diff --git a/CHANGES b/CHANGES index 6a436e1..d66035c 100644 --- a/CHANGES +++ b/CHANGES @@ -27,6 +27,130 @@ new features: new form of FD address with output/input fd numbers +####################### V 1.7.0.0: + +new features: + new address types SCTP-CONNECT and SCTP-LISTEN implement SCTP stream + mode for IPv4 and IPv6; new address options sctp-maxseg and + sctp-nodelay (suggested by David A. Madore; thanks to Jonathan Brannan + for providing an initial patch) + + new address "INTERFACE" for transparent network interface handling + (suggested by Stuart Nicholson) + + added generic socket addresses: SOCKET-CONNECT, SOCKET-LISTEN, + SOCKET-SENDTO, SOCKET-RECVFROM, SOCKET-RECV, SOCKET-DATAGRAM allow + protocol independent socket handling; all parameters are explicitely + specified as numbers or hex data + + added address options ioctl-void, ioctl-int, ioctl-intp, ioctl-string, + ioctl-bin for generic ioctl() calls. + + added address options setsockopt-int, setsockopt-bin, and + setsockopt-string for generic setsockopt() calls + + option so-type now only affects the socket() and socketpair() calls, + not the name resolution. so-type and so-prototype can now be applied to + all socket based addresses. + + new address option "escape" allows to break a socat instance even when + raw terminal mode prevents ^C etc. (feature suggested by Guido Trotter) + + socat sets environment variables SOCAT_VERSION, SOCAT_PID, SOCAT_PPID + for use in executed scripts + + socat sets environment variables SOCAT_SOCKADDR, SOCAT_SOCKPORT, + SOCAT_PEERADDR, SOCAT_PEERPORT in LISTEN type addresses (feature + suggested by Ed Sawicki) + + socat receives all ancillary messages with each received packet on + datagram related addresses. The messages are logged in raw form with + debug level, and broken down with info level. note: each type of + ancillary message must be enabled by appropriate address options. + + socat provides the contents of ancillary messages received on RECVFROM + addresses in appropriate environment variables: + SOCAT_TIMESTAMP, SOCAT_IP_DSTADDR, SOCAT_IP_IF, SOCAT_IP_LOCADDR, + SOCAT_IP_OPTIONS, SOCAT_IP_TOS, SOCAT_IP_TTL, SOCAT_IPV6_DSTADDR, + SOCAT_IPV6_HOPLIMIT, SOCAT_IPV6_TCLASS + + the following address options were added to enable ancillary messages: + so-timestamp, ip-pktinfo (not BSD), ip-recvdstaddr (BSD), ip-recverr, + ip-recvif (BSD), ip-recvopts, ip-recvtos, ip-recvttl, ipv6-recvdstopts, + ipv6-recverr, ipv6-recvhoplimit, ipv6-recvhopopts, ipv6-recvpathmtu, + ipv6-recvpktinfo, ipv6-recvrthdr, ipv6-recvtclass + + new address options ipv6-tclass and ipv6-unicast-hops set the related + socket options. + + STREAMS (UNIX System V STREAMS) can be configured with the new address + options i-pop-all and i-push (thanks to Michal Rysavy for providing a + patch) + +corrections: + some raw IP and UNIX datagram modes failed on BSD systems + + when UDP-LISTEN continued to listen after packet dropped by, e.g., + range option, the old listen socket would not be closed but a new one + created. open sockets could accumulate. + + there was a bug in ip*-recv with bind option: it did not bind, and + with the first received packet an error occurred: + socket_init(): unknown address family 0 + test: RAWIP4RECVBIND + + RECVFROM addresses with FORK option hung after processing the first + packet. test: UDP4RECVFROM_FORK + + corrected a few mistakes that caused compiler warnings on 64bit hosts + (thanks to Jonathan Brannan e.a. for providing a patch) + + EXEC and SYSTEM with stderr injected socat messages into the data + stream. test: EXECSTDERRLOG + + when the EXEC address got a string with consecutive spaces it created + additional empty arguments (thanks to Olivier Hervieu for reporting + this bug). test: EXECSPACES + + in ignoreeof polling mode socat also blocked data transfer in the other + direction during the 1s wait intervalls (thanks to Jorgen Cederlof for + reporting this bug) + + corrected alphabetical order of options (proxy-auth) + + some minor corrections + + improved test.sh script: more stable timing, corrections for BSD + + replaced the select() calls by poll() to cleanly fix the problems with + many file descriptors already open + + socat option -lf did not log to file but to stderr + + socat did not compile on Solaris when configured without termios + feature (thanks to Pavan Gadi for reporting this bug) + +porting: + socat compiles and runs on AIX with gcc (thanks to Andi Mather for his + help) + + socat compiles and runs on Cygwin (thanks to Jan Just Keijser for his + help) + + socat compiles and runs on HP-UX with gcc (thanks to Michal Rysavy for + his help) + + socat compiles and runs on MacOS X (thanks to Camillo Lugaresi for his + help) + +further changes: + filan -s prefixes output with FD number if more than one FD + + Makefile now supports datarootdir (thanks to Camillo Lugaresi for + providing the patch) + + cleanup in xio-unix.c + ####################### V 1.6.0.1: new features: diff --git a/Config/Makefile.AIX-5-3 b/Config/Makefile.AIX-5-3 new file mode 100644 index 0000000..e07ac40 --- /dev/null +++ b/Config/Makefile.AIX-5-3 @@ -0,0 +1,195 @@ +# source: Makefile.in +# Copyright Gerhard Rieger 2001-2008 +# Published under the GNU General Public License V.2, see file COPYING + +# note: @...@ forms are filled in by configure script + +SHELL = /bin/sh +AR = ar +RANLIB = ranlib + +.SUFFIXES: .c .o + +prefix = /usr/local +exec_prefix = ${prefix} + +BINDEST = ${exec_prefix}/bin + +datarootdir = ${prefix}/share +MANDEST = ${datarootdir}/man + +srcdir = . + + +CC = cc -qlanglvl=extc89 +CCOPTS = $(CCOPT) + +SYSDEFS = +CPPFLAGS = -I. +#0 INCLS = -I. @V_INCL@ +DEFS = -DHAVE_CONFIG_H +LIBS = -lbsd -lssl -lcrypto +LDFLAGS = + +INSTALL = ./install-sh -c + +#OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) + + +#0 CFLAGS = -O $(CCOPTS) $(DEFS) $(INCLS) +CFLAGS = -O $(CCOPTS) $(DEFS) $(CPPFLAGS) +CLIBS = $(LIBS) +#CLIBS = $(LIBS) -lm -lefence +XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \ + xiosignal.c xiosigchld.c xioread.c xiowrite.c \ + xiolayer.c xioshutdown.c xioclose.c xioexit.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-socket.c xio-interface.c xio-listen.c xio-unix.c \ + xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \ + xio-sctp.c xio-rawip.c \ + xio-socks.c xio-proxy.c xio-udp.c \ + xio-rawip.c \ + xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ + xio-pty.c xio-openssl.c xio-streams.c\ + xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c +XIOOBJS = $(XIOSRCS:.c=.o) +UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c filan.c sycls.c sslcls.c +UTLOBJS = $(UTLSRCS:.c=.o) +CFILES = $(XIOSRCS) $(UTLSRCS) socat.c procan_main.c filan_main.c +OFILES = $(CFILES:.c=.o) +PROGS = socat procan filan + +HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h compat.h \ + xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.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-interface.h xio-listen.h xio-unix.h \ + xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \ + xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \ + xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ + xio-system.h xio-termios.h xio-readline.h \ + xio-pty.h xio-openssl.h xio-streams.h \ + xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h + + +DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo 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 doc/socat-genericsocket.html +SHFILES = daemon.sh mail.sh ftp.sh readline.sh +TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \ + proxy.sh socks4a-echo.sh testcert.conf +OSFILES = Config/Makefile.Linux-2-6-24 Config/config.Linux-2-6-24.h \ + Config/Makefile.SunOS-5-10 Config/config.SunOS-5-10.h \ + Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \ + Config/Makefile.NetBSD-4-0 Config/config.NetBSD-4-0.h \ + Config/Makefile.OpenBSD-4-3 Config/config.OpenBSD-4-3.h + +all: progs doc + +scmclean: gitclean + +gitclean: distclean docclean + rm -f Makefile.bak configure + +doc: doc/socat.1 doc/socat.html + +docclean: + rm -f doc/socat.1 doc/socat.html + +doc/socat.1: doc/socat.yo + yodl2man -o $@ $+ + +doc/socat.html: doc/socat.yo + cd doc; yodl2html -o socat.html socat.yo; cd .. + +progs: $(PROGS) + +depend: $(CFILES) $(HFILES) + makedepend $(SYSDEFS) $(CFILES) + +socat: socat.o libxio.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS) + +PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o +procan: $(PROCAN_OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(PROCAN_OBJS) $(CLIBS) + +filan: filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o $(CLIBS) + +libxio.a: $(XIOOBJS) $(UTLOBJS) + $(AR) r $@ $(XIOOBJS) $(UTLOBJS) + $(RANLIB) $@ + +doc: doc/xio.help +# + +strip: progs + strip $(PROGS) + +install: progs $(srcdir)/doc/socat.1 + mkdir -p $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST) + mkdir -p $(DESTDIR)$(MANDEST)/man1 + $(INSTALL) -m 644 $(srcdir)/doc/socat.1 $(DESTDIR)$(MANDEST)/man1/ + +uninstall: + rm -f $(DESTDIR)$(BINDEST)/socat + rm -f $(DESTDIR)$(BINDEST)/procan + rm -f $(DESTDIR)$(BINDEST)/filan + rm -f $(DESTDIR)$(MANDEST)/man1/socat.1 + +# make a GNU-zipped tar ball of the source files +dist: socat.tar.gz socat.tar.bz2 + +socat.tar.gz: socat.tar + gzip -9 socat.tar.gz + +socat.tar.bz2: socat.tar + bzip2 -9 socat.tar.bz2 + +VERSION = `sed 's/"//g' 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 + if [ ! -d $(TARDIR) ]; then mkdir $(TARDIR); fi + tar cf - $+ |(cd $(TARDIR); tar xf -) + tar cvf socat.tar $(TARDIR) + rm -f $(TARDIR)/COPYING # write protected + rm -r $(TARDIR) + +clean: + rm -f *.o libxio.a socat procan filan \ + socat.tar socat.tar.Z socat.tar.gz socat.tar.bz2 \ + socat.out compile.log test.log + +# remove all files that are generated from the original socat distribution +# note that Makefile is also removed, so you have to start with ./configure +# again +distclean: clean + rm -f config.status config.cache config.log config.h Makefile + rm -rf autom4te.cache + +info: socat + uname -a >socat.out + ./socat -V >>socat.out + ./socat -hh >>socat.out + +# perform some tests on socat +test: progs + ./test.sh + +cert: + # prepare critical files with correct permissions to avoid race cond + >cert.key + >cert.pem + chmod 600 cert.key cert.pem + # generate a private key + openssl genrsa -out cert.key 1024 + # generate a self signed cert + openssl req -new -key cert.key -x509 -days 3653 -out cert.crt + # ...enter fields + # generate the pem file + cat cert.key cert.crt >cert.pem + #echo use cert.pem on requestors side, i.e. with option cert=cert.pem + #echo use cert.crt on checkers side, i.e. with option cafile=cert.crt diff --git a/Config/Makefile.Cygwin-1-5-25 b/Config/Makefile.Cygwin-1-5-25 new file mode 100644 index 0000000..c152950 --- /dev/null +++ b/Config/Makefile.Cygwin-1-5-25 @@ -0,0 +1,195 @@ +# source: Makefile.in +# Copyright Gerhard Rieger 2001-2008 +# Published under the GNU General Public License V.2, see file COPYING + +# note: @...@ forms are filled in by configure script + +SHELL = /bin/sh +AR = ar +RANLIB = ranlib + +.SUFFIXES: .c .o + +prefix = /usr/local +exec_prefix = ${prefix} + +BINDEST = ${exec_prefix}/bin + +datarootdir = ${prefix}/share +MANDEST = ${datarootdir}/man + +srcdir = . + + +CC = gcc +CCOPTS = $(CCOPT) -Wall -Wno-parentheses + +SYSDEFS = +CPPFLAGS = -I. +#0 INCLS = -I. @V_INCL@ +DEFS = -DHAVE_CONFIG_H +LIBS = -lwrap -lutil -lreadline -lssl -lcrypto +LDFLAGS = + +INSTALL = /usr/bin/install -c + +#OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) + + +#0 CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(INCLS) +CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(CPPFLAGS) +CLIBS = $(LIBS) +#CLIBS = $(LIBS) -lm -lefence +XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \ + xiosignal.c xiosigchld.c xioread.c xiowrite.c \ + xiolayer.c xioshutdown.c xioclose.c xioexit.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-socket.c xio-interface.c xio-listen.c xio-unix.c \ + xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \ + xio-sctp.c xio-rawip.c \ + xio-socks.c xio-proxy.c xio-udp.c \ + xio-rawip.c \ + xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ + xio-pty.c xio-openssl.c xio-streams.c\ + xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c +XIOOBJS = $(XIOSRCS:.c=.o) +UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c filan.c sycls.c sslcls.c +UTLOBJS = $(UTLSRCS:.c=.o) +CFILES = $(XIOSRCS) $(UTLSRCS) socat.c procan_main.c filan_main.c +OFILES = $(CFILES:.c=.o) +PROGS = socat procan filan + +HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h compat.h \ + xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.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-interface.h xio-listen.h xio-unix.h \ + xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \ + xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \ + xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ + xio-system.h xio-termios.h xio-readline.h \ + xio-pty.h xio-openssl.h xio-streams.h \ + xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h + + +DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo 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 doc/socat-genericsocket.html +SHFILES = daemon.sh mail.sh ftp.sh readline.sh +TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \ + proxy.sh socks4a-echo.sh testcert.conf +OSFILES = Config/Makefile.Linux-2-6-24 Config/config.Linux-2-6-24.h \ + Config/Makefile.SunOS-5-10 Config/config.SunOS-5-10.h \ + Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \ + Config/Makefile.NetBSD-4-0 Config/config.NetBSD-4-0.h \ + Config/Makefile.OpenBSD-4-3 Config/config.OpenBSD-4-3.h + +all: progs doc + +scmclean: gitclean + +gitclean: distclean docclean + rm -f Makefile.bak configure + +doc: doc/socat.1 doc/socat.html + +docclean: + rm -f doc/socat.1 doc/socat.html + +doc/socat.1: doc/socat.yo + yodl2man -o $@ $+ + +doc/socat.html: doc/socat.yo + cd doc; yodl2html -o socat.html socat.yo; cd .. + +progs: $(PROGS) + +depend: $(CFILES) $(HFILES) + makedepend $(SYSDEFS) $(CFILES) + +socat: socat.o libxio.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS) + +PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o +procan: $(PROCAN_OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(PROCAN_OBJS) $(CLIBS) + +filan: filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o $(CLIBS) + +libxio.a: $(XIOOBJS) $(UTLOBJS) + $(AR) r $@ $(XIOOBJS) $(UTLOBJS) + $(RANLIB) $@ + +doc: doc/xio.help +# + +strip: progs + strip $(PROGS) + +install: progs $(srcdir)/doc/socat.1 + mkdir -p $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST) + mkdir -p $(DESTDIR)$(MANDEST)/man1 + $(INSTALL) -m 644 $(srcdir)/doc/socat.1 $(DESTDIR)$(MANDEST)/man1/ + +uninstall: + rm -f $(DESTDIR)$(BINDEST)/socat + rm -f $(DESTDIR)$(BINDEST)/procan + rm -f $(DESTDIR)$(BINDEST)/filan + rm -f $(DESTDIR)$(MANDEST)/man1/socat.1 + +# make a GNU-zipped tar ball of the source files +dist: socat.tar.gz socat.tar.bz2 + +socat.tar.gz: socat.tar + gzip -9 socat.tar.gz + +socat.tar.bz2: socat.tar + bzip2 -9 socat.tar.bz2 + +VERSION = `sed 's/"//g' 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 + if [ ! -d $(TARDIR) ]; then mkdir $(TARDIR); fi + tar cf - $+ |(cd $(TARDIR); tar xf -) + tar cvf socat.tar $(TARDIR) + rm -f $(TARDIR)/COPYING # write protected + rm -r $(TARDIR) + +clean: + rm -f *.o libxio.a socat procan filan \ + socat.tar socat.tar.Z socat.tar.gz socat.tar.bz2 \ + socat.out compile.log test.log + +# remove all files that are generated from the original socat distribution +# note that Makefile is also removed, so you have to start with ./configure +# again +distclean: clean + rm -f config.status config.cache config.log config.h Makefile + rm -rf autom4te.cache + +info: socat + uname -a >socat.out + ./socat -V >>socat.out + ./socat -hh >>socat.out + +# perform some tests on socat +test: progs + ./test.sh + +cert: + # prepare critical files with correct permissions to avoid race cond + >cert.key + >cert.pem + chmod 600 cert.key cert.pem + # generate a private key + openssl genrsa -out cert.key 1024 + # generate a self signed cert + openssl req -new -key cert.key -x509 -days 3653 -out cert.crt + # ...enter fields + # generate the pem file + cat cert.key cert.crt >cert.pem + #echo use cert.pem on requestors side, i.e. with option cert=cert.pem + #echo use cert.crt on checkers side, i.e. with option cafile=cert.crt diff --git a/Config/Makefile.FreeBSD-6-1 b/Config/Makefile.FreeBSD-6-1 index 0d8faae..2cd0bfe 100644 --- a/Config/Makefile.FreeBSD-6-1 +++ b/Config/Makefile.FreeBSD-6-1 @@ -1,5 +1,5 @@ -# source: Makefile.FreeBSD-6-1 -# Copyright Gerhard Rieger 2001-2006 +# source: Makefile.in +# Copyright Gerhard Rieger 2001-2008 # Published under the GNU General Public License V.2, see file COPYING # note: @...@ forms are filled in by configure script @@ -15,7 +15,8 @@ exec_prefix = ${prefix} BINDEST = ${exec_prefix}/bin -MANDEST = ${prefix}/man +datarootdir = ${prefix}/share +MANDEST = ${datarootdir}/man srcdir = . @@ -27,7 +28,7 @@ SYSDEFS = -D_LONGLONG CPPFLAGS = -I. #0 INCLS = -I. @V_INCL@ DEFS = -DHAVE_CONFIG_H -LIBS = -lwrap -lutil -lreadline -lssl +LIBS = -lwrap -lutil -lreadline -lssl LDFLAGS = INSTALL = /usr/bin/install -c @@ -44,13 +45,16 @@ XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \ xiolayer.c xioshutdown.c xioclose.c xioexit.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-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-interface.c xio-listen.c xio-unix.c \ + xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \ + xio-sctp.c xio-rawip.c \ + xio-socks.c xio-proxy.c xio-udp.c \ xio-rawip.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-streams.c\ xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c XIOOBJS = $(XIOSRCS:.c=.o) -UTLSRCS = error.c dalan.c procan.c hostan.c fdname.c sysutils.c utils.c nestlex.c filan.c sycls.c sslcls.c +UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c filan.c sycls.c sslcls.c UTLOBJS = $(UTLSRCS:.c=.o) CFILES = $(XIOSRCS) $(UTLSRCS) socat.c procan_main.c filan_main.c OFILES = $(CFILES:.c=.o) @@ -59,29 +63,43 @@ PROGS = socat procan filan HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h compat.h \ xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.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-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-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h \ + xio-socket.h xio-interface.h xio-listen.h xio-unix.h \ + xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \ + xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \ + xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ xio-system.h xio-termios.h xio-readline.h \ - xio-pty.h xio-openssl.h \ + xio-pty.h xio-openssl.h xio-streams.h \ xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h -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 +DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo 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 TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \ proxy.sh socks4a-echo.sh testcert.conf -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.SunOS-5-8 Config/config.SunOS-5-8.h \ - Config/Makefile.HP-UX-B-11-11 Config/config.HP-UX-B-11-11.h \ +OSFILES = Config/Makefile.Linux-2-6-24 Config/config.Linux-2-6-24.h \ + Config/Makefile.SunOS-5-10 Config/config.SunOS-5-10.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.OpenBSD-3-8 Config/config.OpenBSD-3-8.h \ - Config/Makefile.Tru64-5-1B Config/config.Tru64-5-1B.h + Config/Makefile.NetBSD-4-0 Config/config.NetBSD-4-0.h \ + Config/Makefile.OpenBSD-4-3 Config/config.OpenBSD-4-3.h +all: progs doc -all: progs +scmclean: gitclean + +gitclean: distclean docclean + rm -f Makefile.bak configure + +doc: doc/socat.1 doc/socat.html + +docclean: + rm -f doc/socat.1 doc/socat.html + +doc/socat.1: doc/socat.yo + yodl2man -o $@ $+ + +doc/socat.html: doc/socat.yo + cd doc; yodl2html -o socat.html socat.yo; cd .. progs: $(PROGS) @@ -91,7 +109,7 @@ depend: $(CFILES) $(HFILES) socat: socat.o libxio.a $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS) -PROCAN_OBJS=procan_main.o procan.o hostan.o error.o sycls.o sysutils.o utils.o +PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o procan: $(PROCAN_OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(PROCAN_OBJS) $(CLIBS) @@ -108,17 +126,17 @@ doc: doc/xio.help strip: progs strip $(PROGS) -install: progs doc/socat.1 +install: progs $(srcdir)/doc/socat.1 mkdir -p $(DESTDIR)$(BINDEST) $(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST) $(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST) $(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST) mkdir -p $(DESTDIR)$(MANDEST)/man1 - $(INSTALL) -m 644 doc/socat.1 $(DESTDIR)$(MANDEST)/man1/ + $(INSTALL) -m 644 $(srcdir)/doc/socat.1 $(DESTDIR)$(MANDEST)/man1/ uninstall: rm -f $(DESTDIR)$(BINDEST)/socat - rm -f $(DESTDIR)$(BINDEST)/procat + rm -f $(DESTDIR)$(BINDEST)/procan rm -f $(DESTDIR)$(BINDEST)/filan rm -f $(DESTDIR)$(MANDEST)/man1/socat.1 diff --git a/Config/Makefile.Linux-2-6-24 b/Config/Makefile.Linux-2-6-24 new file mode 100644 index 0000000..58e0608 --- /dev/null +++ b/Config/Makefile.Linux-2-6-24 @@ -0,0 +1,195 @@ +# source: Makefile.in +# Copyright Gerhard Rieger 2001-2008 +# Published under the GNU General Public License V.2, see file COPYING + +# note: @...@ forms are filled in by configure script + +SHELL = /bin/sh +AR = ar +RANLIB = ranlib + +.SUFFIXES: .c .o + +prefix = /usr/local +exec_prefix = ${prefix} + +BINDEST = ${exec_prefix}/bin + +datarootdir = ${prefix}/share +MANDEST = ${datarootdir}/man + +srcdir = . + + +CC = gcc +CCOPTS = $(CCOPT) -Wall -Wno-parentheses + +SYSDEFS = +CPPFLAGS = -I. +#0 INCLS = -I. @V_INCL@ +DEFS = -DHAVE_CONFIG_H +LIBS = -lwrap -lutil -lreadline -lssl +LDFLAGS = + +INSTALL = /usr/bin/install -c + +#OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) + + +#0 CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(INCLS) +CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(CPPFLAGS) +CLIBS = $(LIBS) +#CLIBS = $(LIBS) -lm -lefence +XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \ + xiosignal.c xiosigchld.c xioread.c xiowrite.c \ + xiolayer.c xioshutdown.c xioclose.c xioexit.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-socket.c xio-interface.c xio-listen.c xio-unix.c \ + xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \ + xio-sctp.c xio-rawip.c \ + xio-socks.c xio-proxy.c xio-udp.c \ + xio-rawip.c \ + xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ + xio-pty.c xio-openssl.c xio-streams.c\ + xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c +XIOOBJS = $(XIOSRCS:.c=.o) +UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c filan.c sycls.c sslcls.c +UTLOBJS = $(UTLSRCS:.c=.o) +CFILES = $(XIOSRCS) $(UTLSRCS) socat.c procan_main.c filan_main.c +OFILES = $(CFILES:.c=.o) +PROGS = socat procan filan + +HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h compat.h \ + xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.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-interface.h xio-listen.h xio-unix.h \ + xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \ + xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \ + xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ + xio-system.h xio-termios.h xio-readline.h \ + xio-pty.h xio-openssl.h xio-streams.h \ + xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h + + +DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo 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 +TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \ + proxy.sh socks4a-echo.sh testcert.conf +OSFILES = Config/Makefile.Linux-2-6-24 Config/config.Linux-2-6-24.h \ + Config/Makefile.SunOS-5-10 Config/config.SunOS-5-10.h \ + Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \ + Config/Makefile.NetBSD-4-0 Config/config.NetBSD-4-0.h \ + Config/Makefile.OpenBSD-4-3 Config/config.OpenBSD-4-3.h + +all: progs doc + +scmclean: gitclean + +gitclean: distclean docclean + rm -f Makefile.bak configure + +doc: doc/socat.1 doc/socat.html + +docclean: + rm -f doc/socat.1 doc/socat.html + +doc/socat.1: doc/socat.yo + yodl2man -o $@ $+ + +doc/socat.html: doc/socat.yo + cd doc; yodl2html -o socat.html socat.yo; cd .. + +progs: $(PROGS) + +depend: $(CFILES) $(HFILES) + makedepend $(SYSDEFS) $(CFILES) + +socat: socat.o libxio.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS) + +PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o +procan: $(PROCAN_OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(PROCAN_OBJS) $(CLIBS) + +filan: filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o $(CLIBS) + +libxio.a: $(XIOOBJS) $(UTLOBJS) + $(AR) r $@ $(XIOOBJS) $(UTLOBJS) + $(RANLIB) $@ + +doc: doc/xio.help +# + +strip: progs + strip $(PROGS) + +install: progs $(srcdir)/doc/socat.1 + mkdir -p $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST) + mkdir -p $(DESTDIR)$(MANDEST)/man1 + $(INSTALL) -m 644 $(srcdir)/doc/socat.1 $(DESTDIR)$(MANDEST)/man1/ + +uninstall: + rm -f $(DESTDIR)$(BINDEST)/socat + rm -f $(DESTDIR)$(BINDEST)/procan + rm -f $(DESTDIR)$(BINDEST)/filan + rm -f $(DESTDIR)$(MANDEST)/man1/socat.1 + +# make a GNU-zipped tar ball of the source files +dist: socat.tar.gz socat.tar.bz2 + +socat.tar.gz: socat.tar + gzip -9 socat.tar.gz + +socat.tar.bz2: socat.tar + bzip2 -9 socat.tar.bz2 + +VERSION = `sed 's/"//g' 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 + if [ ! -d $(TARDIR) ]; then mkdir $(TARDIR); fi + tar cf - $+ |(cd $(TARDIR); tar xf -) + tar cvf socat.tar $(TARDIR) + rm -f $(TARDIR)/COPYING # write protected + rm -r $(TARDIR) + +clean: + rm -f *.o libxio.a socat procan filan \ + socat.tar socat.tar.Z socat.tar.gz socat.tar.bz2 \ + socat.out compile.log test.log + +# remove all files that are generated from the original socat distribution +# note that Makefile is also removed, so you have to start with ./configure +# again +distclean: clean + rm -f config.status config.cache config.log config.h Makefile + rm -rf autom4te.cache + +info: socat + uname -a >socat.out + ./socat -V >>socat.out + ./socat -hh >>socat.out + +# perform some tests on socat +test: progs + ./test.sh + +cert: + # prepare critical files with correct permissions to avoid race cond + >cert.key + >cert.pem + chmod 600 cert.key cert.pem + # generate a private key + openssl genrsa -out cert.key 1024 + # generate a self signed cert + openssl req -new -key cert.key -x509 -days 3653 -out cert.crt + # ...enter fields + # generate the pem file + cat cert.key cert.crt >cert.pem + #echo use cert.pem on requestors side, i.e. with option cert=cert.pem + #echo use cert.crt on checkers side, i.e. with option cafile=cert.crt diff --git a/Config/Makefile.MacOSX-10-5 b/Config/Makefile.MacOSX-10-5 new file mode 100644 index 0000000..43a8f72 --- /dev/null +++ b/Config/Makefile.MacOSX-10-5 @@ -0,0 +1,195 @@ +# source: Makefile.in +# Copyright Gerhard Rieger 2001-2008 +# Published under the GNU General Public License V.2, see file COPYING + +# note: @...@ forms are filled in by configure script + +SHELL = /bin/sh +AR = ar +RANLIB = ranlib + +.SUFFIXES: .c .o + +prefix = /usr/local +exec_prefix = ${prefix} + +BINDEST = ${exec_prefix}/bin + +datarootdir = ${prefix}/share +MANDEST = ${datarootdir}/man + +srcdir = . + + +CC = gcc +CCOPTS = $(CCOPT) -Wall -Wno-parentheses + +SYSDEFS = -D__DYNAMIC__ +CPPFLAGS = -I. -I/usr/local/include +#0 INCLS = -I. @V_INCL@ +DEFS = -DHAVE_CONFIG_H +LIBS = -lwrap -lutil -lresolv -lreadline -lssl -lcrypto +LDFLAGS = + +INSTALL = /usr/bin/install -c + +#OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) + + +#0 CFLAGS = -O -D_GNU_SOURCE -L/usr/local/lib $(CCOPTS) $(DEFS) $(INCLS) +CFLAGS = -O -D_GNU_SOURCE -L/usr/local/lib $(CCOPTS) $(DEFS) $(CPPFLAGS) +CLIBS = $(LIBS) +#CLIBS = $(LIBS) -lm -lefence +XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \ + xiosignal.c xiosigchld.c xioread.c xiowrite.c \ + xiolayer.c xioshutdown.c xioclose.c xioexit.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-socket.c xio-interface.c xio-listen.c xio-unix.c \ + xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \ + xio-sctp.c xio-rawip.c \ + xio-socks.c xio-proxy.c xio-udp.c \ + xio-rawip.c \ + xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ + xio-pty.c xio-openssl.c xio-streams.c\ + xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c +XIOOBJS = $(XIOSRCS:.c=.o) +UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c filan.c sycls.c sslcls.c +UTLOBJS = $(UTLSRCS:.c=.o) +CFILES = $(XIOSRCS) $(UTLSRCS) socat.c procan_main.c filan_main.c +OFILES = $(CFILES:.c=.o) +PROGS = socat procan filan + +HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h compat.h \ + xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.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-interface.h xio-listen.h xio-unix.h \ + xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \ + xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \ + xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ + xio-system.h xio-termios.h xio-readline.h \ + xio-pty.h xio-openssl.h xio-streams.h \ + xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h + + +DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo 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 doc/socat-genericsocket.html +SHFILES = daemon.sh mail.sh ftp.sh readline.sh +TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \ + proxy.sh socks4a-echo.sh testcert.conf +OSFILES = Config/Makefile.Linux-2-6-24 Config/config.Linux-2-6-24.h \ + Config/Makefile.SunOS-5-10 Config/config.SunOS-5-10.h \ + Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \ + Config/Makefile.NetBSD-4-0 Config/config.NetBSD-4-0.h \ + Config/Makefile.OpenBSD-4-3 Config/config.OpenBSD-4-3.h + +all: progs doc + +scmclean: gitclean + +gitclean: distclean docclean + rm -f Makefile.bak configure + +doc: doc/socat.1 doc/socat.html + +docclean: + rm -f doc/socat.1 doc/socat.html + +doc/socat.1: doc/socat.yo + yodl2man -o $@ $+ + +doc/socat.html: doc/socat.yo + cd doc; yodl2html -o socat.html socat.yo; cd .. + +progs: $(PROGS) + +depend: $(CFILES) $(HFILES) + makedepend $(SYSDEFS) $(CFILES) + +socat: socat.o libxio.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS) + +PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o +procan: $(PROCAN_OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(PROCAN_OBJS) $(CLIBS) + +filan: filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o $(CLIBS) + +libxio.a: $(XIOOBJS) $(UTLOBJS) + $(AR) r $@ $(XIOOBJS) $(UTLOBJS) + $(RANLIB) $@ + +doc: doc/xio.help +# + +strip: progs + strip $(PROGS) + +install: progs $(srcdir)/doc/socat.1 + mkdir -p $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST) + mkdir -p $(DESTDIR)$(MANDEST)/man1 + $(INSTALL) -m 644 $(srcdir)/doc/socat.1 $(DESTDIR)$(MANDEST)/man1/ + +uninstall: + rm -f $(DESTDIR)$(BINDEST)/socat + rm -f $(DESTDIR)$(BINDEST)/procan + rm -f $(DESTDIR)$(BINDEST)/filan + rm -f $(DESTDIR)$(MANDEST)/man1/socat.1 + +# make a GNU-zipped tar ball of the source files +dist: socat.tar.gz socat.tar.bz2 + +socat.tar.gz: socat.tar + gzip -9 socat.tar.gz + +socat.tar.bz2: socat.tar + bzip2 -9 socat.tar.bz2 + +VERSION = `sed 's/"//g' 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 + if [ ! -d $(TARDIR) ]; then mkdir $(TARDIR); fi + tar cf - $+ |(cd $(TARDIR); tar xf -) + tar cvf socat.tar $(TARDIR) + rm -f $(TARDIR)/COPYING # write protected + rm -r $(TARDIR) + +clean: + rm -f *.o libxio.a socat procan filan \ + socat.tar socat.tar.Z socat.tar.gz socat.tar.bz2 \ + socat.out compile.log test.log + +# remove all files that are generated from the original socat distribution +# note that Makefile is also removed, so you have to start with ./configure +# again +distclean: clean + rm -f config.status config.cache config.log config.h Makefile + rm -rf autom4te.cache + +info: socat + uname -a >socat.out + ./socat -V >>socat.out + ./socat -hh >>socat.out + +# perform some tests on socat +test: progs + ./test.sh + +cert: + # prepare critical files with correct permissions to avoid race cond + >cert.key + >cert.pem + chmod 600 cert.key cert.pem + # generate a private key + openssl genrsa -out cert.key 1024 + # generate a self signed cert + openssl req -new -key cert.key -x509 -days 3653 -out cert.crt + # ...enter fields + # generate the pem file + cat cert.key cert.crt >cert.pem + #echo use cert.pem on requestors side, i.e. with option cert=cert.pem + #echo use cert.crt on checkers side, i.e. with option cafile=cert.crt diff --git a/Config/Makefile.NetBSD-4-0 b/Config/Makefile.NetBSD-4-0 new file mode 100644 index 0000000..5f6256a --- /dev/null +++ b/Config/Makefile.NetBSD-4-0 @@ -0,0 +1,195 @@ +# source: Makefile.in +# Copyright Gerhard Rieger 2001-2008 +# Published under the GNU General Public License V.2, see file COPYING + +# note: @...@ forms are filled in by configure script + +SHELL = /bin/sh +AR = ar +RANLIB = ranlib + +.SUFFIXES: .c .o + +prefix = /usr/local +exec_prefix = ${prefix} + +BINDEST = ${exec_prefix}/bin + +datarootdir = ${prefix}/share +MANDEST = ${datarootdir}/man + +srcdir = . + + +CC = gcc +CCOPTS = $(CCOPT) -Wall -Wno-parentheses + +SYSDEFS = +CPPFLAGS = -I. +#0 INCLS = -I. @V_INCL@ +DEFS = -DHAVE_CONFIG_H +LIBS = -lwrap -lutil -lssl +LDFLAGS = + +INSTALL = /usr/bin/install -c + +#OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) + + +#0 CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(INCLS) +CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(CPPFLAGS) +CLIBS = $(LIBS) +#CLIBS = $(LIBS) -lm -lefence +XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \ + xiosignal.c xiosigchld.c xioread.c xiowrite.c \ + xiolayer.c xioshutdown.c xioclose.c xioexit.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-socket.c xio-interface.c xio-listen.c xio-unix.c \ + xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \ + xio-sctp.c xio-rawip.c \ + xio-socks.c xio-proxy.c xio-udp.c \ + xio-rawip.c \ + xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ + xio-pty.c xio-openssl.c xio-streams.c\ + xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c +XIOOBJS = $(XIOSRCS:.c=.o) +UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c filan.c sycls.c sslcls.c +UTLOBJS = $(UTLSRCS:.c=.o) +CFILES = $(XIOSRCS) $(UTLSRCS) socat.c procan_main.c filan_main.c +OFILES = $(CFILES:.c=.o) +PROGS = socat procan filan + +HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h compat.h \ + xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.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-interface.h xio-listen.h xio-unix.h \ + xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \ + xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \ + xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ + xio-system.h xio-termios.h xio-readline.h \ + xio-pty.h xio-openssl.h xio-streams.h \ + xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h + + +DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo 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 +TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \ + proxy.sh socks4a-echo.sh testcert.conf +OSFILES = Config/Makefile.Linux-2-6-24 Config/config.Linux-2-6-24.h \ + Config/Makefile.SunOS-5-10 Config/config.SunOS-5-10.h \ + Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \ + Config/Makefile.NetBSD-4-0 Config/config.NetBSD-4-0.h \ + Config/Makefile.OpenBSD-4-3 Config/config.OpenBSD-4-3.h + +all: progs doc + +scmclean: gitclean + +gitclean: distclean docclean + rm -f Makefile.bak configure + +doc: doc/socat.1 doc/socat.html + +docclean: + rm -f doc/socat.1 doc/socat.html + +doc/socat.1: doc/socat.yo + yodl2man -o $@ $+ + +doc/socat.html: doc/socat.yo + cd doc; yodl2html -o socat.html socat.yo; cd .. + +progs: $(PROGS) + +depend: $(CFILES) $(HFILES) + makedepend $(SYSDEFS) $(CFILES) + +socat: socat.o libxio.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS) + +PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o +procan: $(PROCAN_OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(PROCAN_OBJS) $(CLIBS) + +filan: filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o $(CLIBS) + +libxio.a: $(XIOOBJS) $(UTLOBJS) + $(AR) r $@ $(XIOOBJS) $(UTLOBJS) + $(RANLIB) $@ + +doc: doc/xio.help +# + +strip: progs + strip $(PROGS) + +install: progs $(srcdir)/doc/socat.1 + mkdir -p $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST) + mkdir -p $(DESTDIR)$(MANDEST)/man1 + $(INSTALL) -m 644 $(srcdir)/doc/socat.1 $(DESTDIR)$(MANDEST)/man1/ + +uninstall: + rm -f $(DESTDIR)$(BINDEST)/socat + rm -f $(DESTDIR)$(BINDEST)/procan + rm -f $(DESTDIR)$(BINDEST)/filan + rm -f $(DESTDIR)$(MANDEST)/man1/socat.1 + +# make a GNU-zipped tar ball of the source files +dist: socat.tar.gz socat.tar.bz2 + +socat.tar.gz: socat.tar + gzip -9 socat.tar.gz + +socat.tar.bz2: socat.tar + bzip2 -9 socat.tar.bz2 + +VERSION = `sed 's/"//g' 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 + if [ ! -d $(TARDIR) ]; then mkdir $(TARDIR); fi + tar cf - $+ |(cd $(TARDIR); tar xf -) + tar cvf socat.tar $(TARDIR) + rm -f $(TARDIR)/COPYING # write protected + rm -r $(TARDIR) + +clean: + rm -f *.o libxio.a socat procan filan \ + socat.tar socat.tar.Z socat.tar.gz socat.tar.bz2 \ + socat.out compile.log test.log + +# remove all files that are generated from the original socat distribution +# note that Makefile is also removed, so you have to start with ./configure +# again +distclean: clean + rm -f config.status config.cache config.log config.h Makefile + rm -rf autom4te.cache + +info: socat + uname -a >socat.out + ./socat -V >>socat.out + ./socat -hh >>socat.out + +# perform some tests on socat +test: progs + ./test.sh + +cert: + # prepare critical files with correct permissions to avoid race cond + >cert.key + >cert.pem + chmod 600 cert.key cert.pem + # generate a private key + openssl genrsa -out cert.key 1024 + # generate a self signed cert + openssl req -new -key cert.key -x509 -days 3653 -out cert.crt + # ...enter fields + # generate the pem file + cat cert.key cert.crt >cert.pem + #echo use cert.pem on requestors side, i.e. with option cert=cert.pem + #echo use cert.crt on checkers side, i.e. with option cafile=cert.crt diff --git a/Config/Makefile.OpenBSD-4-3 b/Config/Makefile.OpenBSD-4-3 new file mode 100644 index 0000000..2683fcc --- /dev/null +++ b/Config/Makefile.OpenBSD-4-3 @@ -0,0 +1,195 @@ +# source: Makefile.in +# Copyright Gerhard Rieger 2001-2008 +# Published under the GNU General Public License V.2, see file COPYING + +# note: @...@ forms are filled in by configure script + +SHELL = /bin/sh +AR = ar +RANLIB = ranlib + +.SUFFIXES: .c .o + +prefix = /usr/local +exec_prefix = ${prefix} + +BINDEST = ${exec_prefix}/bin + +datarootdir = ${prefix}/share +MANDEST = ${datarootdir}/man + +srcdir = . + + +CC = gcc +CCOPTS = $(CCOPT) -Wall -Wno-parentheses + +SYSDEFS = -D__GNUC__=3 -D__GNUC_MINOR__=3 -D__GNUC_PATCHLEVEL__=5 +CPPFLAGS = -I. +#0 INCLS = -I. @V_INCL@ +DEFS = -DHAVE_CONFIG_H +LIBS = -lwrap -lutil -lreadline -lcurses -lssl -lcrypto +LDFLAGS = + +INSTALL = /usr/bin/install -c + +#OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) + + +#0 CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(INCLS) +CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(CPPFLAGS) +CLIBS = $(LIBS) +#CLIBS = $(LIBS) -lm -lefence +XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \ + xiosignal.c xiosigchld.c xioread.c xiowrite.c \ + xiolayer.c xioshutdown.c xioclose.c xioexit.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-socket.c xio-interface.c xio-listen.c xio-unix.c \ + xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \ + xio-sctp.c xio-rawip.c \ + xio-socks.c xio-proxy.c xio-udp.c \ + xio-rawip.c \ + xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ + xio-pty.c xio-openssl.c xio-streams.c\ + xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c +XIOOBJS = $(XIOSRCS:.c=.o) +UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c filan.c sycls.c sslcls.c +UTLOBJS = $(UTLSRCS:.c=.o) +CFILES = $(XIOSRCS) $(UTLSRCS) socat.c procan_main.c filan_main.c +OFILES = $(CFILES:.c=.o) +PROGS = socat procan filan + +HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h compat.h \ + xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.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-interface.h xio-listen.h xio-unix.h \ + xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \ + xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \ + xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ + xio-system.h xio-termios.h xio-readline.h \ + xio-pty.h xio-openssl.h xio-streams.h \ + xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h + + +DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo 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 +TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \ + proxy.sh socks4a-echo.sh testcert.conf +OSFILES = Config/Makefile.Linux-2-6-24 Config/config.Linux-2-6-24.h \ + Config/Makefile.SunOS-5-10 Config/config.SunOS-5-10.h \ + Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \ + Config/Makefile.NetBSD-4-0 Config/config.NetBSD-4-0.h \ + Config/Makefile.OpenBSD-4-3 Config/config.OpenBSD-4-3.h + +all: progs doc + +scmclean: gitclean + +gitclean: distclean docclean + rm -f Makefile.bak configure + +doc: doc/socat.1 doc/socat.html + +docclean: + rm -f doc/socat.1 doc/socat.html + +doc/socat.1: doc/socat.yo + yodl2man -o $@ $+ + +doc/socat.html: doc/socat.yo + cd doc; yodl2html -o socat.html socat.yo; cd .. + +progs: $(PROGS) + +depend: $(CFILES) $(HFILES) + makedepend $(SYSDEFS) $(CFILES) + +socat: socat.o libxio.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS) + +PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o +procan: $(PROCAN_OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(PROCAN_OBJS) $(CLIBS) + +filan: filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o $(CLIBS) + +libxio.a: $(XIOOBJS) $(UTLOBJS) + $(AR) r $@ $(XIOOBJS) $(UTLOBJS) + $(RANLIB) $@ + +doc: doc/xio.help +# + +strip: progs + strip $(PROGS) + +install: progs $(srcdir)/doc/socat.1 + mkdir -p $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST) + mkdir -p $(DESTDIR)$(MANDEST)/man1 + $(INSTALL) -m 644 $(srcdir)/doc/socat.1 $(DESTDIR)$(MANDEST)/man1/ + +uninstall: + rm -f $(DESTDIR)$(BINDEST)/socat + rm -f $(DESTDIR)$(BINDEST)/procan + rm -f $(DESTDIR)$(BINDEST)/filan + rm -f $(DESTDIR)$(MANDEST)/man1/socat.1 + +# make a GNU-zipped tar ball of the source files +dist: socat.tar.gz socat.tar.bz2 + +socat.tar.gz: socat.tar + gzip -9 socat.tar.gz + +socat.tar.bz2: socat.tar + bzip2 -9 socat.tar.bz2 + +VERSION = `sed 's/"//g' 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 + if [ ! -d $(TARDIR) ]; then mkdir $(TARDIR); fi + tar cf - $+ |(cd $(TARDIR); tar xf -) + tar cvf socat.tar $(TARDIR) + rm -f $(TARDIR)/COPYING # write protected + rm -r $(TARDIR) + +clean: + rm -f *.o libxio.a socat procan filan \ + socat.tar socat.tar.Z socat.tar.gz socat.tar.bz2 \ + socat.out compile.log test.log + +# remove all files that are generated from the original socat distribution +# note that Makefile is also removed, so you have to start with ./configure +# again +distclean: clean + rm -f config.status config.cache config.log config.h Makefile + rm -rf autom4te.cache + +info: socat + uname -a >socat.out + ./socat -V >>socat.out + ./socat -hh >>socat.out + +# perform some tests on socat +test: progs + ./test.sh + +cert: + # prepare critical files with correct permissions to avoid race cond + >cert.key + >cert.pem + chmod 600 cert.key cert.pem + # generate a private key + openssl genrsa -out cert.key 1024 + # generate a self signed cert + openssl req -new -key cert.key -x509 -days 3653 -out cert.crt + # ...enter fields + # generate the pem file + cat cert.key cert.crt >cert.pem + #echo use cert.pem on requestors side, i.e. with option cert=cert.pem + #echo use cert.crt on checkers side, i.e. with option cafile=cert.crt diff --git a/Config/Makefile.SunOS-5-10 b/Config/Makefile.SunOS-5-10 new file mode 100644 index 0000000..d3d5901 --- /dev/null +++ b/Config/Makefile.SunOS-5-10 @@ -0,0 +1,195 @@ +# source: Makefile.in +# Copyright Gerhard Rieger 2001-2008 +# Published under the GNU General Public License V.2, see file COPYING + +# note: @...@ forms are filled in by configure script + +SHELL = /bin/sh +AR = ar +RANLIB = ranlib + +.SUFFIXES: .c .o + +prefix = /usr/local +exec_prefix = ${prefix} + +BINDEST = ${exec_prefix}/bin + +datarootdir = ${prefix}/share +MANDEST = ${datarootdir}/man + +srcdir = . + + +CC = gcc +CCOPTS = $(CCOPT) -Wall -Wno-parentheses + +SYSDEFS = +CPPFLAGS = -I. -I/usr/sfw/include +#0 INCLS = -I. @V_INCL@ +DEFS = -DHAVE_CONFIG_H +LIBS = -lwrap -lrt -lsocket -lnsl -lresolv -lreadline -lcurses -L/usr/sfw/lib -lssl -lcrypto +LDFLAGS = + +INSTALL = ./install-sh -c + +#OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) + + +#0 CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(INCLS) +CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(CPPFLAGS) +CLIBS = $(LIBS) +#CLIBS = $(LIBS) -lm -lefence +XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \ + xiosignal.c xiosigchld.c xioread.c xiowrite.c \ + xiolayer.c xioshutdown.c xioclose.c xioexit.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-socket.c xio-interface.c xio-listen.c xio-unix.c \ + xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \ + xio-sctp.c xio-rawip.c \ + xio-socks.c xio-proxy.c xio-udp.c \ + xio-rawip.c \ + xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ + xio-pty.c xio-openssl.c xio-streams.c\ + xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c +XIOOBJS = $(XIOSRCS:.c=.o) +UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c filan.c sycls.c sslcls.c +UTLOBJS = $(UTLSRCS:.c=.o) +CFILES = $(XIOSRCS) $(UTLSRCS) socat.c procan_main.c filan_main.c +OFILES = $(CFILES:.c=.o) +PROGS = socat procan filan + +HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h compat.h \ + xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.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-interface.h xio-listen.h xio-unix.h \ + xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \ + xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \ + xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ + xio-system.h xio-termios.h xio-readline.h \ + xio-pty.h xio-openssl.h xio-streams.h \ + xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h + + +DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo 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 +TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \ + proxy.sh socks4a-echo.sh testcert.conf +OSFILES = Config/Makefile.Linux-2-6-24 Config/config.Linux-2-6-24.h \ + Config/Makefile.SunOS-5-10 Config/config.SunOS-5-10.h \ + Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \ + Config/Makefile.NetBSD-4-0 Config/config.NetBSD-4-0.h \ + Config/Makefile.OpenBSD-4-3 Config/config.OpenBSD-4-3.h + +all: progs doc + +scmclean: gitclean + +gitclean: distclean docclean + rm -f Makefile.bak configure + +doc: doc/socat.1 doc/socat.html + +docclean: + rm -f doc/socat.1 doc/socat.html + +doc/socat.1: doc/socat.yo + yodl2man -o $@ $+ + +doc/socat.html: doc/socat.yo + cd doc; yodl2html -o socat.html socat.yo; cd .. + +progs: $(PROGS) + +depend: $(CFILES) $(HFILES) + makedepend $(SYSDEFS) $(CFILES) + +socat: socat.o libxio.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS) + +PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o +procan: $(PROCAN_OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(PROCAN_OBJS) $(CLIBS) + +filan: filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o $(CLIBS) + +libxio.a: $(XIOOBJS) $(UTLOBJS) + $(AR) r $@ $(XIOOBJS) $(UTLOBJS) + $(RANLIB) $@ + +doc: doc/xio.help +# + +strip: progs + strip $(PROGS) + +install: progs $(srcdir)/doc/socat.1 + mkdir -p $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST) + $(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST) + mkdir -p $(DESTDIR)$(MANDEST)/man1 + $(INSTALL) -m 644 $(srcdir)/doc/socat.1 $(DESTDIR)$(MANDEST)/man1/ + +uninstall: + rm -f $(DESTDIR)$(BINDEST)/socat + rm -f $(DESTDIR)$(BINDEST)/procan + rm -f $(DESTDIR)$(BINDEST)/filan + rm -f $(DESTDIR)$(MANDEST)/man1/socat.1 + +# make a GNU-zipped tar ball of the source files +dist: socat.tar.gz socat.tar.bz2 + +socat.tar.gz: socat.tar + gzip -9 socat.tar.gz + +socat.tar.bz2: socat.tar + bzip2 -9 socat.tar.bz2 + +VERSION = `sed 's/"//g' 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 + if [ ! -d $(TARDIR) ]; then mkdir $(TARDIR); fi + tar cf - $+ |(cd $(TARDIR); tar xf -) + tar cvf socat.tar $(TARDIR) + rm -f $(TARDIR)/COPYING # write protected + rm -r $(TARDIR) + +clean: + rm -f *.o libxio.a socat procan filan \ + socat.tar socat.tar.Z socat.tar.gz socat.tar.bz2 \ + socat.out compile.log test.log + +# remove all files that are generated from the original socat distribution +# note that Makefile is also removed, so you have to start with ./configure +# again +distclean: clean + rm -f config.status config.cache config.log config.h Makefile + rm -rf autom4te.cache + +info: socat + uname -a >socat.out + ./socat -V >>socat.out + ./socat -hh >>socat.out + +# perform some tests on socat +test: progs + ./test.sh + +cert: + # prepare critical files with correct permissions to avoid race cond + >cert.key + >cert.pem + chmod 600 cert.key cert.pem + # generate a private key + openssl genrsa -out cert.key 1024 + # generate a self signed cert + openssl req -new -key cert.key -x509 -days 3653 -out cert.crt + # ...enter fields + # generate the pem file + cat cert.key cert.crt >cert.pem + #echo use cert.pem on requestors side, i.e. with option cert=cert.pem + #echo use cert.crt on checkers side, i.e. with option cafile=cert.crt diff --git a/Config/config.AIX-5-3.h b/Config/config.AIX-5-3.h new file mode 100644 index 0000000..9c0fec2 --- /dev/null +++ b/Config/config.AIX-5-3.h @@ -0,0 +1,523 @@ +/* config.h. Generated from config.h.in by configure. */ +/* source: config.h.in */ +/* Copyright Gerhard Rieger 2001-2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +#ifndef __config_h_included +#define __config_h_included 1 + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define if your struct stat has st_blksize. */ +#define HAVE_ST_BLKSIZE 1 + +/* Define if your struct stat has st_blocks. */ +#define HAVE_ST_BLOCKS 1 + +/* Define if your struct stat has st_rdev. */ +#define HAVE_ST_RDEV 1 + +/* Define if you have the strftime function. */ +#define HAVE_STRFTIME 1 + +/* Define if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to `int' if doesn't define. */ +/* #undef mode_t */ + +/* Define to `long' if doesn't define. */ +/* #undef off_t */ + +/* Define to `int' if doesn't define. */ +/* #undef pid_t */ + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the poll function. */ +#define HAVE_POLL 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtod function. */ +#define HAVE_STRTOD 1 + +/* Define if you have the strtol function. */ +#define HAVE_STRTOL 1 + +/* Define if you have the strtoul function. */ +#define HAVE_STRTOUL 1 + +/* Define if you have the uname function. */ +#define HAVE_UNAME 1 + +/* Define if you have the getpgid function. */ +#define HAVE_GETPGID 1 + +/* Define if you have the getsid function. */ +#define HAVE_GETSID 1 + +/* Define if you have the nanosleep function. */ +#define HAVE_NANOSLEEP 1 + +/* Define if you have the getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define if you have the getipnodebyname function. */ +#define HAVE_GETIPNODEBYNAME 1 + +/* Define if you have the setgroups function. */ +#define HAVE_SETGROUPS 1 + +/* Define if you have the inet_aton function. */ +#define HAVE_INET_ATON 1 + +/* Define if you have the memrchr function. */ +/* #undef HAVE_MEMRCHR */ + +/* Define if you have the if_indextoname function. */ +#define HAVE_IF_INDEXTONAME 1 + +/* Define if you have the sigaction function */ +#define HAVE_SIGACTION 1 + +/* Define if you have the stat64 function */ +#define HAVE_STAT64 1 + +/* Define if you have the fstat64 function */ +#define HAVE_FSTAT64 1 + +/* Define if you have the lstat64 function */ +#define HAVE_LSTAT64 1 + +/* Define if you have the lseek64 function */ +#define HAVE_LSEEK64 1 + +/* Define if you have the truncate64 function */ +#define HAVE_TRUNCATE64 1 + +/* Define if you have the ftruncate64 function */ +#define HAVE_FTRUNCATE64 1 + +/* Define if you have the strtoll function */ +#define HAVE_STRTOLL 1 + +/* Define if you have the hstrerror function */ +#define HAVE_HSTRERROR 1 + +/* Define if you have the inet_ntop function */ +#define HAVE_INET_NTOP 1 + +/* Define if you have the hstrerror prototype */ +#define HAVE_PROTOTYPE_HSTRERROR 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define if you have the header file. */ +#define HAVE_GRP_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_PTY_H */ + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_SYSTM_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP6_H 1 + +/* Define if you have the header file. */ +#define HAVE_ARPA_NAMESER_H 1 + +/* Define if you have the header file. */ +#define HAVE_RESOLV_H 1 + +/* Define if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_DL_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_TYPES_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_ERRQUEUE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_IF_TUN_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETPACKET_PACKET_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET_IF_ETHER_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_SELECT_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. (NetBSD, OpenBSD: openpty()) */ +/* #undef HAVE_UTIL_H */ + +/* Define if you have the header file. (FreeBSD: openpty()) */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define if you have the header file. (stream opts on SunOS)*/ +#define HAVE_SYS_STROPTS_H 1 + +/* Define if you have the header file. */ +#define HAVE_REGEX_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_FS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_EXT2_FS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_READLINE_READLINE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_READLINE_HISTORY_H */ + +/* Define if you have the readline library. */ +/* #undef HAVE_LIBREADLINE */ + +/* Define if you have the m library (-lm). */ +/* #undef HAVE_LIBM */ + +/* Define if you have the floor function */ +/* #undef HAVE_FLOOR */ + +/* some platforms need _XOPEN_EXTENDED_SOURCE to get syslog headers (AIX4.1) */ +/* #undef _XOPEN_EXTENDED_SOURCE */ + +/* fdset may have component fds_bits or __fds_bits */ +#define HAVE_FDS_BITS 1 + +/* Define if you have the sa_family_t */ +#define HAVE_TYPE_SA_FAMILY_T 1 + +/* define if your struct sigaction has sa_sigaction */ +#define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1 + +/* Define if your struct termios has component c_ispeed */ +/* #undef HAVE_TERMIOS_ISPEED */ + +/* the offset of c_ispeed in struct termios - usable in an speed_t array. + Applies only when HAVE_TERMIOS_ISPEED is set */ +/* #undef ISPEED_OFFSET */ + +/* the offset of c_ospeed in struct termios - see ISPEED_OFFSET */ +#ifdef ISPEED_OFFSET +# define OSPEED_OFFSET (ISPEED_OFFSET+1) +#else +/* # undef OSPEED_OFFSET */ +#endif + +/* Define if your termios.h likes _SVID3 defined */ +/* #undef _SVID3 */ + +/* Define if you have struct timespec (e.g. for nanosleep) */ +#define HAVE_STRUCT_TIMESPEC 1 + +/* Define if you have struct linger */ +#define HAVE_STRUCT_LINGER 1 + +/* Define if you have struct ip_mreq */ +#define HAVE_STRUCT_IP_MREQ 1 + +/* Define if you have struct ip_mreqn */ +/* #undef HAVE_STRUCT_IP_MREQN */ + +/* Define if you have struct ipv6_mreq */ +#define HAVE_STRUCT_IPV6_MREQ 1 + +/* Define if you have struct ifreq */ +#define HAVE_STRUCT_IFREQ 1 + +/* Define if you have struct ifreq.ifr_index */ +/* #undef HAVE_STRUCT_IFREQ_IFR_INDEX */ + +/* Define if you have struct ifreq.ifr_ifindex; not on HPUX */ +/* #undef HAVE_STRUCT_IFREQ_IFR_IFINDEX */ + +/* Define if your struct sockaddr has sa_len */ +#define HAVE_STRUCT_SOCKADDR_SALEN 1 + +/* there are several implementations of sockaddr_in6 */ +#define HAVE_IP6_SOCKADDR 0 + +/* Define if you have struct iovec */ +#define HAVE_STRUCT_IOVEC 1 + +/* define if your struct msghdr has msg_control */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROL 1 + +/* define if your struct msghdr has msg_controllen */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROLLEN 1 + +/* define if your struct msghdr has msg_flag */ +#define HAVE_STRUCT_MSGHDR_MSGFLAGS 1 + +/* define if you have struct cmsghdr */ +#define HAVE_STRUCT_CMSGHDR 1 + +/* define if you have struct in_pktinfo */ +/* #undef HAVE_STRUCT_IN_PKTINFO */ + +/* define if your struct ip has ip_hl; otherwise assume ip_vhl */ +#define HAVE_STRUCT_IP_IP_HL 1 + +/* Define if you have the setenv function */ +#define HAVE_SETENV 1 + +/* Define if you have the unsetenv function. not on HP-UX */ +#define HAVE_UNSETENV 1 + +/* Define if you have the flock function */ +/* #undef HAVE_FLOCK */ +#define HAVE_FLOCK 1 + +/* Define if you have the openpty function */ +/* #undef HAVE_OPENPTY */ + +/* Define if you have the grantpt function */ +#define HAVE_GRANTPT 1 + +/* Define if you have the unlockpt function */ +#define HAVE_UNLOCKPT 1 + +/* Define if you have the ptsname function */ +#define HAVE_PTSNAME 1 + +/* Define if you have the /dev/ptmx pseudo terminal multiplexer */ +/* #undef HAVE_DEV_PTMX */ + +/* Define if you have the /dev/ptc pseudo terminal multiplexer */ +#define HAVE_DEV_PTC 1 + +/* Define if you have the long long type */ +#define HAVE_TYPE_LONGLONG 1 + +/* is socklen_t already typedef'd? */ +#define HAVE_TYPE_SOCKLEN 1 + +/* Define if you have the struct stat64 type */ +#define HAVE_TYPE_STAT64 1 + +/* Define if you have the struct off64_t type */ +#define HAVE_TYPE_OFF64 1 + +/* is sighandler_t already typedef'd? */ +/* #undef HAVE_TYPE_SIGHANDLER */ + +/* is uint8_t already defined? */ +#define HAVE_TYPE_UINT8 1 + +/* is uint16_t already defined? */ +#define HAVE_TYPE_UINT16 1 + +/* is uint32_t already defined? */ +#define HAVE_TYPE_UINT32 1 + +/* is uint64_t already defined? */ +#define HAVE_TYPE_UINT64 1 + +/* Define if you have the printf "Z" modifier */ +/* #undef HAVE_FORMAT_Z */ + +/* Define the shift offset of the CRDLY mask */ +#define CRDLY_SHIFT 8 + +/* Define the shift offset of the TABDLY mask */ +#define TABDLY_SHIFT 10 + +/* Define the shift offset of the CSIZE mask */ +#define CSIZE_SHIFT 4 + +/* Define if you have tcpwrappers (libwrap, tcpd) and it declares hosts_allow_table */ +/* #undef HAVE_HOSTS_ALLOW_TABLE */ +#if defined(HAVE_HOSTS_ALLOW_TABLE) && HAVE_HOSTS_ALLOW_TABLE +# define HAVE_HOSTS_DENY_TABLE 1 +#else +/* # undef HAVE_HOSTS_DENY_TABLE */ +#endif + +/* 1..short, 3..int, 5..long; 2,4,6..unsigned */ +#define HAVE_BASIC_SIZE_T 0 /* unknown, taking default */ +#define HAVE_BASIC_MODE_T 0 /* unknown, taking default */ +#define HAVE_BASIC_PID_T 0 /* unknown, taking default */ +#define HAVE_BASIC_UID_T 0 /* unknown, taking default */ +#define HAVE_BASIC_GID_T 0 /* unknown, taking default */ +#define HAVE_BASIC_TIME_T 0 /* unknown, taking default */ +#define HAVE_BASIC_OFF64_T 0 /* unknown, taking default */ + +#define HAVE_BASIC_SOCKLEN_T 0 /* unknown, taking default */ + +#define HAVE_TYPEOF_ST_DEV 0 /* unknown, taking default */ +#define HAVE_TYPEOF_ST_INO 0 /* unknown, taking default */ +#define HAVE_TYPEOF_ST_NLINK 0 /* unknown, taking default */ +#define HAVE_TYPEOF_ST_SIZE 0 /* unknown, taking default */ +#define HAVE_TYPEOF_ST_BLKSIZE 0 /* unknown, taking default */ +#define HAVE_TYPEOF_ST_BLOCKS 0 /* unknown, taking default */ + +#define HAVE_TYPEOF_ST64_DEV 0 /* unknown, taking default */ +#define HAVE_TYPEOF_ST64_INO 0 /* unknown, taking default */ +#define HAVE_TYPEOF_ST64_NLINK 0 /* unknown, taking default */ +#define HAVE_TYPEOF_ST64_SIZE 0 /* unknown, taking default */ +#define HAVE_TYPEOF_ST64_BLKSIZE 0 /* unknown, taking default */ +#define HAVE_TYPEOF_ST64_BLOCKS 0 /* unknown, taking default */ + +#define HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC 0 /* unknown, taking default */ + +#define HAVE_TYPEOF_RLIM_MAX 0 /* unknown, taking default */ + +/* Define if you have the /proc filesystem */ +#define HAVE_PROC_DIR 1 + +/* Define if you have the /proc/$$/fd directories */ +#define HAVE_PROC_DIR_FD 1 + +#define WITH_HELP 1 +#define WITH_STDIO 1 +#define WITH_FDNUM 1 +#define WITH_FILE 1 +#define WITH_CREAT 1 +#define WITH_GOPEN 1 +#define WITH_TERMIOS 1 +#define WITH_PIPE 1 +#define WITH_UNIX 1 +/* #undef WITH_ABSTRACT_UNIXSOCKET */ +#define WITH_IP4 1 +#define WITH_IP6 1 +#define WITH_RAWIP 1 +#define WITH_GENERICSOCKET 1 +/* #undef WITH_INTERFACE */ +#define WITH_TCP 1 +#define WITH_UDP 1 +#define WITH_SCTP 1 +#define WITH_LISTEN 1 +#define WITH_SOCKS4 1 +#define WITH_SOCKS4A 1 +#define WITH_PROXY 1 +#define WITH_EXEC 1 +#define WITH_SYSTEM 1 +/* #undef WITH_READLINE */ +/* #undef WITH_TUN */ +#define WITH_PTY 1 +#define WITH_EXT2 1 +#define WITH_OPENSSL 1 +#define WITH_STREAMS 1 +/* #undef WITH_FIPS */ +/* #undef OPENSSL_FIPS */ +/* #undef WITH_LIBWRAP */ +/* #undef HAVE_TCPD_H */ +/* #undef HAVE_LIBWRAP */ + +#define WITH_SYCLS 1 +#define WITH_FILAN 1 +#define WITH_RETRY 1 + +#define WITH_MSGLEVEL 0 + +#endif /* !defined(__config_h_included) */ diff --git a/Config/config.Cygwin-1-5-25.h b/Config/config.Cygwin-1-5-25.h new file mode 100644 index 0000000..096580f --- /dev/null +++ b/Config/config.Cygwin-1-5-25.h @@ -0,0 +1,522 @@ +/* config.h. Generated from config.h.in by configure. */ +/* source: config.h.in */ +/* Copyright Gerhard Rieger 2001-2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +#ifndef __config_h_included +#define __config_h_included 1 + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define if your struct stat has st_blksize. */ +#define HAVE_ST_BLKSIZE 1 + +/* Define if your struct stat has st_blocks. */ +#define HAVE_ST_BLOCKS 1 + +/* Define if your struct stat has st_rdev. */ +#define HAVE_ST_RDEV 1 + +/* Define if you have the strftime function. */ +#define HAVE_STRFTIME 1 + +/* Define if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to `int' if doesn't define. */ +/* #undef mode_t */ + +/* Define to `long' if doesn't define. */ +/* #undef off_t */ + +/* Define to `int' if doesn't define. */ +/* #undef pid_t */ + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the poll function. */ +#define HAVE_POLL 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtod function. */ +#define HAVE_STRTOD 1 + +/* Define if you have the strtol function. */ +#define HAVE_STRTOL 1 + +/* Define if you have the strtoul function. */ +#define HAVE_STRTOUL 1 + +/* Define if you have the uname function. */ +#define HAVE_UNAME 1 + +/* Define if you have the getpgid function. */ +#define HAVE_GETPGID 1 + +/* Define if you have the getsid function. */ +#define HAVE_GETSID 1 + +/* Define if you have the nanosleep function. */ +#define HAVE_NANOSLEEP 1 + +/* Define if you have the getaddrinfo function. */ +/* #undef HAVE_GETADDRINFO */ + +/* Define if you have the getipnodebyname function. */ +/* #undef HAVE_GETIPNODEBYNAME */ + +/* Define if you have the setgroups function. */ +#define HAVE_SETGROUPS 1 + +/* Define if you have the inet_aton function. */ +#define HAVE_INET_ATON 1 + +/* Define if you have the memrchr function. */ +/* #undef HAVE_MEMRCHR */ + +/* Define if you have the if_indextoname function. */ +/* #undef HAVE_IF_INDEXTONAME */ + +/* Define if you have the sigaction function */ +#define HAVE_SIGACTION 1 + +/* Define if you have the stat64 function */ +/* #undef HAVE_STAT64 */ + +/* Define if you have the fstat64 function */ +/* #undef HAVE_FSTAT64 */ + +/* Define if you have the lstat64 function */ +/* #undef HAVE_LSTAT64 */ + +/* Define if you have the lseek64 function */ +/* #undef HAVE_LSEEK64 */ + +/* Define if you have the truncate64 function */ +/* #undef HAVE_TRUNCATE64 */ + +/* Define if you have the ftruncate64 function */ +/* #undef HAVE_FTRUNCATE64 */ + +/* Define if you have the strtoll function */ +#define HAVE_STRTOLL 1 + +/* Define if you have the hstrerror function */ +#define HAVE_HSTRERROR 1 + +/* Define if you have the inet_ntop function */ +#define HAVE_INET_NTOP 1 + +/* Define if you have the hstrerror prototype */ +#define HAVE_PROTOTYPE_HSTRERROR 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define if you have the header file. */ +#define HAVE_GRP_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define if you have the header file. */ +#define HAVE_PTY_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_SYSTM_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET_IP6_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_ARPA_NAMESER_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_RESOLV_H */ + +/* Define if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_NET_IF_DL_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_TYPES_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_ERRQUEUE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_IF_TUN_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETPACKET_PACKET_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET_IF_ETHER_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_SELECT_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. (NetBSD, OpenBSD: openpty()) */ +/* #undef HAVE_UTIL_H */ + +/* Define if you have the header file. (FreeBSD: openpty()) */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define if you have the header file. (stream opts on SunOS)*/ +/* #undef HAVE_SYS_STROPTS_H */ + +/* Define if you have the header file. */ +#define HAVE_REGEX_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_FS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_EXT2_FS_H */ + +/* Define if you have the header file. */ +#define HAVE_READLINE_READLINE_H 1 + +/* Define if you have the header file. */ +#define HAVE_READLINE_HISTORY_H 1 + +/* Define if you have the readline library. */ +#define HAVE_LIBREADLINE 1 + +/* Define if you have the m library (-lm). */ +/* #undef HAVE_LIBM */ + +/* Define if you have the floor function */ +/* #undef HAVE_FLOOR */ + +/* some platforms need _XOPEN_EXTENDED_SOURCE to get syslog headers (AIX4.1) */ +/* #undef _XOPEN_EXTENDED_SOURCE */ + +/* fdset may have component fds_bits or __fds_bits */ +#define HAVE_FDS_BITS 1 + +/* Define if you have the sa_family_t */ +#define HAVE_TYPE_SA_FAMILY_T 1 + +/* define if your struct sigaction has sa_sigaction */ +#define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1 + +/* Define if your struct termios has component c_ispeed */ +#define HAVE_TERMIOS_ISPEED 1 + +/* the offset of c_ispeed in struct termios - usable in an speed_t array. + Applies only when HAVE_TERMIOS_ISPEED is set */ +#define ISPEED_OFFSET 9 + +/* the offset of c_ospeed in struct termios - see ISPEED_OFFSET */ +#ifdef ISPEED_OFFSET +# define OSPEED_OFFSET (ISPEED_OFFSET+1) +#else +/* # undef OSPEED_OFFSET */ +#endif + +/* Define if your termios.h likes _SVID3 defined */ +/* #undef _SVID3 */ + +/* Define if you have struct timespec (e.g. for nanosleep) */ +#define HAVE_STRUCT_TIMESPEC 1 + +/* Define if you have struct linger */ +#define HAVE_STRUCT_LINGER 1 + +/* Define if you have struct ip_mreq */ +#define HAVE_STRUCT_IP_MREQ 1 + +/* Define if you have struct ip_mreqn */ +/* #undef HAVE_STRUCT_IP_MREQN */ + +/* Define if you have struct ipv6_mreq */ +/* #undef HAVE_STRUCT_IPV6_MREQ */ + +/* Define if you have struct ifreq */ +#define HAVE_STRUCT_IFREQ 1 + +/* Define if you have struct ifreq.ifr_index */ +/* #undef HAVE_STRUCT_IFREQ_IFR_INDEX */ + +/* Define if you have struct ifreq.ifr_ifindex; not on HPUX */ +/* #undef HAVE_STRUCT_IFREQ_IFR_IFINDEX */ + +/* Define if your struct sockaddr has sa_len */ +/* #undef HAVE_STRUCT_SOCKADDR_SALEN */ + +/* there are several implementations of sockaddr_in6 */ +/* #undef HAVE_IP6_SOCKADDR */ + +/* Define if you have struct iovec */ +#define HAVE_STRUCT_IOVEC 1 + +/* define if your struct msghdr has msg_control */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROL 1 + +/* define if your struct msghdr has msg_controllen */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROLLEN 1 + +/* define if your struct msghdr has msg_flag */ +#define HAVE_STRUCT_MSGHDR_MSGFLAGS 1 + +/* define if you have struct cmsghdr */ +#define HAVE_STRUCT_CMSGHDR 1 + +/* define if you have struct in_pktinfo */ +/* #undef HAVE_STRUCT_IN_PKTINFO */ + +/* define if your struct ip has ip_hl; otherwise assume ip_vhl */ +#define HAVE_STRUCT_IP_IP_HL 1 + +/* Define if you have the setenv function */ +#define HAVE_SETENV 1 + +/* Define if you have the unsetenv function. not on HP-UX */ +#define HAVE_UNSETENV 1 + +/* Define if you have the flock function */ +#define HAVE_FLOCK 1 + +/* Define if you have the openpty function */ +#define HAVE_OPENPTY 1 + +/* Define if you have the grantpt function */ +#define HAVE_GRANTPT 1 + +/* Define if you have the unlockpt function */ +#define HAVE_UNLOCKPT 1 + +/* Define if you have the ptsname function */ +#define HAVE_PTSNAME 1 + +/* Define if you have the /dev/ptmx pseudo terminal multiplexer */ +#define HAVE_DEV_PTMX 1 + +/* Define if you have the /dev/ptc pseudo terminal multiplexer */ +/* #undef HAVE_DEV_PTC */ + +/* Define if you have the long long type */ +#define HAVE_TYPE_LONGLONG 1 + +/* is socklen_t already typedef'd? */ +#define HAVE_TYPE_SOCKLEN 1 + +/* Define if you have the struct stat64 type */ +/* #undef HAVE_TYPE_STAT64 */ + +/* Define if you have the struct off64_t type */ +/* #undef HAVE_TYPE_OFF64 */ + +/* is sighandler_t already typedef'd? */ +/* #undef HAVE_TYPE_SIGHANDLER */ + +/* is uint8_t already defined? */ +#define HAVE_TYPE_UINT8 1 + +/* is uint16_t already defined? */ +#define HAVE_TYPE_UINT16 1 + +/* is uint32_t already defined? */ +#define HAVE_TYPE_UINT32 1 + +/* is uint64_t already defined? */ +#define HAVE_TYPE_UINT64 1 + +/* Define if you have the printf "Z" modifier */ +/* #undef HAVE_FORMAT_Z */ + +/* Define the shift offset of the CRDLY mask */ +#define CRDLY_SHIFT 7 + +/* Define the shift offset of the TABDLY mask */ +#define TABDLY_SHIFT 11 + +/* Define the shift offset of the CSIZE mask */ +#define CSIZE_SHIFT 4 + +/* Define if you have tcpwrappers (libwrap, tcpd) and it declares hosts_allow_table */ +#define HAVE_HOSTS_ALLOW_TABLE 1 +#if defined(HAVE_HOSTS_ALLOW_TABLE) && HAVE_HOSTS_ALLOW_TABLE +# define HAVE_HOSTS_DENY_TABLE 1 +#else +/* # undef HAVE_HOSTS_DENY_TABLE */ +#endif + +/* 1..short, 3..int, 5..long; 2,4,6..unsigned */ +#define HAVE_BASIC_SIZE_T 4 /* unsigned int */ +#define HAVE_BASIC_MODE_T 4 /* unsigned int */ +#define HAVE_BASIC_PID_T 3 /* int */ +#define HAVE_BASIC_UID_T 6 /* unsigned long */ +#define HAVE_BASIC_GID_T 6 /* unsigned long */ +#define HAVE_BASIC_TIME_T 5 /* long */ +#define HAVE_BASIC_OFF64_T 0 /* unknown, taking default */ + +#define HAVE_BASIC_SOCKLEN_T 3 /* int */ + +#define HAVE_TYPEOF_ST_DEV 6 /* unsigned long */ +#define HAVE_TYPEOF_ST_INO 8 /* unsigned long long */ +#define HAVE_TYPEOF_ST_NLINK 2 /* unsigned short */ +#define HAVE_TYPEOF_ST_SIZE 7 /* long long */ +#define HAVE_TYPEOF_ST_BLKSIZE 5 /* long */ +#define HAVE_TYPEOF_ST_BLOCKS 7 /* long long */ + +/* #undef HAVE_TYPEOF_ST64_DEV */ +/* #undef HAVE_TYPEOF_ST64_INO */ +/* #undef HAVE_TYPEOF_ST64_NLINK */ +/* #undef HAVE_TYPEOF_ST64_SIZE */ +/* #undef HAVE_TYPEOF_ST64_BLKSIZE */ +/* #undef HAVE_TYPEOF_ST64_BLOCKS */ + +#define HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC 5 /* long */ + +#define HAVE_TYPEOF_RLIM_MAX 6 /* unsigned long */ + +/* Define if you have the /proc filesystem */ +#define HAVE_PROC_DIR 1 + +/* Define if you have the /proc/$$/fd directories */ +#define HAVE_PROC_DIR_FD 1 + +#define WITH_HELP 1 +#define WITH_STDIO 1 +#define WITH_FDNUM 1 +#define WITH_FILE 1 +#define WITH_CREAT 1 +#define WITH_GOPEN 1 +#define WITH_TERMIOS 1 +#define WITH_PIPE 1 +#define WITH_UNIX 1 +/* #undef WITH_ABSTRACT_UNIXSOCKET */ +#define WITH_IP4 1 +/* #undef WITH_IP6 */ +#define WITH_RAWIP 1 +#define WITH_GENERICSOCKET 1 +/* #undef WITH_INTERFACE */ +#define WITH_TCP 1 +#define WITH_UDP 1 +/* #undef WITH_SCTP */ +#define WITH_LISTEN 1 +#define WITH_SOCKS4 1 +#define WITH_SOCKS4A 1 +#define WITH_PROXY 1 +#define WITH_EXEC 1 +#define WITH_SYSTEM 1 +#define WITH_READLINE 1 +/* #undef WITH_TUN */ +#define WITH_PTY 1 +#define WITH_EXT2 1 +#define WITH_OPENSSL 1 +#define WITH_STREAMS 1 +/* #undef WITH_FIPS */ +/* #undef OPENSSL_FIPS */ +#define WITH_LIBWRAP 1 +#define HAVE_TCPD_H 1 +#define HAVE_LIBWRAP 1 + +#define WITH_SYCLS 1 +#define WITH_FILAN 1 +#define WITH_RETRY 1 + +#define WITH_MSGLEVEL 0 + +#endif /* !defined(__config_h_included) */ diff --git a/Config/config.FreeBSD-6-1.h b/Config/config.FreeBSD-6-1.h index af45423..aad86e3 100644 --- a/Config/config.FreeBSD-6-1.h +++ b/Config/config.FreeBSD-6-1.h @@ -1,6 +1,6 @@ -/* config.h. Generated by configure. */ -/* source: Config/config.FreeBSD-6-1.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* config.h. Generated from config.h.in by configure. */ +/* source: config.h.in */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __config_h_included @@ -108,6 +108,9 @@ /* Define if you have the memrchr function. */ /* #undef HAVE_MEMRCHR */ +/* Define if you have the if_indextoname function. */ +#define HAVE_IF_INDEXTONAME 1 + /* Define if you have the sigaction function */ #define HAVE_SIGACTION 1 @@ -225,9 +228,24 @@ /* Define if you have the header file. */ #define HAVE_NET_IF_H 1 +/* Define if you have the header file. */ +#define HAVE_NET_IF_DL_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_TYPES_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_ERRQUEUE_H */ + /* Define if you have the header file. */ /* #undef HAVE_LINUX_IF_TUN_H */ +/* Define if you have the header file. */ +/* #undef HAVE_NETPACKET_PACKET_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET_IF_ETHER_H */ + /* Define if you have the header file. */ #define HAVE_SYS_UTSNAME_H 1 @@ -276,6 +294,12 @@ /* fdset may have component fds_bits or __fds_bits */ #define HAVE_FDS_BITS 1 +/* Define if you have the sa_family_t */ +#define HAVE_TYPE_SA_FAMILY_T 1 + +/* define if your struct sigaction has sa_sigaction */ +#define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1 + /* Define if your struct termios has component c_ispeed */ #define HAVE_TERMIOS_ISPEED 1 @@ -314,7 +338,7 @@ /* Define if you have struct ifreq.ifr_index */ #define HAVE_STRUCT_IFREQ_IFR_INDEX 1 -/* Define if you have struct ifreq.ifr_ifindex */ +/* Define if you have struct ifreq.ifr_ifindex; not on HPUX */ /* #undef HAVE_STRUCT_IFREQ_IFR_IFINDEX */ /* Define if your struct sockaddr has sa_len */ @@ -335,12 +359,21 @@ /* define if your struct msghdr has msg_flag */ #define HAVE_STRUCT_MSGHDR_MSGFLAGS 1 +/* define if you have struct cmsghdr */ +#define HAVE_STRUCT_CMSGHDR 1 + +/* define if you have struct in_pktinfo */ +/* #undef HAVE_STRUCT_IN_PKTINFO */ + /* define if your struct ip has ip_hl; otherwise assume ip_vhl */ #define HAVE_STRUCT_IP_IP_HL 1 /* Define if you have the setenv function */ #define HAVE_SETENV 1 +/* Define if you have the unsetenv function. not on HP-UX */ +#define HAVE_UNSETENV 1 + /* Define if you have the flock function */ #define HAVE_FLOCK 1 @@ -434,7 +467,7 @@ /* #undef HAVE_TYPEOF_ST64_BLKSIZE */ /* #undef HAVE_TYPEOF_ST64_BLOCKS */ -/* #undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC */ +#define HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC 5 /* long */ #define HAVE_TYPEOF_RLIM_MAX 7 /* long long */ @@ -457,8 +490,11 @@ #define WITH_IP4 1 #define WITH_IP6 1 #define WITH_RAWIP 1 +#define WITH_GENERICSOCKET 1 +/* #undef WITH_INTERFACE */ #define WITH_TCP 1 #define WITH_UDP 1 +#define WITH_SCTP 1 #define WITH_LISTEN 1 #define WITH_SOCKS4 1 #define WITH_SOCKS4A 1 @@ -470,6 +506,7 @@ #define WITH_PTY 1 #define WITH_EXT2 1 #define WITH_OPENSSL 1 +#define WITH_STREAMS 1 /* #undef WITH_FIPS */ /* #undef OPENSSL_FIPS */ #define WITH_LIBWRAP 1 diff --git a/Config/config.Linux-2-6-24.h b/Config/config.Linux-2-6-24.h new file mode 100644 index 0000000..94dc9b8 --- /dev/null +++ b/Config/config.Linux-2-6-24.h @@ -0,0 +1,522 @@ +/* config.h. Generated from config.h.in by configure. */ +/* source: config.h.in */ +/* Copyright Gerhard Rieger 2001-2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +#ifndef __config_h_included +#define __config_h_included 1 + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define if your struct stat has st_blksize. */ +#define HAVE_ST_BLKSIZE 1 + +/* Define if your struct stat has st_blocks. */ +#define HAVE_ST_BLOCKS 1 + +/* Define if your struct stat has st_rdev. */ +#define HAVE_ST_RDEV 1 + +/* Define if you have the strftime function. */ +#define HAVE_STRFTIME 1 + +/* Define if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to `int' if doesn't define. */ +/* #undef mode_t */ + +/* Define to `long' if doesn't define. */ +/* #undef off_t */ + +/* Define to `int' if doesn't define. */ +/* #undef pid_t */ + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the poll function. */ +#define HAVE_POLL 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtod function. */ +#define HAVE_STRTOD 1 + +/* Define if you have the strtol function. */ +#define HAVE_STRTOL 1 + +/* Define if you have the strtoul function. */ +#define HAVE_STRTOUL 1 + +/* Define if you have the uname function. */ +#define HAVE_UNAME 1 + +/* Define if you have the getpgid function. */ +#define HAVE_GETPGID 1 + +/* Define if you have the getsid function. */ +#define HAVE_GETSID 1 + +/* Define if you have the nanosleep function. */ +#define HAVE_NANOSLEEP 1 + +/* Define if you have the getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define if you have the getipnodebyname function. */ +/* #undef HAVE_GETIPNODEBYNAME */ + +/* Define if you have the setgroups function. */ +#define HAVE_SETGROUPS 1 + +/* Define if you have the inet_aton function. */ +#define HAVE_INET_ATON 1 + +/* Define if you have the memrchr function. */ +#define HAVE_MEMRCHR 1 + +/* Define if you have the if_indextoname function. */ +#define HAVE_IF_INDEXTONAME 1 + +/* Define if you have the sigaction function */ +#define HAVE_SIGACTION 1 + +/* Define if you have the stat64 function */ +#define HAVE_STAT64 1 + +/* Define if you have the fstat64 function */ +#define HAVE_FSTAT64 1 + +/* Define if you have the lstat64 function */ +#define HAVE_LSTAT64 1 + +/* Define if you have the lseek64 function */ +#define HAVE_LSEEK64 1 + +/* Define if you have the truncate64 function */ +#define HAVE_TRUNCATE64 1 + +/* Define if you have the ftruncate64 function */ +#define HAVE_FTRUNCATE64 1 + +/* Define if you have the strtoll function */ +#define HAVE_STRTOLL 1 + +/* Define if you have the hstrerror function */ +#define HAVE_HSTRERROR 1 + +/* Define if you have the inet_ntop function */ +#define HAVE_INET_NTOP 1 + +/* Define if you have the hstrerror prototype */ +#define HAVE_PROTOTYPE_HSTRERROR 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define if you have the header file. */ +#define HAVE_GRP_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define if you have the header file. */ +#define HAVE_PTY_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_SYSTM_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP6_H 1 + +/* Define if you have the header file. */ +#define HAVE_ARPA_NAMESER_H 1 + +/* Define if you have the header file. */ +#define HAVE_RESOLV_H 1 + +/* Define if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_NET_IF_DL_H */ + +/* Define if you have the header file. */ +#define HAVE_LINUX_TYPES_H 1 + +/* Define if you have the header file. */ +#define HAVE_LINUX_ERRQUEUE_H 1 + +/* Define if you have the header file. */ +#define HAVE_LINUX_IF_TUN_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETPACKET_PACKET_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IF_ETHER_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_SELECT_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. (NetBSD, OpenBSD: openpty()) */ +/* #undef HAVE_UTIL_H */ + +/* Define if you have the header file. (FreeBSD: openpty()) */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define if you have the header file. (stream opts on SunOS)*/ +#define HAVE_SYS_STROPTS_H 1 + +/* Define if you have the header file. */ +#define HAVE_REGEX_H 1 + +/* Define if you have the header file. */ +#define HAVE_LINUX_FS_H 1 + +/* Define if you have the header file. */ +#define HAVE_LINUX_EXT2_FS_H 1 + +/* Define if you have the header file. */ +#define HAVE_READLINE_READLINE_H 1 + +/* Define if you have the header file. */ +#define HAVE_READLINE_HISTORY_H 1 + +/* Define if you have the readline library. */ +#define HAVE_LIBREADLINE 1 + +/* Define if you have the m library (-lm). */ +/* #undef HAVE_LIBM */ + +/* Define if you have the floor function */ +/* #undef HAVE_FLOOR */ + +/* some platforms need _XOPEN_EXTENDED_SOURCE to get syslog headers (AIX4.1) */ +/* #undef _XOPEN_EXTENDED_SOURCE */ + +/* fdset may have component fds_bits or __fds_bits */ +#define HAVE_FDS_BITS 1 + +/* Define if you have the sa_family_t */ +#define HAVE_TYPE_SA_FAMILY_T 1 + +/* define if your struct sigaction has sa_sigaction */ +#define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1 + +/* Define if your struct termios has component c_ispeed */ +#define HAVE_TERMIOS_ISPEED 1 + +/* the offset of c_ispeed in struct termios - usable in an speed_t array. + Applies only when HAVE_TERMIOS_ISPEED is set */ +#define ISPEED_OFFSET 13 + +/* the offset of c_ospeed in struct termios - see ISPEED_OFFSET */ +#ifdef ISPEED_OFFSET +# define OSPEED_OFFSET (ISPEED_OFFSET+1) +#else +/* # undef OSPEED_OFFSET */ +#endif + +/* Define if your termios.h likes _SVID3 defined */ +/* #undef _SVID3 */ + +/* Define if you have struct timespec (e.g. for nanosleep) */ +#define HAVE_STRUCT_TIMESPEC 1 + +/* Define if you have struct linger */ +#define HAVE_STRUCT_LINGER 1 + +/* Define if you have struct ip_mreq */ +#define HAVE_STRUCT_IP_MREQ 1 + +/* Define if you have struct ip_mreqn */ +#define HAVE_STRUCT_IP_MREQN 1 + +/* Define if you have struct ipv6_mreq */ +#define HAVE_STRUCT_IPV6_MREQ 1 + +/* Define if you have struct ifreq */ +#define HAVE_STRUCT_IFREQ 1 + +/* Define if you have struct ifreq.ifr_index */ +/* #undef HAVE_STRUCT_IFREQ_IFR_INDEX */ + +/* Define if you have struct ifreq.ifr_ifindex; not on HPUX */ +#define HAVE_STRUCT_IFREQ_IFR_IFINDEX 1 + +/* Define if your struct sockaddr has sa_len */ +/* #undef HAVE_STRUCT_SOCKADDR_SALEN */ + +/* there are several implementations of sockaddr_in6 */ +#define HAVE_IP6_SOCKADDR 0 + +/* Define if you have struct iovec */ +#define HAVE_STRUCT_IOVEC 1 + +/* define if your struct msghdr has msg_control */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROL 1 + +/* define if your struct msghdr has msg_controllen */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROLLEN 1 + +/* define if your struct msghdr has msg_flag */ +#define HAVE_STRUCT_MSGHDR_MSGFLAGS 1 + +/* define if you have struct cmsghdr */ +#define HAVE_STRUCT_CMSGHDR 1 + +/* define if you have struct in_pktinfo */ +#define HAVE_STRUCT_IN_PKTINFO 1 + +/* define if your struct ip has ip_hl; otherwise assume ip_vhl */ +#define HAVE_STRUCT_IP_IP_HL 1 + +/* Define if you have the setenv function */ +#define HAVE_SETENV 1 + +/* Define if you have the unsetenv function. not on HP-UX */ +#define HAVE_UNSETENV 1 + +/* Define if you have the flock function */ +#define HAVE_FLOCK 1 + +/* Define if you have the openpty function */ +#define HAVE_OPENPTY 1 + +/* Define if you have the grantpt function */ +#define HAVE_GRANTPT 1 + +/* Define if you have the unlockpt function */ +#define HAVE_UNLOCKPT 1 + +/* Define if you have the ptsname function */ +#define HAVE_PTSNAME 1 + +/* Define if you have the /dev/ptmx pseudo terminal multiplexer */ +#define HAVE_DEV_PTMX 1 + +/* Define if you have the /dev/ptc pseudo terminal multiplexer */ +/* #undef HAVE_DEV_PTC */ + +/* Define if you have the long long type */ +#define HAVE_TYPE_LONGLONG 1 + +/* is socklen_t already typedef'd? */ +#define HAVE_TYPE_SOCKLEN 1 + +/* Define if you have the struct stat64 type */ +#define HAVE_TYPE_STAT64 1 + +/* Define if you have the struct off64_t type */ +#define HAVE_TYPE_OFF64 1 + +/* is sighandler_t already typedef'd? */ +#define HAVE_TYPE_SIGHANDLER 1 + +/* is uint8_t already defined? */ +#define HAVE_TYPE_UINT8 1 + +/* is uint16_t already defined? */ +#define HAVE_TYPE_UINT16 1 + +/* is uint32_t already defined? */ +#define HAVE_TYPE_UINT32 1 + +/* is uint64_t already defined? */ +#define HAVE_TYPE_UINT64 1 + +/* Define if you have the printf "Z" modifier */ +#define HAVE_FORMAT_Z 1 + +/* Define the shift offset of the CRDLY mask */ +#define CRDLY_SHIFT 9 + +/* Define the shift offset of the TABDLY mask */ +#define TABDLY_SHIFT 11 + +/* Define the shift offset of the CSIZE mask */ +#define CSIZE_SHIFT 4 + +/* Define if you have tcpwrappers (libwrap, tcpd) and it declares hosts_allow_table */ +#define HAVE_HOSTS_ALLOW_TABLE 1 +#if defined(HAVE_HOSTS_ALLOW_TABLE) && HAVE_HOSTS_ALLOW_TABLE +# define HAVE_HOSTS_DENY_TABLE 1 +#else +/* # undef HAVE_HOSTS_DENY_TABLE */ +#endif + +/* 1..short, 3..int, 5..long; 2,4,6..unsigned */ +#define HAVE_BASIC_SIZE_T 4 /* unsigned int */ +#define HAVE_BASIC_MODE_T 4 /* unsigned int */ +#define HAVE_BASIC_PID_T 3 /* int */ +#define HAVE_BASIC_UID_T 4 /* unsigned int */ +#define HAVE_BASIC_GID_T 4 /* unsigned int */ +#define HAVE_BASIC_TIME_T 5 /* long */ +#define HAVE_BASIC_OFF64_T 7 /* long long */ + +#define HAVE_BASIC_SOCKLEN_T 4 /* unsigned int */ + +#define HAVE_TYPEOF_ST_DEV 8 /* unsigned long long */ +#define HAVE_TYPEOF_ST_INO 6 /* unsigned long */ +#define HAVE_TYPEOF_ST_NLINK 4 /* unsigned int */ +#define HAVE_TYPEOF_ST_SIZE 5 /* long */ +#define HAVE_TYPEOF_ST_BLKSIZE 5 /* long */ +#define HAVE_TYPEOF_ST_BLOCKS 5 /* long */ + +#define HAVE_TYPEOF_ST64_DEV 8 /* unsigned long long */ +#define HAVE_TYPEOF_ST64_INO 8 /* unsigned long long */ +#define HAVE_TYPEOF_ST64_NLINK 4 /* unsigned int */ +#define HAVE_TYPEOF_ST64_SIZE 7 /* long long */ +#define HAVE_TYPEOF_ST64_BLKSIZE 5 /* long */ +#define HAVE_TYPEOF_ST64_BLOCKS 7 /* long long */ + +#define HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC 5 /* long */ + +#define HAVE_TYPEOF_RLIM_MAX 6 /* unsigned long */ + +/* Define if you have the /proc filesystem */ +#define HAVE_PROC_DIR 1 + +/* Define if you have the /proc/$$/fd directories */ +#define HAVE_PROC_DIR_FD 1 + +#define WITH_HELP 1 +#define WITH_STDIO 1 +#define WITH_FDNUM 1 +#define WITH_FILE 1 +#define WITH_CREAT 1 +#define WITH_GOPEN 1 +#define WITH_TERMIOS 1 +#define WITH_PIPE 1 +#define WITH_UNIX 1 +#define WITH_ABSTRACT_UNIXSOCKET 1 +#define WITH_IP4 1 +#define WITH_IP6 1 +#define WITH_RAWIP 1 +#define WITH_GENERICSOCKET 1 +#define WITH_INTERFACE 1 +#define WITH_TCP 1 +#define WITH_UDP 1 +#define WITH_SCTP 1 +#define WITH_LISTEN 1 +#define WITH_SOCKS4 1 +#define WITH_SOCKS4A 1 +#define WITH_PROXY 1 +#define WITH_EXEC 1 +#define WITH_SYSTEM 1 +#define WITH_READLINE 1 +#define WITH_TUN 1 +#define WITH_PTY 1 +#define WITH_EXT2 1 +#define WITH_OPENSSL 1 +#define WITH_STREAMS 1 +/* #undef WITH_FIPS */ +/* #undef OPENSSL_FIPS */ +#define WITH_LIBWRAP 1 +#define HAVE_TCPD_H 1 +#define HAVE_LIBWRAP 1 + +#define WITH_SYCLS 1 +#define WITH_FILAN 1 +#define WITH_RETRY 1 + +#define WITH_MSGLEVEL 0 + +#endif /* !defined(__config_h_included) */ diff --git a/Config/config.MacOSX-10-5.h b/Config/config.MacOSX-10-5.h new file mode 100644 index 0000000..c19ca9e --- /dev/null +++ b/Config/config.MacOSX-10-5.h @@ -0,0 +1,522 @@ +/* config.h. Generated from config.h.in by configure. */ +/* source: config.h.in */ +/* Copyright Gerhard Rieger 2001-2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +#ifndef __config_h_included +#define __config_h_included 1 + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define if your struct stat has st_blksize. */ +#define HAVE_ST_BLKSIZE 1 + +/* Define if your struct stat has st_blocks. */ +#define HAVE_ST_BLOCKS 1 + +/* Define if your struct stat has st_rdev. */ +#define HAVE_ST_RDEV 1 + +/* Define if you have the strftime function. */ +#define HAVE_STRFTIME 1 + +/* Define if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to `int' if doesn't define. */ +/* #undef mode_t */ + +/* Define to `long' if doesn't define. */ +/* #undef off_t */ + +/* Define to `int' if doesn't define. */ +/* #undef pid_t */ + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the poll function. */ +#define HAVE_POLL 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtod function. */ +#define HAVE_STRTOD 1 + +/* Define if you have the strtol function. */ +#define HAVE_STRTOL 1 + +/* Define if you have the strtoul function. */ +#define HAVE_STRTOUL 1 + +/* Define if you have the uname function. */ +#define HAVE_UNAME 1 + +/* Define if you have the getpgid function. */ +#define HAVE_GETPGID 1 + +/* Define if you have the getsid function. */ +#define HAVE_GETSID 1 + +/* Define if you have the nanosleep function. */ +#define HAVE_NANOSLEEP 1 + +/* Define if you have the getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define if you have the getipnodebyname function. */ +#define HAVE_GETIPNODEBYNAME 1 + +/* Define if you have the setgroups function. */ +#define HAVE_SETGROUPS 1 + +/* Define if you have the inet_aton function. */ +#define HAVE_INET_ATON 1 + +/* Define if you have the memrchr function. */ +/* #undef HAVE_MEMRCHR */ + +/* Define if you have the if_indextoname function. */ +#define HAVE_IF_INDEXTONAME 1 + +/* Define if you have the sigaction function */ +#define HAVE_SIGACTION 1 + +/* Define if you have the stat64 function */ +#define HAVE_STAT64 1 + +/* Define if you have the fstat64 function */ +#define HAVE_FSTAT64 1 + +/* Define if you have the lstat64 function */ +#define HAVE_LSTAT64 1 + +/* Define if you have the lseek64 function */ +/* #undef HAVE_LSEEK64 */ + +/* Define if you have the truncate64 function */ +/* #undef HAVE_TRUNCATE64 */ + +/* Define if you have the ftruncate64 function */ +/* #undef HAVE_FTRUNCATE64 */ + +/* Define if you have the strtoll function */ +#define HAVE_STRTOLL 1 + +/* Define if you have the hstrerror function */ +#define HAVE_HSTRERROR 1 + +/* Define if you have the inet_ntop function */ +#define HAVE_INET_NTOP 1 + +/* Define if you have the hstrerror prototype */ +#define HAVE_PROTOTYPE_HSTRERROR 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define if you have the header file. */ +#define HAVE_GRP_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_PTY_H */ + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_SYSTM_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP6_H 1 + +/* Define if you have the header file. */ +#define HAVE_ARPA_NAMESER_H 1 + +/* Define if you have the header file. */ +#define HAVE_RESOLV_H 1 + +/* Define if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_DL_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_TYPES_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_ERRQUEUE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_IF_TUN_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETPACKET_PACKET_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET_IF_ETHER_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_SELECT_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. (NetBSD, OpenBSD: openpty()) */ +#define HAVE_UTIL_H 1 + +/* Define if you have the header file. (FreeBSD: openpty()) */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define if you have the header file. (stream opts on SunOS)*/ +/* #undef HAVE_SYS_STROPTS_H */ + +/* Define if you have the header file. */ +#define HAVE_REGEX_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_FS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_EXT2_FS_H */ + +/* Define if you have the header file. */ +#define HAVE_READLINE_READLINE_H 1 + +/* Define if you have the header file. */ +#define HAVE_READLINE_HISTORY_H 1 + +/* Define if you have the readline library. */ +#define HAVE_LIBREADLINE 1 + +/* Define if you have the m library (-lm). */ +/* #undef HAVE_LIBM */ + +/* Define if you have the floor function */ +/* #undef HAVE_FLOOR */ + +/* some platforms need _XOPEN_EXTENDED_SOURCE to get syslog headers (AIX4.1) */ +/* #undef _XOPEN_EXTENDED_SOURCE */ + +/* fdset may have component fds_bits or __fds_bits */ +#define HAVE_FDS_BITS 1 + +/* Define if you have the sa_family_t */ +#define HAVE_TYPE_SA_FAMILY_T 1 + +/* define if your struct sigaction has sa_sigaction */ +#define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1 + +/* Define if your struct termios has component c_ispeed */ +#define HAVE_TERMIOS_ISPEED 1 + +/* the offset of c_ispeed in struct termios - usable in an speed_t array. + Applies only when HAVE_TERMIOS_ISPEED is set */ +#define ISPEED_OFFSET 9 + +/* the offset of c_ospeed in struct termios - see ISPEED_OFFSET */ +#ifdef ISPEED_OFFSET +# define OSPEED_OFFSET (ISPEED_OFFSET+1) +#else +/* # undef OSPEED_OFFSET */ +#endif + +/* Define if your termios.h likes _SVID3 defined */ +/* #undef _SVID3 */ + +/* Define if you have struct timespec (e.g. for nanosleep) */ +#define HAVE_STRUCT_TIMESPEC 1 + +/* Define if you have struct linger */ +#define HAVE_STRUCT_LINGER 1 + +/* Define if you have struct ip_mreq */ +#define HAVE_STRUCT_IP_MREQ 1 + +/* Define if you have struct ip_mreqn */ +/* #undef HAVE_STRUCT_IP_MREQN */ + +/* Define if you have struct ipv6_mreq */ +#define HAVE_STRUCT_IPV6_MREQ 1 + +/* Define if you have struct ifreq */ +#define HAVE_STRUCT_IFREQ 1 + +/* Define if you have struct ifreq.ifr_index */ +/* #undef HAVE_STRUCT_IFREQ_IFR_INDEX */ + +/* Define if you have struct ifreq.ifr_ifindex; not on HPUX */ +/* #undef HAVE_STRUCT_IFREQ_IFR_IFINDEX */ + +/* Define if your struct sockaddr has sa_len */ +#define HAVE_STRUCT_SOCKADDR_SALEN 1 + +/* there are several implementations of sockaddr_in6 */ +#define HAVE_IP6_SOCKADDR 0 + +/* Define if you have struct iovec */ +#define HAVE_STRUCT_IOVEC 1 + +/* define if your struct msghdr has msg_control */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROL 1 + +/* define if your struct msghdr has msg_controllen */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROLLEN 1 + +/* define if your struct msghdr has msg_flag */ +#define HAVE_STRUCT_MSGHDR_MSGFLAGS 1 + +/* define if you have struct cmsghdr */ +#define HAVE_STRUCT_CMSGHDR 1 + +/* define if you have struct in_pktinfo */ +/* #undef HAVE_STRUCT_IN_PKTINFO */ + +/* define if your struct ip has ip_hl; otherwise assume ip_vhl */ +#define HAVE_STRUCT_IP_IP_HL 1 + +/* Define if you have the setenv function */ +#define HAVE_SETENV 1 + +/* Define if you have the unsetenv function. not on HP-UX */ +#define HAVE_UNSETENV 1 + +/* Define if you have the flock function */ +#define HAVE_FLOCK 1 + +/* Define if you have the openpty function */ +#define HAVE_OPENPTY 1 + +/* Define if you have the grantpt function */ +#define HAVE_GRANTPT 1 + +/* Define if you have the unlockpt function */ +#define HAVE_UNLOCKPT 1 + +/* Define if you have the ptsname function */ +#define HAVE_PTSNAME 1 + +/* Define if you have the /dev/ptmx pseudo terminal multiplexer */ +#define HAVE_DEV_PTMX 1 + +/* Define if you have the /dev/ptc pseudo terminal multiplexer */ +/* #undef HAVE_DEV_PTC */ + +/* Define if you have the long long type */ +#define HAVE_TYPE_LONGLONG 1 + +/* is socklen_t already typedef'd? */ +#define HAVE_TYPE_SOCKLEN 1 + +/* Define if you have the struct stat64 type */ +#define HAVE_TYPE_STAT64 1 + +/* Define if you have the struct off64_t type */ +/* #undef HAVE_TYPE_OFF64 */ + +/* is sighandler_t already typedef'd? */ +/* #undef HAVE_TYPE_SIGHANDLER */ + +/* is uint8_t already defined? */ +#define HAVE_TYPE_UINT8 1 + +/* is uint16_t already defined? */ +#define HAVE_TYPE_UINT16 1 + +/* is uint32_t already defined? */ +#define HAVE_TYPE_UINT32 1 + +/* is uint64_t already defined? */ +#define HAVE_TYPE_UINT64 1 + +/* Define if you have the printf "Z" modifier */ +/* #undef HAVE_FORMAT_Z */ + +/* Define the shift offset of the CRDLY mask */ +#define CRDLY_SHIFT 12 + +/* Define the shift offset of the TABDLY mask */ +#define TABDLY_SHIFT -1 + +/* Define the shift offset of the CSIZE mask */ +#define CSIZE_SHIFT 8 + +/* Define if you have tcpwrappers (libwrap, tcpd) and it declares hosts_allow_table */ +#define HAVE_HOSTS_ALLOW_TABLE 1 +#if defined(HAVE_HOSTS_ALLOW_TABLE) && HAVE_HOSTS_ALLOW_TABLE +# define HAVE_HOSTS_DENY_TABLE 1 +#else +/* # undef HAVE_HOSTS_DENY_TABLE */ +#endif + +/* 1..short, 3..int, 5..long; 2,4,6..unsigned */ +#define HAVE_BASIC_SIZE_T 6 /* unsigned long */ +#define HAVE_BASIC_MODE_T 2 /* unsigned short */ +#define HAVE_BASIC_PID_T 3 /* int */ +#define HAVE_BASIC_UID_T 4 /* unsigned int */ +#define HAVE_BASIC_GID_T 4 /* unsigned int */ +#define HAVE_BASIC_TIME_T 5 /* long */ +#define HAVE_BASIC_OFF64_T 0 /* unknown, taking default */ + +#define HAVE_BASIC_SOCKLEN_T 4 /* unsigned int */ + +#define HAVE_TYPEOF_ST_DEV 3 /* int */ +#define HAVE_TYPEOF_ST_INO 4 /* unsigned int */ +#define HAVE_TYPEOF_ST_NLINK 2 /* unsigned short */ +#define HAVE_TYPEOF_ST_SIZE 7 /* long long */ +#define HAVE_TYPEOF_ST_BLKSIZE 3 /* int */ +#define HAVE_TYPEOF_ST_BLOCKS 7 /* long long */ + +#define HAVE_TYPEOF_ST64_DEV 3 /* int */ +#define HAVE_TYPEOF_ST64_INO 8 /* unsigned long long */ +#define HAVE_TYPEOF_ST64_NLINK 2 /* unsigned short */ +#define HAVE_TYPEOF_ST64_SIZE 7 /* long long */ +#define HAVE_TYPEOF_ST64_BLKSIZE 3 /* int */ +#define HAVE_TYPEOF_ST64_BLOCKS 7 /* long long */ + +#define HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC 3 /* int */ + +#define HAVE_TYPEOF_RLIM_MAX 8 /* unsigned long long */ + +/* Define if you have the /proc filesystem */ +/* #undef HAVE_PROC_DIR */ + +/* Define if you have the /proc/$$/fd directories */ +/* #undef HAVE_PROC_DIR_FD */ + +#define WITH_HELP 1 +#define WITH_STDIO 1 +#define WITH_FDNUM 1 +#define WITH_FILE 1 +#define WITH_CREAT 1 +#define WITH_GOPEN 1 +#define WITH_TERMIOS 1 +#define WITH_PIPE 1 +#define WITH_UNIX 1 +/* #undef WITH_ABSTRACT_UNIXSOCKET */ +#define WITH_IP4 1 +#define WITH_IP6 1 +#define WITH_RAWIP 1 +#define WITH_GENERICSOCKET 1 +/* #undef WITH_INTERFACE */ +#define WITH_TCP 1 +#define WITH_UDP 1 +/* #undef WITH_SCTP */ +#define WITH_LISTEN 1 +#define WITH_SOCKS4 1 +#define WITH_SOCKS4A 1 +#define WITH_PROXY 1 +#define WITH_EXEC 1 +#define WITH_SYSTEM 1 +#define WITH_READLINE 1 +/* #undef WITH_TUN */ +#define WITH_PTY 1 +#define WITH_EXT2 1 +#define WITH_OPENSSL 1 +#define WITH_STREAMS 1 +/* #undef WITH_FIPS */ +/* #undef OPENSSL_FIPS */ +#define WITH_LIBWRAP 1 +#define HAVE_TCPD_H 1 +#define HAVE_LIBWRAP 1 + +#define WITH_SYCLS 1 +#define WITH_FILAN 1 +#define WITH_RETRY 1 + +#define WITH_MSGLEVEL 0 + +#endif /* !defined(__config_h_included) */ diff --git a/Config/config.NetBSD-4-0.h b/Config/config.NetBSD-4-0.h new file mode 100644 index 0000000..27f18a9 --- /dev/null +++ b/Config/config.NetBSD-4-0.h @@ -0,0 +1,522 @@ +/* config.h. Generated from config.h.in by configure. */ +/* source: config.h.in */ +/* Copyright Gerhard Rieger 2001-2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +#ifndef __config_h_included +#define __config_h_included 1 + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define if your struct stat has st_blksize. */ +#define HAVE_ST_BLKSIZE 1 + +/* Define if your struct stat has st_blocks. */ +#define HAVE_ST_BLOCKS 1 + +/* Define if your struct stat has st_rdev. */ +#define HAVE_ST_RDEV 1 + +/* Define if you have the strftime function. */ +#define HAVE_STRFTIME 1 + +/* Define if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to `int' if doesn't define. */ +/* #undef mode_t */ + +/* Define to `long' if doesn't define. */ +/* #undef off_t */ + +/* Define to `int' if doesn't define. */ +/* #undef pid_t */ + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the poll function. */ +#define HAVE_POLL 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtod function. */ +#define HAVE_STRTOD 1 + +/* Define if you have the strtol function. */ +#define HAVE_STRTOL 1 + +/* Define if you have the strtoul function. */ +#define HAVE_STRTOUL 1 + +/* Define if you have the uname function. */ +#define HAVE_UNAME 1 + +/* Define if you have the getpgid function. */ +#define HAVE_GETPGID 1 + +/* Define if you have the getsid function. */ +#define HAVE_GETSID 1 + +/* Define if you have the nanosleep function. */ +#define HAVE_NANOSLEEP 1 + +/* Define if you have the getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define if you have the getipnodebyname function. */ +/* #undef HAVE_GETIPNODEBYNAME */ + +/* Define if you have the setgroups function. */ +#define HAVE_SETGROUPS 1 + +/* Define if you have the inet_aton function. */ +#define HAVE_INET_ATON 1 + +/* Define if you have the memrchr function. */ +/* #undef HAVE_MEMRCHR */ + +/* Define if you have the if_indextoname function. */ +#define HAVE_IF_INDEXTONAME 1 + +/* Define if you have the sigaction function */ +#define HAVE_SIGACTION 1 + +/* Define if you have the stat64 function */ +/* #undef HAVE_STAT64 */ + +/* Define if you have the fstat64 function */ +/* #undef HAVE_FSTAT64 */ + +/* Define if you have the lstat64 function */ +/* #undef HAVE_LSTAT64 */ + +/* Define if you have the lseek64 function */ +/* #undef HAVE_LSEEK64 */ + +/* Define if you have the truncate64 function */ +/* #undef HAVE_TRUNCATE64 */ + +/* Define if you have the ftruncate64 function */ +/* #undef HAVE_FTRUNCATE64 */ + +/* Define if you have the strtoll function */ +#define HAVE_STRTOLL 1 + +/* Define if you have the hstrerror function */ +#define HAVE_HSTRERROR 1 + +/* Define if you have the inet_ntop function */ +#define HAVE_INET_NTOP 1 + +/* Define if you have the hstrerror prototype */ +#define HAVE_PROTOTYPE_HSTRERROR 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define if you have the header file. */ +#define HAVE_GRP_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_PTY_H */ + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_SYSTM_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP6_H 1 + +/* Define if you have the header file. */ +#define HAVE_ARPA_NAMESER_H 1 + +/* Define if you have the header file. */ +#define HAVE_RESOLV_H 1 + +/* Define if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_DL_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_TYPES_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_ERRQUEUE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_IF_TUN_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETPACKET_PACKET_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET_IF_ETHER_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_SELECT_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. (NetBSD, OpenBSD: openpty()) */ +#define HAVE_UTIL_H 1 + +/* Define if you have the header file. (FreeBSD: openpty()) */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define if you have the header file. (stream opts on SunOS)*/ +/* #undef HAVE_SYS_STROPTS_H */ + +/* Define if you have the header file. */ +#define HAVE_REGEX_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_FS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_EXT2_FS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_READLINE_READLINE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_READLINE_HISTORY_H */ + +/* Define if you have the readline library. */ +/* #undef HAVE_LIBREADLINE */ + +/* Define if you have the m library (-lm). */ +/* #undef HAVE_LIBM */ + +/* Define if you have the floor function */ +/* #undef HAVE_FLOOR */ + +/* some platforms need _XOPEN_EXTENDED_SOURCE to get syslog headers (AIX4.1) */ +/* #undef _XOPEN_EXTENDED_SOURCE */ + +/* fdset may have component fds_bits or __fds_bits */ +#define HAVE_FDS_BITS 1 + +/* Define if you have the sa_family_t */ +#define HAVE_TYPE_SA_FAMILY_T 1 + +/* define if your struct sigaction has sa_sigaction */ +#define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1 + +/* Define if your struct termios has component c_ispeed */ +#define HAVE_TERMIOS_ISPEED 1 + +/* the offset of c_ispeed in struct termios - usable in an speed_t array. + Applies only when HAVE_TERMIOS_ISPEED is set */ +#define ISPEED_OFFSET 9 + +/* the offset of c_ospeed in struct termios - see ISPEED_OFFSET */ +#ifdef ISPEED_OFFSET +# define OSPEED_OFFSET (ISPEED_OFFSET+1) +#else +/* # undef OSPEED_OFFSET */ +#endif + +/* Define if your termios.h likes _SVID3 defined */ +/* #undef _SVID3 */ + +/* Define if you have struct timespec (e.g. for nanosleep) */ +#define HAVE_STRUCT_TIMESPEC 1 + +/* Define if you have struct linger */ +#define HAVE_STRUCT_LINGER 1 + +/* Define if you have struct ip_mreq */ +#define HAVE_STRUCT_IP_MREQ 1 + +/* Define if you have struct ip_mreqn */ +/* #undef HAVE_STRUCT_IP_MREQN */ + +/* Define if you have struct ipv6_mreq */ +#define HAVE_STRUCT_IPV6_MREQ 1 + +/* Define if you have struct ifreq */ +#define HAVE_STRUCT_IFREQ 1 + +/* Define if you have struct ifreq.ifr_index */ +/* #undef HAVE_STRUCT_IFREQ_IFR_INDEX */ + +/* Define if you have struct ifreq.ifr_ifindex; not on HPUX */ +/* #undef HAVE_STRUCT_IFREQ_IFR_IFINDEX */ + +/* Define if your struct sockaddr has sa_len */ +#define HAVE_STRUCT_SOCKADDR_SALEN 1 + +/* there are several implementations of sockaddr_in6 */ +#define HAVE_IP6_SOCKADDR 0 + +/* Define if you have struct iovec */ +#define HAVE_STRUCT_IOVEC 1 + +/* define if your struct msghdr has msg_control */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROL 1 + +/* define if your struct msghdr has msg_controllen */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROLLEN 1 + +/* define if your struct msghdr has msg_flag */ +#define HAVE_STRUCT_MSGHDR_MSGFLAGS 1 + +/* define if you have struct cmsghdr */ +#define HAVE_STRUCT_CMSGHDR 1 + +/* define if you have struct in_pktinfo */ +/* #undef HAVE_STRUCT_IN_PKTINFO */ + +/* define if your struct ip has ip_hl; otherwise assume ip_vhl */ +#define HAVE_STRUCT_IP_IP_HL 1 + +/* Define if you have the setenv function */ +#define HAVE_SETENV 1 + +/* Define if you have the unsetenv function. not on HP-UX */ +#define HAVE_UNSETENV 1 + +/* Define if you have the flock function */ +#define HAVE_FLOCK 1 + +/* Define if you have the openpty function */ +#define HAVE_OPENPTY 1 + +/* Define if you have the grantpt function */ +#define HAVE_GRANTPT 1 + +/* Define if you have the unlockpt function */ +#define HAVE_UNLOCKPT 1 + +/* Define if you have the ptsname function */ +#define HAVE_PTSNAME 1 + +/* Define if you have the /dev/ptmx pseudo terminal multiplexer */ +#define HAVE_DEV_PTMX 1 + +/* Define if you have the /dev/ptc pseudo terminal multiplexer */ +/* #undef HAVE_DEV_PTC */ + +/* Define if you have the long long type */ +#define HAVE_TYPE_LONGLONG 1 + +/* is socklen_t already typedef'd? */ +#define HAVE_TYPE_SOCKLEN 1 + +/* Define if you have the struct stat64 type */ +/* #undef HAVE_TYPE_STAT64 */ + +/* Define if you have the struct off64_t type */ +/* #undef HAVE_TYPE_OFF64 */ + +/* is sighandler_t already typedef'd? */ +/* #undef HAVE_TYPE_SIGHANDLER */ + +/* is uint8_t already defined? */ +#define HAVE_TYPE_UINT8 1 + +/* is uint16_t already defined? */ +#define HAVE_TYPE_UINT16 1 + +/* is uint32_t already defined? */ +#define HAVE_TYPE_UINT32 1 + +/* is uint64_t already defined? */ +#define HAVE_TYPE_UINT64 1 + +/* Define if you have the printf "Z" modifier */ +/* #undef HAVE_FORMAT_Z */ + +/* Define the shift offset of the CRDLY mask */ +#define CRDLY_SHIFT -1 + +/* Define the shift offset of the TABDLY mask */ +#define TABDLY_SHIFT -1 + +/* Define the shift offset of the CSIZE mask */ +#define CSIZE_SHIFT 8 + +/* Define if you have tcpwrappers (libwrap, tcpd) and it declares hosts_allow_table */ +#define HAVE_HOSTS_ALLOW_TABLE 1 +#if defined(HAVE_HOSTS_ALLOW_TABLE) && HAVE_HOSTS_ALLOW_TABLE +# define HAVE_HOSTS_DENY_TABLE 1 +#else +/* # undef HAVE_HOSTS_DENY_TABLE */ +#endif + +/* 1..short, 3..int, 5..long; 2,4,6..unsigned */ +#define HAVE_BASIC_SIZE_T 4 /* unsigned int */ +#define HAVE_BASIC_MODE_T 4 /* unsigned int */ +#define HAVE_BASIC_PID_T 3 /* int */ +#define HAVE_BASIC_UID_T 4 /* unsigned int */ +#define HAVE_BASIC_GID_T 4 /* unsigned int */ +#define HAVE_BASIC_TIME_T 5 /* long */ +#define HAVE_BASIC_OFF64_T 0 /* unknown, taking default */ + +#define HAVE_BASIC_SOCKLEN_T 4 /* unsigned int */ + +#define HAVE_TYPEOF_ST_DEV 4 /* unsigned int */ +#define HAVE_TYPEOF_ST_INO 8 /* unsigned long long */ +#define HAVE_TYPEOF_ST_NLINK 4 /* unsigned int */ +#define HAVE_TYPEOF_ST_SIZE 7 /* long long */ +#define HAVE_TYPEOF_ST_BLKSIZE 4 /* unsigned int */ +#define HAVE_TYPEOF_ST_BLOCKS 7 /* long long */ + +/* #undef HAVE_TYPEOF_ST64_DEV */ +/* #undef HAVE_TYPEOF_ST64_INO */ +/* #undef HAVE_TYPEOF_ST64_NLINK */ +/* #undef HAVE_TYPEOF_ST64_SIZE */ +/* #undef HAVE_TYPEOF_ST64_BLKSIZE */ +/* #undef HAVE_TYPEOF_ST64_BLOCKS */ + +#define HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC 5 /* long */ + +#define HAVE_TYPEOF_RLIM_MAX 7 /* long long */ + +/* Define if you have the /proc filesystem */ +#define HAVE_PROC_DIR 1 + +/* Define if you have the /proc/$$/fd directories */ +/* #undef HAVE_PROC_DIR_FD */ + +#define WITH_HELP 1 +#define WITH_STDIO 1 +#define WITH_FDNUM 1 +#define WITH_FILE 1 +#define WITH_CREAT 1 +#define WITH_GOPEN 1 +#define WITH_TERMIOS 1 +#define WITH_PIPE 1 +#define WITH_UNIX 1 +/* #undef WITH_ABSTRACT_UNIXSOCKET */ +#define WITH_IP4 1 +#define WITH_IP6 1 +#define WITH_RAWIP 1 +#define WITH_GENERICSOCKET 1 +/* #undef WITH_INTERFACE */ +#define WITH_TCP 1 +#define WITH_UDP 1 +/* #undef WITH_SCTP */ +#define WITH_LISTEN 1 +#define WITH_SOCKS4 1 +#define WITH_SOCKS4A 1 +#define WITH_PROXY 1 +#define WITH_EXEC 1 +#define WITH_SYSTEM 1 +/* #undef WITH_READLINE */ +/* #undef WITH_TUN */ +#define WITH_PTY 1 +#define WITH_EXT2 1 +#define WITH_OPENSSL 1 +#define WITH_STREAMS 1 +/* #undef WITH_FIPS */ +/* #undef OPENSSL_FIPS */ +#define WITH_LIBWRAP 1 +#define HAVE_TCPD_H 1 +#define HAVE_LIBWRAP 1 + +#define WITH_SYCLS 1 +#define WITH_FILAN 1 +#define WITH_RETRY 1 + +#define WITH_MSGLEVEL 0 + +#endif /* !defined(__config_h_included) */ diff --git a/Config/config.OpenBSD-4-3.h b/Config/config.OpenBSD-4-3.h new file mode 100644 index 0000000..a3852e1 --- /dev/null +++ b/Config/config.OpenBSD-4-3.h @@ -0,0 +1,522 @@ +/* config.h. Generated from config.h.in by configure. */ +/* source: config.h.in */ +/* Copyright Gerhard Rieger 2001-2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +#ifndef __config_h_included +#define __config_h_included 1 + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define if your struct stat has st_blksize. */ +#define HAVE_ST_BLKSIZE 1 + +/* Define if your struct stat has st_blocks. */ +#define HAVE_ST_BLOCKS 1 + +/* Define if your struct stat has st_rdev. */ +#define HAVE_ST_RDEV 1 + +/* Define if you have the strftime function. */ +#define HAVE_STRFTIME 1 + +/* Define if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to `int' if doesn't define. */ +/* #undef mode_t */ + +/* Define to `long' if doesn't define. */ +/* #undef off_t */ + +/* Define to `int' if doesn't define. */ +/* #undef pid_t */ + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the poll function. */ +#define HAVE_POLL 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtod function. */ +#define HAVE_STRTOD 1 + +/* Define if you have the strtol function. */ +#define HAVE_STRTOL 1 + +/* Define if you have the strtoul function. */ +#define HAVE_STRTOUL 1 + +/* Define if you have the uname function. */ +#define HAVE_UNAME 1 + +/* Define if you have the getpgid function. */ +#define HAVE_GETPGID 1 + +/* Define if you have the getsid function. */ +#define HAVE_GETSID 1 + +/* Define if you have the nanosleep function. */ +#define HAVE_NANOSLEEP 1 + +/* Define if you have the getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define if you have the getipnodebyname function. */ +/* #undef HAVE_GETIPNODEBYNAME */ + +/* Define if you have the setgroups function. */ +#define HAVE_SETGROUPS 1 + +/* Define if you have the inet_aton function. */ +#define HAVE_INET_ATON 1 + +/* Define if you have the memrchr function. */ +#define HAVE_MEMRCHR 1 + +/* Define if you have the if_indextoname function. */ +#define HAVE_IF_INDEXTONAME 1 + +/* Define if you have the sigaction function */ +#define HAVE_SIGACTION 1 + +/* Define if you have the stat64 function */ +/* #undef HAVE_STAT64 */ + +/* Define if you have the fstat64 function */ +/* #undef HAVE_FSTAT64 */ + +/* Define if you have the lstat64 function */ +/* #undef HAVE_LSTAT64 */ + +/* Define if you have the lseek64 function */ +/* #undef HAVE_LSEEK64 */ + +/* Define if you have the truncate64 function */ +/* #undef HAVE_TRUNCATE64 */ + +/* Define if you have the ftruncate64 function */ +/* #undef HAVE_FTRUNCATE64 */ + +/* Define if you have the strtoll function */ +#define HAVE_STRTOLL 1 + +/* Define if you have the hstrerror function */ +#define HAVE_HSTRERROR 1 + +/* Define if you have the inet_ntop function */ +#define HAVE_INET_NTOP 1 + +/* Define if you have the hstrerror prototype */ +#define HAVE_PROTOTYPE_HSTRERROR 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define if you have the header file. */ +#define HAVE_GRP_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_PTY_H */ + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_SYSTM_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP6_H 1 + +/* Define if you have the header file. */ +#define HAVE_ARPA_NAMESER_H 1 + +/* Define if you have the header file. */ +#define HAVE_RESOLV_H 1 + +/* Define if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_DL_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_TYPES_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_ERRQUEUE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_IF_TUN_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETPACKET_PACKET_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET_IF_ETHER_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_SELECT_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. (NetBSD, OpenBSD: openpty()) */ +#define HAVE_UTIL_H 1 + +/* Define if you have the header file. (FreeBSD: openpty()) */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define if you have the header file. (stream opts on SunOS)*/ +/* #undef HAVE_SYS_STROPTS_H */ + +/* Define if you have the header file. */ +#define HAVE_REGEX_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_FS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_EXT2_FS_H */ + +/* Define if you have the header file. */ +#define HAVE_READLINE_READLINE_H 1 + +/* Define if you have the header file. */ +#define HAVE_READLINE_HISTORY_H 1 + +/* Define if you have the readline library. */ +#define HAVE_LIBREADLINE 1 + +/* Define if you have the m library (-lm). */ +/* #undef HAVE_LIBM */ + +/* Define if you have the floor function */ +/* #undef HAVE_FLOOR */ + +/* some platforms need _XOPEN_EXTENDED_SOURCE to get syslog headers (AIX4.1) */ +/* #undef _XOPEN_EXTENDED_SOURCE */ + +/* fdset may have component fds_bits or __fds_bits */ +#define HAVE_FDS_BITS 1 + +/* Define if you have the sa_family_t */ +#define HAVE_TYPE_SA_FAMILY_T 1 + +/* define if your struct sigaction has sa_sigaction */ +#define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1 + +/* Define if your struct termios has component c_ispeed */ +#define HAVE_TERMIOS_ISPEED 1 + +/* the offset of c_ispeed in struct termios - usable in an speed_t array. + Applies only when HAVE_TERMIOS_ISPEED is set */ +#define ISPEED_OFFSET 9 + +/* the offset of c_ospeed in struct termios - see ISPEED_OFFSET */ +#ifdef ISPEED_OFFSET +# define OSPEED_OFFSET (ISPEED_OFFSET+1) +#else +/* # undef OSPEED_OFFSET */ +#endif + +/* Define if your termios.h likes _SVID3 defined */ +/* #undef _SVID3 */ + +/* Define if you have struct timespec (e.g. for nanosleep) */ +#define HAVE_STRUCT_TIMESPEC 1 + +/* Define if you have struct linger */ +#define HAVE_STRUCT_LINGER 1 + +/* Define if you have struct ip_mreq */ +#define HAVE_STRUCT_IP_MREQ 1 + +/* Define if you have struct ip_mreqn */ +/* #undef HAVE_STRUCT_IP_MREQN */ + +/* Define if you have struct ipv6_mreq */ +#define HAVE_STRUCT_IPV6_MREQ 1 + +/* Define if you have struct ifreq */ +#define HAVE_STRUCT_IFREQ 1 + +/* Define if you have struct ifreq.ifr_index */ +/* #undef HAVE_STRUCT_IFREQ_IFR_INDEX */ + +/* Define if you have struct ifreq.ifr_ifindex; not on HPUX */ +/* #undef HAVE_STRUCT_IFREQ_IFR_IFINDEX */ + +/* Define if your struct sockaddr has sa_len */ +#define HAVE_STRUCT_SOCKADDR_SALEN 1 + +/* there are several implementations of sockaddr_in6 */ +#define HAVE_IP6_SOCKADDR 0 + +/* Define if you have struct iovec */ +/* #undef HAVE_STRUCT_IOVEC */ + +/* define if your struct msghdr has msg_control */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROL 1 + +/* define if your struct msghdr has msg_controllen */ +#define HAVE_STRUCT_MSGHDR_MSGCONTROLLEN 1 + +/* define if your struct msghdr has msg_flag */ +#define HAVE_STRUCT_MSGHDR_MSGFLAGS 1 + +/* define if you have struct cmsghdr */ +#define HAVE_STRUCT_CMSGHDR 1 + +/* define if you have struct in_pktinfo */ +/* #undef HAVE_STRUCT_IN_PKTINFO */ + +/* define if your struct ip has ip_hl; otherwise assume ip_vhl */ +#define HAVE_STRUCT_IP_IP_HL 1 + +/* Define if you have the setenv function */ +#define HAVE_SETENV 1 + +/* Define if you have the unsetenv function. not on HP-UX */ +#define HAVE_UNSETENV 1 + +/* Define if you have the flock function */ +#define HAVE_FLOCK 1 + +/* Define if you have the openpty function */ +#define HAVE_OPENPTY 1 + +/* Define if you have the grantpt function */ +/* #undef HAVE_GRANTPT */ + +/* Define if you have the unlockpt function */ +/* #undef HAVE_UNLOCKPT */ + +/* Define if you have the ptsname function */ +/* #undef HAVE_PTSNAME */ + +/* Define if you have the /dev/ptmx pseudo terminal multiplexer */ +/* #undef HAVE_DEV_PTMX */ + +/* Define if you have the /dev/ptc pseudo terminal multiplexer */ +/* #undef HAVE_DEV_PTC */ + +/* Define if you have the long long type */ +#define HAVE_TYPE_LONGLONG 1 + +/* is socklen_t already typedef'd? */ +#define HAVE_TYPE_SOCKLEN 1 + +/* Define if you have the struct stat64 type */ +/* #undef HAVE_TYPE_STAT64 */ + +/* Define if you have the struct off64_t type */ +/* #undef HAVE_TYPE_OFF64 */ + +/* is sighandler_t already typedef'd? */ +/* #undef HAVE_TYPE_SIGHANDLER */ + +/* is uint8_t already defined? */ +#define HAVE_TYPE_UINT8 1 + +/* is uint16_t already defined? */ +#define HAVE_TYPE_UINT16 1 + +/* is uint32_t already defined? */ +#define HAVE_TYPE_UINT32 1 + +/* is uint64_t already defined? */ +#define HAVE_TYPE_UINT64 1 + +/* Define if you have the printf "Z" modifier */ +/* #undef HAVE_FORMAT_Z */ + +/* Define the shift offset of the CRDLY mask */ +#define CRDLY_SHIFT -1 + +/* Define the shift offset of the TABDLY mask */ +#define TABDLY_SHIFT -1 + +/* Define the shift offset of the CSIZE mask */ +#define CSIZE_SHIFT 8 + +/* Define if you have tcpwrappers (libwrap, tcpd) and it declares hosts_allow_table */ +#define HAVE_HOSTS_ALLOW_TABLE 1 +#if defined(HAVE_HOSTS_ALLOW_TABLE) && HAVE_HOSTS_ALLOW_TABLE +# define HAVE_HOSTS_DENY_TABLE 1 +#else +/* # undef HAVE_HOSTS_DENY_TABLE */ +#endif + +/* 1..short, 3..int, 5..long; 2,4,6..unsigned */ +#define HAVE_BASIC_SIZE_T 6 /* unsigned long */ +#define HAVE_BASIC_MODE_T 4 /* unsigned int */ +#define HAVE_BASIC_PID_T 3 /* int */ +#define HAVE_BASIC_UID_T 4 /* unsigned int */ +#define HAVE_BASIC_GID_T 4 /* unsigned int */ +#define HAVE_BASIC_TIME_T 3 /* int */ +#define HAVE_BASIC_OFF64_T 0 /* unknown, taking default */ + +#define HAVE_BASIC_SOCKLEN_T 4 /* unsigned int */ + +#define HAVE_TYPEOF_ST_DEV 3 /* int */ +#define HAVE_TYPEOF_ST_INO 4 /* unsigned int */ +#define HAVE_TYPEOF_ST_NLINK 4 /* unsigned int */ +#define HAVE_TYPEOF_ST_SIZE 7 /* long long */ +#define HAVE_TYPEOF_ST_BLKSIZE 4 /* unsigned int */ +#define HAVE_TYPEOF_ST_BLOCKS 7 /* long long */ + +/* #undef HAVE_TYPEOF_ST64_DEV */ +/* #undef HAVE_TYPEOF_ST64_INO */ +/* #undef HAVE_TYPEOF_ST64_NLINK */ +/* #undef HAVE_TYPEOF_ST64_SIZE */ +/* #undef HAVE_TYPEOF_ST64_BLKSIZE */ +/* #undef HAVE_TYPEOF_ST64_BLOCKS */ + +#define HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC 5 /* long */ + +#define HAVE_TYPEOF_RLIM_MAX 8 /* unsigned long long */ + +/* Define if you have the /proc filesystem */ +/* #undef HAVE_PROC_DIR */ + +/* Define if you have the /proc/$$/fd directories */ +/* #undef HAVE_PROC_DIR_FD */ + +#define WITH_HELP 1 +#define WITH_STDIO 1 +#define WITH_FDNUM 1 +#define WITH_FILE 1 +#define WITH_CREAT 1 +#define WITH_GOPEN 1 +#define WITH_TERMIOS 1 +#define WITH_PIPE 1 +#define WITH_UNIX 1 +/* #undef WITH_ABSTRACT_UNIXSOCKET */ +#define WITH_IP4 1 +#define WITH_IP6 1 +#define WITH_RAWIP 1 +#define WITH_GENERICSOCKET 1 +/* #undef WITH_INTERFACE */ +#define WITH_TCP 1 +#define WITH_UDP 1 +/* #undef WITH_SCTP */ +#define WITH_LISTEN 1 +#define WITH_SOCKS4 1 +#define WITH_SOCKS4A 1 +#define WITH_PROXY 1 +#define WITH_EXEC 1 +#define WITH_SYSTEM 1 +#define WITH_READLINE 1 +/* #undef WITH_TUN */ +#define WITH_PTY 1 +#define WITH_EXT2 1 +#define WITH_OPENSSL 1 +#define WITH_STREAMS 1 +/* #undef WITH_FIPS */ +/* #undef OPENSSL_FIPS */ +#define WITH_LIBWRAP 1 +#define HAVE_TCPD_H 1 +#define HAVE_LIBWRAP 1 + +#define WITH_SYCLS 1 +#define WITH_FILAN 1 +#define WITH_RETRY 1 + +#define WITH_MSGLEVEL 0 + +#endif /* !defined(__config_h_included) */ diff --git a/Config/config.SunOS-5-10.h b/Config/config.SunOS-5-10.h new file mode 100644 index 0000000..1745c80 --- /dev/null +++ b/Config/config.SunOS-5-10.h @@ -0,0 +1,522 @@ +/* config.h. Generated from config.h.in by configure. */ +/* source: config.h.in */ +/* Copyright Gerhard Rieger 2001-2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +#ifndef __config_h_included +#define __config_h_included 1 + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define if your struct stat has st_blksize. */ +#define HAVE_ST_BLKSIZE 1 + +/* Define if your struct stat has st_blocks. */ +#define HAVE_ST_BLOCKS 1 + +/* Define if your struct stat has st_rdev. */ +#define HAVE_ST_RDEV 1 + +/* Define if you have the strftime function. */ +#define HAVE_STRFTIME 1 + +/* Define if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to `int' if doesn't define. */ +/* #undef mode_t */ + +/* Define to `long' if doesn't define. */ +/* #undef off_t */ + +/* Define to `int' if doesn't define. */ +/* #undef pid_t */ + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the poll function. */ +#define HAVE_POLL 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtod function. */ +#define HAVE_STRTOD 1 + +/* Define if you have the strtol function. */ +#define HAVE_STRTOL 1 + +/* Define if you have the strtoul function. */ +#define HAVE_STRTOUL 1 + +/* Define if you have the uname function. */ +#define HAVE_UNAME 1 + +/* Define if you have the getpgid function. */ +#define HAVE_GETPGID 1 + +/* Define if you have the getsid function. */ +#define HAVE_GETSID 1 + +/* Define if you have the nanosleep function. */ +#define HAVE_NANOSLEEP 1 + +/* Define if you have the getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define if you have the getipnodebyname function. */ +#define HAVE_GETIPNODEBYNAME 1 + +/* Define if you have the setgroups function. */ +#define HAVE_SETGROUPS 1 + +/* Define if you have the inet_aton function. */ +#define HAVE_INET_ATON 1 + +/* Define if you have the memrchr function. */ +/* #undef HAVE_MEMRCHR */ + +/* Define if you have the if_indextoname function. */ +#define HAVE_IF_INDEXTONAME 1 + +/* Define if you have the sigaction function */ +#define HAVE_SIGACTION 1 + +/* Define if you have the stat64 function */ +#define HAVE_STAT64 1 + +/* Define if you have the fstat64 function */ +#define HAVE_FSTAT64 1 + +/* Define if you have the lstat64 function */ +#define HAVE_LSTAT64 1 + +/* Define if you have the lseek64 function */ +#define HAVE_LSEEK64 1 + +/* Define if you have the truncate64 function */ +#define HAVE_TRUNCATE64 1 + +/* Define if you have the ftruncate64 function */ +#define HAVE_FTRUNCATE64 1 + +/* Define if you have the strtoll function */ +#define HAVE_STRTOLL 1 + +/* Define if you have the hstrerror function */ +#define HAVE_HSTRERROR 1 + +/* Define if you have the inet_ntop function */ +#define HAVE_INET_NTOP 1 + +/* Define if you have the hstrerror prototype */ +#define HAVE_PROTOTYPE_HSTRERROR 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define if you have the header file. */ +#define HAVE_GRP_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_PTY_H */ + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_SYSTM_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP6_H 1 + +/* Define if you have the header file. */ +#define HAVE_ARPA_NAMESER_H 1 + +/* Define if you have the header file. */ +#define HAVE_RESOLV_H 1 + +/* Define if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_DL_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_TYPES_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_ERRQUEUE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_IF_TUN_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETPACKET_PACKET_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET_IF_ETHER_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_SELECT_H 1 + +/* Define if you have the header file. (AIX) */ +#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. (NetBSD, OpenBSD: openpty()) */ +/* #undef HAVE_UTIL_H */ + +/* Define if you have the header file. (FreeBSD: openpty()) */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define if you have the header file. (stream opts on SunOS)*/ +#define HAVE_SYS_STROPTS_H 1 + +/* Define if you have the header file. */ +#define HAVE_REGEX_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_FS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_EXT2_FS_H */ + +/* Define if you have the header file. */ +#define HAVE_READLINE_READLINE_H 1 + +/* Define if you have the header file. */ +#define HAVE_READLINE_HISTORY_H 1 + +/* Define if you have the readline library. */ +#define HAVE_LIBREADLINE 1 + +/* Define if you have the m library (-lm). */ +/* #undef HAVE_LIBM */ + +/* Define if you have the floor function */ +/* #undef HAVE_FLOOR */ + +/* some platforms need _XOPEN_EXTENDED_SOURCE to get syslog headers (AIX4.1) */ +/* #undef _XOPEN_EXTENDED_SOURCE */ + +/* fdset may have component fds_bits or __fds_bits */ +#define HAVE_FDS_BITS 1 + +/* Define if you have the sa_family_t */ +#define HAVE_TYPE_SA_FAMILY_T 1 + +/* define if your struct sigaction has sa_sigaction */ +#define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1 + +/* Define if your struct termios has component c_ispeed */ +/* #undef HAVE_TERMIOS_ISPEED */ + +/* the offset of c_ispeed in struct termios - usable in an speed_t array. + Applies only when HAVE_TERMIOS_ISPEED is set */ +/* #undef ISPEED_OFFSET */ + +/* the offset of c_ospeed in struct termios - see ISPEED_OFFSET */ +#ifdef ISPEED_OFFSET +# define OSPEED_OFFSET (ISPEED_OFFSET+1) +#else +/* # undef OSPEED_OFFSET */ +#endif + +/* Define if your termios.h likes _SVID3 defined */ +/* #undef _SVID3 */ + +/* Define if you have struct timespec (e.g. for nanosleep) */ +#define HAVE_STRUCT_TIMESPEC 1 + +/* Define if you have struct linger */ +#define HAVE_STRUCT_LINGER 1 + +/* Define if you have struct ip_mreq */ +#define HAVE_STRUCT_IP_MREQ 1 + +/* Define if you have struct ip_mreqn */ +/* #undef HAVE_STRUCT_IP_MREQN */ + +/* Define if you have struct ipv6_mreq */ +#define HAVE_STRUCT_IPV6_MREQ 1 + +/* Define if you have struct ifreq */ +#define HAVE_STRUCT_IFREQ 1 + +/* Define if you have struct ifreq.ifr_index */ +#define HAVE_STRUCT_IFREQ_IFR_INDEX 1 + +/* Define if you have struct ifreq.ifr_ifindex; not on HPUX */ +/* #undef HAVE_STRUCT_IFREQ_IFR_IFINDEX */ + +/* Define if your struct sockaddr has sa_len */ +/* #undef HAVE_STRUCT_SOCKADDR_SALEN */ + +/* there are several implementations of sockaddr_in6 */ +#define HAVE_IP6_SOCKADDR 0 + +/* Define if you have struct iovec */ +#define HAVE_STRUCT_IOVEC 1 + +/* define if your struct msghdr has msg_control */ +/* #undef HAVE_STRUCT_MSGHDR_MSGCONTROL */ + +/* define if your struct msghdr has msg_controllen */ +/* #undef HAVE_STRUCT_MSGHDR_MSGCONTROLLEN */ + +/* define if your struct msghdr has msg_flag */ +/* #undef HAVE_STRUCT_MSGHDR_MSGFLAGS */ + +/* define if you have struct cmsghdr */ +#define HAVE_STRUCT_CMSGHDR 1 + +/* define if you have struct in_pktinfo */ +/* #undef HAVE_STRUCT_IN_PKTINFO */ + +/* define if your struct ip has ip_hl; otherwise assume ip_vhl */ +#define HAVE_STRUCT_IP_IP_HL 1 + +/* Define if you have the setenv function */ +#define HAVE_SETENV 1 + +/* Define if you have the unsetenv function. not on HP-UX */ +#define HAVE_UNSETENV 1 + +/* Define if you have the flock function */ +/* #undef HAVE_FLOCK */ + +/* Define if you have the openpty function */ +/* #undef HAVE_OPENPTY */ + +/* Define if you have the grantpt function */ +#define HAVE_GRANTPT 1 + +/* Define if you have the unlockpt function */ +#define HAVE_UNLOCKPT 1 + +/* Define if you have the ptsname function */ +#define HAVE_PTSNAME 1 + +/* Define if you have the /dev/ptmx pseudo terminal multiplexer */ +#define HAVE_DEV_PTMX 1 + +/* Define if you have the /dev/ptc pseudo terminal multiplexer */ +/* #undef HAVE_DEV_PTC */ + +/* Define if you have the long long type */ +#define HAVE_TYPE_LONGLONG 1 + +/* is socklen_t already typedef'd? */ +#define HAVE_TYPE_SOCKLEN 1 + +/* Define if you have the struct stat64 type */ +#define HAVE_TYPE_STAT64 1 + +/* Define if you have the struct off64_t type */ +#define HAVE_TYPE_OFF64 1 + +/* is sighandler_t already typedef'd? */ +/* #undef HAVE_TYPE_SIGHANDLER */ + +/* is uint8_t already defined? */ +#define HAVE_TYPE_UINT8 1 + +/* is uint16_t already defined? */ +#define HAVE_TYPE_UINT16 1 + +/* is uint32_t already defined? */ +#define HAVE_TYPE_UINT32 1 + +/* is uint64_t already defined? */ +#define HAVE_TYPE_UINT64 1 + +/* Define if you have the printf "Z" modifier */ +/* #undef HAVE_FORMAT_Z */ + +/* Define the shift offset of the CRDLY mask */ +#define CRDLY_SHIFT 9 + +/* Define the shift offset of the TABDLY mask */ +#define TABDLY_SHIFT 11 + +/* Define the shift offset of the CSIZE mask */ +#define CSIZE_SHIFT 4 + +/* Define if you have tcpwrappers (libwrap, tcpd) and it declares hosts_allow_table */ +#define HAVE_HOSTS_ALLOW_TABLE 1 +#if defined(HAVE_HOSTS_ALLOW_TABLE) && HAVE_HOSTS_ALLOW_TABLE +# define HAVE_HOSTS_DENY_TABLE 1 +#else +/* # undef HAVE_HOSTS_DENY_TABLE */ +#endif + +/* 1..short, 3..int, 5..long; 2,4,6..unsigned */ +#define HAVE_BASIC_SIZE_T 4 /* unsigned int */ +#define HAVE_BASIC_MODE_T 6 /* unsigned long */ +#define HAVE_BASIC_PID_T 5 /* long */ +#define HAVE_BASIC_UID_T 5 /* long */ +#define HAVE_BASIC_GID_T 5 /* long */ +#define HAVE_BASIC_TIME_T 5 /* long */ +#define HAVE_BASIC_OFF64_T 7 /* long long */ + +#define HAVE_BASIC_SOCKLEN_T 4 /* unsigned int */ + +#define HAVE_TYPEOF_ST_DEV 6 /* unsigned long */ +#define HAVE_TYPEOF_ST_INO 6 /* unsigned long */ +#define HAVE_TYPEOF_ST_NLINK 6 /* unsigned long */ +#define HAVE_TYPEOF_ST_SIZE 5 /* long */ +#define HAVE_TYPEOF_ST_BLKSIZE 5 /* long */ +#define HAVE_TYPEOF_ST_BLOCKS 5 /* long */ + +#define HAVE_TYPEOF_ST64_DEV 6 /* unsigned long */ +#define HAVE_TYPEOF_ST64_INO 8 /* unsigned long long */ +#define HAVE_TYPEOF_ST64_NLINK 6 /* unsigned long */ +#define HAVE_TYPEOF_ST64_SIZE 7 /* long long */ +#define HAVE_TYPEOF_ST64_BLKSIZE 5 /* long */ +#define HAVE_TYPEOF_ST64_BLOCKS 7 /* long long */ + +#define HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC 5 /* long */ + +#define HAVE_TYPEOF_RLIM_MAX 6 /* unsigned long */ + +/* Define if you have the /proc filesystem */ +#define HAVE_PROC_DIR 1 + +/* Define if you have the /proc/$$/fd directories */ +#define HAVE_PROC_DIR_FD 1 + +#define WITH_HELP 1 +#define WITH_STDIO 1 +#define WITH_FDNUM 1 +#define WITH_FILE 1 +#define WITH_CREAT 1 +#define WITH_GOPEN 1 +#define WITH_TERMIOS 1 +#define WITH_PIPE 1 +#define WITH_UNIX 1 +/* #undef WITH_ABSTRACT_UNIXSOCKET */ +#define WITH_IP4 1 +#define WITH_IP6 1 +#define WITH_RAWIP 1 +#define WITH_GENERICSOCKET 1 +/* #undef WITH_INTERFACE */ +#define WITH_TCP 1 +#define WITH_UDP 1 +#define WITH_SCTP 1 +#define WITH_LISTEN 1 +#define WITH_SOCKS4 1 +#define WITH_SOCKS4A 1 +#define WITH_PROXY 1 +#define WITH_EXEC 1 +#define WITH_SYSTEM 1 +#define WITH_READLINE 1 +/* #undef WITH_TUN */ +#define WITH_PTY 1 +#define WITH_EXT2 1 +#define WITH_OPENSSL 1 +#define WITH_STREAMS 1 +/* #undef WITH_FIPS */ +/* #undef OPENSSL_FIPS */ +#define WITH_LIBWRAP 1 +#define HAVE_TCPD_H 1 +#define HAVE_LIBWRAP 1 + +#define WITH_SYCLS 1 +#define WITH_FILAN 1 +#define WITH_RETRY 1 + +#define WITH_MSGLEVEL 0 + +#endif /* !defined(__config_h_included) */ diff --git a/EXAMPLES b/EXAMPLES index 00fc20e..0fd34c6 100644 --- a/EXAMPLES +++ b/EXAMPLES @@ -37,6 +37,16 @@ $ socat -,raw,echo=0 tcp:172.16.181.130:2023 // replace /bin/login by /bin/bash when using SSL client authentication, can be // run without root then +// this is a cool trick, proposed by Christophe Lohr, to dump communications to +// two files; it would also work for other manipulations (recode, compress...) +// and it might also work with netcat ;-) +$ socat TCP-LISTEN:5555 SYSTEM:'tee l2r | socat - "TCP:remote:5555" | tee r2l' + +/////////////////////////////////////////////////////////////////////////////// +// emergence solution because usleep(1) is not always available +// this will "sleep" for 0.1s +$ socat -T 0.1 pipe pipe + /////////////////////////////////////////////////////////////////////////////// // a very primitive HTTP/1.0 echo server (problems: sends reply headers before // request; hangs if client does not shutdown - HTTP keep-alive) @@ -45,6 +55,11 @@ $ socat -,raw,echo=0 tcp:172.16.181.130:2023 // incoming data back to client $ socat TCP-LISTEN:8000,crlf SYSTEM:"echo HTTP/1.0 200; echo Content-Type\: text/plain; echo; cat" +// a less primitive HTTP echo server that sends back not only the reqest but +// also server and client address and port. Might have portability issues with +// echo +./socat -T 1 -d -d tcp-l:10081,reuseaddr,fork,crlf system:"echo -e \"\\\"HTTP/1.0 200 OK\\\nDocumentType: text/html\\\n\\\ndate: \$\(date\)
server:\$SOCAT_SOCKADDR:\$SOCAT_SOCKPORT
client: \$SOCAT_PEERADDR:\$SOCAT_PEERPORT\\\n
\\\"\"; cat; echo -e \"\\\"\\\n
\\\"\"" + /////////////////////////////////////////////////////////////////////////////// // for communicating with an attached modem, I had reasonable results with // following command line. Required privileges depend on device mode. @@ -285,6 +300,29 @@ $ socat -d -d -d -d - udp-datagram:224.0.0.2:6666,bind=:6666,ip-add-membership=2 // packets leave via wrong interface (set route: ...) // socket bound to specific address +//============================================================================= +// GENERIC FUNCTION CALLS + +// ioctl(): open CD drive (given value valid on Linux) +// on my Linux system I find in /usr/include/linux/cdrom.h the define: +// #define CDROMEJECT 0x5309 /* Ejects the cdrom media */ +// the following command makes something like ioctl(fd, CDROMEJECT, NULL) +// (don't care about the read error): +$ socat /dev/cdrom,o-nonblock,ioctl-void=0x5309 - + +// setsockopt(): SO_REUSEADDR +// the following command performs - beyond lots of overhead - something like: +// myint=1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &myint, sizeof(myint)) +$ socat -u udp-recv:7777,setsockopt-int=1:2:1 - +// setsockopt(): SO_BINDTODEVICE + +// ways to apply SO_BINDTODEVICE without using the special socat address option +// so-bindtodevice: +// with string argument: +$ sudo ./socat tcp-l:7777,setsockopt-string=1:25:eth0 pipe +// with binary argument: +$ sudo ./socat tcp-l:7777,setsockopt-bin=1:25:x6574683000 pipe + =============================================================================== // not tested, just ideas, or have problems diff --git a/Makefile.in b/Makefile.in index 684c5bf..12c9b32 100644 --- a/Makefile.in +++ b/Makefile.in @@ -15,6 +15,7 @@ exec_prefix = @exec_prefix@ BINDEST = @bindir@ +datarootdir = @datarootdir@ MANDEST = @mandir@ srcdir = @srcdir@ @@ -44,10 +45,12 @@ XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.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-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-socks5.c xio-proxy.c xio-udp.c \ - xio-rawip.c \ + xio-socket.c xio-interface.c xio-listen.c xio-unix.c \ + xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \ + xio-sctp.c xio-rawip.c \ + xio-socks.c xio-socks5.c xio-proxy.c xio-udp.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-streams.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) @@ -60,27 +63,28 @@ PROGS = socat procan filan HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h compat.h \ xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.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-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-socks5.h xio-proxy.h xio-progcall.h xio-exec.h \ + xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h \ + xio-socket.h xio-interface.h xio-listen.h xio-unix.h \ + xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \ + xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.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-pty.h xio-openssl.h \ + xio-pty.h xio-openssl.h xio-streams.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.yo 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.yo 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 doc/socat-genericsocket.html SHFILES = daemon.sh mail.sh ftp.sh readline.sh TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \ proxy.sh socks4a-echo.sh testcert.conf -#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.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.FreeBSD-6-1 Config/config.FreeBSD-6-1.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.Tru64-5-1B Config/config.Tru64-5-1B.h - +OSFILES = Config/Makefile.Linux-2-6-24 Config/config.Linux-2-6-24.h \ + Config/Makefile.SunOS-5-10 Config/config.SunOS-5-10.h \ + Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \ + Config/Makefile.NetBSD-4-0 Config/config.NetBSD-4-0.h \ + Config/Makefile.OpenBSD-4-3 Config/config.OpenBSD-4-3.h \ + Config/Makefile.AIX-5-3 Config/config.AIX-5-3.h \ + Config/Makefile.Cygwin-1-5-25 Config/config.Cygwin-1-5-25.h \ + Config/Makefile.MacOSX-10-5 Config/config.MacOSX-10-5.h all: progs doc @@ -98,7 +102,7 @@ doc/socat.1: doc/socat.yo yodl2man -o $@ $+ doc/socat.html: doc/socat.yo - yodl2html -o $@ $+ + cd doc; yodl2html -o socat.html socat.yo; cd .. progs: $(PROGS) @@ -125,13 +129,13 @@ doc: doc/xio.help strip: progs strip $(PROGS) -install: progs doc/socat.1 +install: progs $(srcdir)/doc/socat.1 mkdir -p $(DESTDIR)$(BINDEST) $(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST) $(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST) $(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST) mkdir -p $(DESTDIR)$(MANDEST)/man1 - $(INSTALL) -m 644 doc/socat.1 $(DESTDIR)$(MANDEST)/man1/ + $(INSTALL) -m 644 $(srcdir)/doc/socat.1 $(DESTDIR)$(MANDEST)/man1/ uninstall: rm -f $(DESTDIR)$(BINDEST)/socat diff --git a/README b/README index 6baad77..f92849d 100644 --- a/README +++ b/README @@ -45,28 +45,27 @@ distributions. platforms --------- -socat 1.6.0 was compiled and more or less successfully tested under the +socat 1.7.0 was compiled and more or less successfully tested under the following operating systems: -SuSE Linux 10.1 on x86 -AIX 5.2 on PPC with gcc -Solaris 9 on Sparc with gcc +Debian lenny/sid on x86, kernel 2.6.24 FreeBSD 6.1 on x86 -HP-UX B 11.11 on PA-RISC with gcc +NetBSD4.0 on x86 +OpenBSD 4.3 on x86 +OpenSolaris 10 on x86 with gcc +Mac OS X 10.5.5 on iMac G5, with libreadline +HP-UX 11.23 +AIX 5.3 on 64bit Power4 with gcc +Cygwin 1.5.25 on i686 tests on Tru64 can no longer be performed because HP testdrive has taken down these hosts. -tests on Mac OS X can no longer be performed because the Sourceforge -compilefarm was discontinued. - -tests on NetBSD and OpenBSD can no longer be performed for the above reasons. - Some versions of socat have been reported to successfully compile under older Linux versions back to RedHat 2.1 (kernel 1.2.13, gcc 2.7.0), under AIX 4.1 and 4.3, SunOS 5.7-5.8, FreeBSD 4.2 - 4.9, MacOS X 10.1, Cygwin, Solaris 8 on x86, -OSR 5.0.6, NetBSD 1.6.1 and 2.0.2, OpenBSD 3.4 and 3.8, Tru64 5.1B, and Mac OS -X 10.1-10.2. +OSR 5.0.6, NetBSD 1.6.1 and 2.0.2, OpenBSD 3.4 and 3.8, Tru64 5.1B, Mac OS X +10.1-10.2, and HP-UX 11 It might well compile and run under other UNIX like operating systems. @@ -76,7 +75,7 @@ install Get the tarball and extract it: gtar xzf socat.tar.gz - cd socat-1.6.0.1 + cd socat-1.7.0.0 ./configure make su @@ -180,12 +179,24 @@ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/sfw/lib For some shell scripts, it is preferable to have /usr/xpg4/bin at a prominent position in $PATH. +With the default compiler define _GNU_SOURCE, the CMSG_* macros are not +available, and therefore ancillary messages cannot be used. To enable these try +the following: +After running ./configure, edit Makefile and replace "-D_GNU_SOURCE" with +"-D_XPG4_2 -D__EXTENSIONS__" and run make + platform specifics - hp-ux -------------------------- +Ancillary messages cannot be compiled in with socat: both struct msghdr and +strutc cmsghdr are required. Compiling with -D_XOPEN_SOURCE_EXTENDED provides +struct msghdr but disables struct cmsghdr while -D_OPEN_SOURCE disables struct +msghdr but disables struct cmsghdr. Please contact socat development if you +know a solution. + Shutting down the write channel of a UNIX domain socket does not seem to -trigger an EOF on the other socket. This makes problems with the exec and +trigger an EOF on the peer socket. This makes problems with the exec and system addresses. This OS provides the type "long long", but not the strtoll() function to read diff --git a/VERSION b/VERSION index 7f61be2..35fad60 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -"2.0.0-b1" +"2.0.0-b2" diff --git a/compat.h b/compat.h index 64e5fe6..bbde6fe 100644 --- a/compat.h +++ b/compat.h @@ -604,6 +604,10 @@ # define NETDB_INTERNAL h_NETDB_INTERNAL #endif +#ifndef INET_ADDRSTRLEN +# define INET_ADDRSTRLEN sizeof(struct sockaddr_in) +#endif + #if !HAVE_PROTOTYPE_HSTRERROR /* with MacOSX this is char * */ extern const char *hstrerror(int); diff --git a/config.h.in b/config.h.in index 02630e7..5e9f7f2 100644 --- a/config.h.in +++ b/config.h.in @@ -1,5 +1,5 @@ /* source: config.h.in */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __config_h_included @@ -107,6 +107,9 @@ /* Define if you have the memrchr function. */ #undef HAVE_MEMRCHR +/* Define if you have the if_indextoname function. */ +#undef HAVE_IF_INDEXTONAME + /* Define if you have the sigaction function */ #undef HAVE_SIGACTION @@ -224,9 +227,24 @@ /* Define if you have the header file. */ #undef HAVE_NET_IF_H +/* Define if you have the header file. */ +#undef HAVE_NET_IF_DL_H + +/* Define if you have the header file. */ +#undef HAVE_LINUX_TYPES_H + +/* Define if you have the header file. */ +#undef HAVE_LINUX_ERRQUEUE_H + /* Define if you have the header file. */ #undef HAVE_LINUX_IF_TUN_H +/* Define if you have the header file. */ +#undef HAVE_NETPACKET_PACKET_H + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + /* Define if you have the header file. */ #undef HAVE_SYS_UTSNAME_H @@ -275,6 +293,12 @@ /* fdset may have component fds_bits or __fds_bits */ #undef HAVE_FDS_BITS +/* Define if you have the sa_family_t */ +#undef HAVE_TYPE_SA_FAMILY_T + +/* define if your struct sigaction has sa_sigaction */ +#undef HAVE_STRUCT_SIGACTION_SA_SIGACTION + /* Define if your struct termios has component c_ispeed */ #undef HAVE_TERMIOS_ISPEED @@ -313,7 +337,7 @@ /* Define if you have struct ifreq.ifr_index */ #undef HAVE_STRUCT_IFREQ_IFR_INDEX -/* Define if you have struct ifreq.ifr_ifindex */ +/* Define if you have struct ifreq.ifr_ifindex; not on HPUX */ #undef HAVE_STRUCT_IFREQ_IFR_IFINDEX /* Define if your struct sockaddr has sa_len */ @@ -334,12 +358,21 @@ /* define if your struct msghdr has msg_flag */ #undef HAVE_STRUCT_MSGHDR_MSGFLAGS +/* define if you have struct cmsghdr */ +#undef HAVE_STRUCT_CMSGHDR + +/* define if you have struct in_pktinfo */ +#undef HAVE_STRUCT_IN_PKTINFO + /* define if your struct ip has ip_hl; otherwise assume ip_vhl */ #undef HAVE_STRUCT_IP_IP_HL /* Define if you have the setenv function */ #undef HAVE_SETENV +/* Define if you have the unsetenv function. not on HP-UX */ +#undef HAVE_UNSETENV + /* Define if you have the flock function */ #undef HAVE_FLOCK @@ -458,8 +491,11 @@ #undef WITH_IP4 #undef WITH_IP6 #undef WITH_RAWIP +#undef WITH_GENERICSOCKET +#undef WITH_INTERFACE #undef WITH_TCP #undef WITH_UDP +#undef WITH_SCTP #undef WITH_LISTEN #undef WITH_SOCKS4 #undef WITH_SOCKS4A @@ -473,6 +509,7 @@ #undef WITH_PTY #undef WITH_EXT2 #undef WITH_OPENSSL +#define WITH_STREAMS 1 #undef WITH_FIPS #undef OPENSSL_FIPS #undef WITH_LIBWRAP diff --git a/configure.in b/configure.in index e723554..c1352fb 100644 --- a/configure.in +++ b/configure.in @@ -55,13 +55,26 @@ AC_CHECK_HEADERS(pwd.h grp.h stdint.h sys/types.h sys/poll.h sys/socket.h sys/ui AC_CHECK_HEADERS(pty.h) AC_CHECK_HEADERS(netinet/in.h netinet/in_systm.h netinet/ip.h netinet/tcp.h) AC_CHECK_HEADERS(netinet6/in6.h) # found on OpenBSD, used for IPV6_* -AC_CHECK_HEADERS(arpa/nameser.h resolv.h) -AC_CHECK_HEADERS(termios.h net/if.h linux/if_tun.h) +AC_CHECK_HEADERS(net/if.h, [], [], [AC_INCLUDES_DEFAULT + #if HAVE_SYS_SOCKET_H + #include + #endif]) # Mac OS X requires including sys/socket.h +AC_CHECK_HEADERS(arpa/nameser.h) + +AC_HEADER_RESOLV() + +AC_CHECK_HEADERS(termios.h linux/if_tun.h) +AC_CHECK_HEADERS(net/if_dl.h) +AC_CHECK_HEADERS(linux/types.h linux/errqueue.h) AC_CHECK_HEADERS(sys/utsname.h sys/select.h sys/file.h) AC_CHECK_HEADERS(util.h libutil.h sys/stropts.h regex.h) AC_CHECK_HEADERS(linux/fs.h linux/ext2_fs.h) +dnl Link libresolv if necessary (for Mac OS X) +AC_SEARCH_LIBS([res_9_init], [resolv]) + + dnl Check for extra socket library (for Solaris) AC_CHECK_FUNC(hstrerror, , AC_CHECK_LIB(resolv, hstrerror, [LIBS="$LIBS -lresolv"; AC_DEFINE(HAVE_HSTRERROR)])) AC_CHECK_FUNC(gethostent, , AC_CHECK_LIB(nsl, gethostent)) @@ -201,7 +214,11 @@ AC_ARG_ENABLE(ip6, [ --disable-ip6 disable IPv6 support], if test "$WITH_IP6"; then AC_CHECK_HEADERS([netinet/ip6.h], [AC_DEFINE(HAVE_NETINET_IP6_H) AC_DEFINE(WITH_IP6)], - [AC_MSG_WARN([include file netinet/ip6.h not found, disabling IP6])]) + [AC_MSG_WARN([include file netinet/ip6.h not found, disabling IP6])], + [AC_INCLUDES_DEFAULT + #ifdef HAVE_NETINET_IN_H + # include + #endif]) fi AC_MSG_CHECKING(whether to include raw IP support) @@ -212,6 +229,36 @@ AC_ARG_ENABLE(rawip, [ --disable-rawip disable raw IP support], esac], [AC_DEFINE(WITH_RAWIP) AC_MSG_RESULT(yes)]) +AC_MSG_CHECKING(whether to include generic socket support) +AC_ARG_ENABLE(rawsocket, [ --disable-genericsocket disable generic socket support], + [case "$enableval" in + no) AC_MSG_RESULT(no);; + *) AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes);; + esac], + [AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes)]) +AC_MSG_CHECKING(whether to include raw network interface support) +AC_ARG_ENABLE(interface, [ --disable-interface disable network interface support], + [case "$enableval" in + no) AC_MSG_RESULT(no); WITH_INTERFACE= ;; + *) AC_MSG_RESULT(yes); WITH_INTERFACE=1 ;; + esac], + [AC_MSG_RESULT(yes); WITH_INTERFACE=1 ]) +if test "$WITH_INTERFACE"; then + AC_CHECK_HEADER(netpacket/packet.h, + AC_DEFINE(HAVE_NETPACKET_PACKET_H), + [WITH_INTERFACE=; + AC_MSG_WARN([include file netpacket/packet.h not found, disabling interface])]) +fi +if test "$WITH_INTERFACE"; then + AC_CHECK_HEADER(netinet/if_ether.h, + AC_DEFINE(HAVE_NETINET_IF_ETHER_H), + [WITH_INTERFACE=; + AC_MSG_WARN([include file netinet/if_ether.h not found, disabling interface])]) +fi +if test "$WITH_INTERFACE"; then + AC_DEFINE(WITH_INTERFACE) +fi + AC_MSG_CHECKING(whether to include TCP support) AC_ARG_ENABLE(tcp, [ --disable-tcp disable TCP support], [case "$enableval" in @@ -228,6 +275,30 @@ AC_ARG_ENABLE(udp, [ --disable-udp disable UDP support], esac], [AC_DEFINE(WITH_UDP) AC_MSG_RESULT(yes)]) +AC_MSG_CHECKING(whether to include SCTP support) +AC_ARG_ENABLE(sctp, [ --disable-sctp disable SCTP support], + [case "$enableval" in + no) AC_MSG_RESULT(no); WITH_SCTP= ;; + *) AC_MSG_RESULT(yes); WITH_SCTP=1 ;; + esac], + [AC_MSG_RESULT(yes); WITH_SCTP=1 ]) + +if test -n "$WITH_SCTP"; then +AC_MSG_CHECKING(for IPPROTO_SCTP) +AC_CACHE_VAL(sc_cv_define_ipproto_sctp, +[AC_TRY_COMPILE([#include +#include ], +[IPPROTO_SCTP;], +[sc_cv_define_ipproto_sctp=yes], +[sc_cv_define_ipproto_sctp=no])]) +AC_MSG_RESULT($sc_cv_define_ipproto_sctp) +if test $sc_cv_define_ipproto_sctp = yes; then + AC_DEFINE(WITH_SCTP) +else + AC_MSG_WARN([IPPROTO_SCTP undefined, disabling SCTP support]) +fi +fi + AC_MSG_CHECKING(whether to include listen support) AC_ARG_ENABLE(listen, [ --disable-listen disable listen support], [case "$enableval" in @@ -300,93 +371,56 @@ AC_ARG_ENABLE(readline, [ --disable-readline disable readline support], esac], [AC_MSG_RESULT(yes); WITH_READLINE=1 ]) -# check if we find the components of GNU readline if test -n "$WITH_READLINE"; then - # first, we need to find the include file - AC_MSG_NOTICE(checking for components of readline) - #AC_CHECK_HEADERS(readline/readline.h readline/history.h) - AC_CACHE_VAL(sc_cv_have_readline_h, - [AC_TRY_COMPILE([#include /* FreeBSD needs "FILE *" */ -#include -#include ],[;], - [sc_cv_have_readline_h=yes; READLINE_ROOT=""; ], - [sc_cv_have_readline_h=no - for D in "/sw" "/usr/local" "/opt/freeware" "/usr/sfw"; do - I="$D/include" - i="$I/readline/readline.h" - if test -r "$i"; then - #V_INCL="$V_INCL -I$I/" - CPPFLAGS="$CPPFLAGS -I$I" - AC_MSG_NOTICE(found $i) - sc_cv_have_readline_h=yes; READLINE_ROOT="$D" - break; - fi - done]) - ]) - if test "$sc_cv_have_readline_h" = "yes"; then - AC_DEFINE(HAVE_READLINE_READLINE_H) - AC_DEFINE(HAVE_READLINE_HISTORY_H) - fi - AC_MSG_NOTICE(checked for readline.h... $sc_cv_have_readline_h) -fi # end checking for readline.h -# -if test -n "$WITH_READLINE" -a "$sc_cv_have_readline_h" = yes; then - # next, we search for the readline library (libreadline.*) - AC_MSG_CHECKING(for libreadline) - AC_CACHE_VAL(sc_cv_have_libreadline, - [ LIBS0="$LIBS" - if test -n "$READLINE_ROOT"; then - L="$READLINE_ROOT/lib"; LIBS="$LIBS0 -L$L -lreadline" - else - LIBS="$LIBS0 -lreadline" - fi - AC_TRY_LINK([#include /* FreeBSD needs FILE * */ -#include -#include ], - [readline(NULL)], - [sc_cv_have_libreadline='yes'], - [sc_cv_have_libreadline='no' - LIBS1="$LIBS" - LIBS="$LIBS -lcurses" - AC_TRY_LINK([#include /* FreeBSD needs FILE * */ -#include -#include ], - [readline(NULL)], - [sc_cv_have_libreadline='yes'], - [sc_cv_have_libreadline='no' - LIBS="$LIBS1 -lncurses" # eg for SuSE52 - AC_TRY_LINK([#include /* FreeBSD needs FILE * */ -#include -#include ], - [readline(NULL)], - [sc_cv_have_libreadline='yes'], - [sc_cv_have_libreadline='no']) - ])] - ) - if test "$sc_cv_have_libreadline" != 'yes'; then - LIBS="$LIBS0" - fi - ] -#! missing libcurses dependency; missing freeware places -# # we test if libcurses is available and if it can be used without further libs -# AC_CHECK_LIB(ncurses, main, , AC_CHECK_LIB(curses, main)) # some Linux work with this -# # we test if readline can be used without further libs -# AC_CHECK_LIB(readline, readline) -# # we see if using_history() is already in $LIBS; if not, we try it with curses -# AC_CHECK_FUNC(using_history, , AC_CHECK_LIB(history, using_history,,, -lcurses)) -#fi - ) - if test "$sc_cv_have_libreadline" = 'yes'; then - AC_DEFINE(HAVE_LIBREADLINE) - fi - AC_MSG_RESULT($sc_cv_have_libreadline) -fi -# -if test -n "$WITH_READLINE"; then - if test "$sc_cv_have_readline_h" = "yes" -a "$sc_cv_have_libreadline" = "yes"; then - AC_DEFINE(WITH_READLINE) - else - AC_MSG_WARN([not all components of readline found, disabling it]); + CPPFLAGS_ORIG=$CPPFLAGS + CFLAGS_ORIG=$CFLAGS + LIBS_ORIG=$LIBS + sc_usable_readline_found= + + for D in "" "/usr/local" "/opt/local" "/sw" "/opt/freeware" "/usr/sfw"; do + if test -n "$D" ; then + CPPFLAGS="$CPPFLAGS -I$D/include" + CFLAGS="$CFLAGS -L$D/lib" + DLOC="in location $D" + else + DLOC="in default location" + fi + AC_MSG_CHECKING(for usable readline $DLOC) + + # Some systems require -lcurses, some require -lncurses. + # Mac OS X 10.4 (and others) ships with libedit masquerading as readline, + # but it doesn't work well with socat. It can be recognized by the absence + # of append_history. + + for L in "" "-lcurses" "-lncurses"; do + LIBS="$LIBS_ORIG -lreadline $L" + AC_TRY_LINK( + [ #include + #include + #include ], + [ readline(NULL); + append_history(0, NULL); ], + [ sc_usable_readline_found=1 + break ]) + done + + if test -n "$sc_usable_readline_found"; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_READLINE_READLINE_H,1) + AC_DEFINE(HAVE_READLINE_HISTORY_H,1) + AC_DEFINE(HAVE_LIBREADLINE,1) + AC_DEFINE(WITH_READLINE,1) + break + else + AC_MSG_RESULT(no) + CPPFLAGS=$CPPFLAGS_ORIG + CFLAGS=$CFLAGS_ORIG + LIBS=$LIBS_ORIG + fi + done + + if test -z "$sc_usable_readline_found"; then + AC_MSG_WARN([no suitable version of readline found; perhaps you need to install a newer version]) fi fi @@ -577,13 +611,14 @@ AC_ARG_ENABLE(tun, [ --disable-tun disable TUN/TAP support], esac], [AC_MSG_RESULT(yes); WITH_TUN=1 ]) +# +if ! test "$ac_cv_header_linux_if_tun_h" = 'yes'; then + AC_MSG_WARN(include file linux/if_tun.h not found, disabling TUN) + WITH_TUN= +fi # if test -n "$WITH_TUN"; then - if test `uname` != Linux; then - AC_MSG_NOTICE(only on Linux) - else - AC_DEFINE(WITH_TUN) - fi + AC_DEFINE(WITH_TUN) fi AC_MSG_CHECKING(whether to include system call tracing) @@ -654,6 +689,7 @@ AC_FUNC_STRFTIME AC_CHECK_FUNCS(putenv select poll socket strdup strerror strstr strtod strtol) AC_CHECK_FUNCS(strtoul uname getpgid getsid getaddrinfo) AC_CHECK_FUNCS(getipnodebyname setgroups inet_aton memrchr) +AC_CHECK_FUNCS(if_indextoname) AC_CHECK_FUNCS(grantpt unlockpt ptsname) @@ -807,6 +843,27 @@ AC_TRY_COMPILE([#include [AC_MSG_RESULT(yes); AC_DEFINE(HAVE_FDS_BITS)], [AC_MSG_RESULT(no);]) +AC_MSG_CHECKING(for sa_family_t) +AC_CACHE_VAL(sc_cv_type_sa_family_t, +[AC_TRY_COMPILE([#include +#include ],[sa_family_t s;], +[sc_cv_type_sa_family_t=yes], +[sc_cv_type_sa_family_t=no])]) +if test $sc_cv_type_sa_family_t = yes; then + AC_DEFINE(HAVE_TYPE_SA_FAMILY_T) +fi +AC_MSG_RESULT($sc_cv_type_sa_family_t) + +AC_MSG_CHECKING(for struct sigaction.sa_sigaction) +AC_CACHE_VAL(sc_cv_struct_sigaction_sa_sigaction, +[AC_TRY_COMPILE([#include ],[struct sigaction s;s.sa_sigaction=0;], +[sc_cv_struct_sigaction_sa_sigaction=yes], +[sc_cv_struct_sigaction_sa_sigaction=no])]) +if test $sc_cv_struct_sigaction_sa_sigaction = yes; then + AC_DEFINE(HAVE_STRUCT_SIGACTION_SA_SIGACTION) +fi +AC_MSG_RESULT($sc_cv_struct_sigaction_sa_sigaction) + ### struct termios .c_ispeed AC_MSG_CHECKING(for termios.c_ispeed) AC_CACHE_VAL(sc_cv_termios_ispeed, @@ -1082,6 +1139,32 @@ if test $sc_cv_struct_msghdr_msgflags = yes; then fi AC_MSG_RESULT($sc_cv_struct_msghdr_msgflags) +dnl check for struct cmsghdr +AC_MSG_CHECKING(for struct cmsghdr) +AC_CACHE_VAL(sc_cv_struct_cmsghdr, +[AC_TRY_COMPILE([#include +#include +#include ],[struct cmsghdr s;], +[sc_cv_struct_cmsghdr=yes], +[sc_cv_struct_cmsghdr=no])]) +if test $sc_cv_struct_cmsghdr = yes; then + AC_DEFINE(HAVE_STRUCT_CMSGHDR) +fi +AC_MSG_RESULT($sc_cv_struct_cmsghdr) + +dnl check for struct in_pktinfo +AC_MSG_CHECKING(for struct in_pktinfo) +AC_CACHE_VAL(sc_cv_struct_in_pktinfo, +[AC_TRY_COMPILE([#include +#include +#include ],[struct in_pktinfo s;], +[sc_cv_struct_in_pktinfo=yes], +[sc_cv_struct_in_pktinfo=no])]) +if test $sc_cv_struct_in_pktinfo = yes; then + AC_DEFINE(HAVE_STRUCT_IN_PKTINFO) +fi +AC_MSG_RESULT($sc_cv_struct_in_pktinfo) + dnl check for ip_hl in struct ip AC_MSG_CHECKING(for struct ip.ip_hl) AC_CACHE_VAL(sc_cv_struct_ip_ip_hl, @@ -1153,6 +1236,9 @@ dnl Search for setenv() AC_CHECK_FUNC(setenv, AC_DEFINE(HAVE_SETENV), AC_CHECK_LIB(isode, setenv, [LIBS="-lisode $LIBS"])) +dnl Search for unsetenv() +AC_CHECK_FUNC(unsetenv, AC_DEFINE(HAVE_UNSETENV)) + dnl Run time checks @@ -1196,7 +1282,11 @@ AC_CACHE_CHECK(shift offset of $1, $2, if (n==0) {fprintf(stderr,"$1 is 0 (impossible!)\n"); exit(1);} i=0; while (!(n&1)) { n>>=1; ++i; } - fprintf(f, "%u", i); + if (3<], struct stat64, st_blksize, HAVE_TYP AC_TYPEOF_COMPONENT([#include ], struct stat64, st_blocks, HAVE_TYPEOF_ST64_BLOCKS, sc_cv_type_stat64_stblocks_basic) fi -AC_TYPEOF_COMPONENT([#include ], struct timeval, tv_usec, HAVE_TYPEOF_STRUCT_TIMEVAL_TVUSEC, sc_cv_type_struct_timeval_tvusec) +AC_TYPEOF_COMPONENT([#include ], struct timeval, tv_usec, HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC, sc_cv_type_struct_timeval_tv_usec) AC_TYPEOF_COMPONENT([#include #include diff --git a/dalan.c b/dalan.c index bc475cd..1d7334f 100644 --- a/dalan.c +++ b/dalan.c @@ -68,6 +68,7 @@ void dalan_init(void) { /* read data description from line, write result to data; do not write so much data that *p exceeds n ! + p must be initialized to 0. return 0 on success, -1 if the data was cut due to n limit, 1 if a syntax error occurred diff --git a/doc/dest-unreach.css b/doc/dest-unreach.css index b5dd82f..61a8dac 100644 --- a/doc/dest-unreach.css +++ b/doc/dest-unreach.css @@ -1,15 +1,9 @@ - - -dest-unreach.org stylesheet - - - - - diff --git a/doc/socat-multicast.html b/doc/socat-multicast.html index fc31f7b..829eba3 100644 --- a/doc/socat-multicast.html +++ b/doc/socat-multicast.html @@ -240,8 +240,7 @@ interfaces. This membership cannot be dropped on Linux. sockets without exception accept packets that are directly addressed to them; the multi- and broadcast receiving features are just extensions to the normal functionality. socat has no way to find out if an incoming packet is addressed -to a unicast, multicast or broadcast address. Please contact the author if you -know how the target address can be determined.

+to a unicast, multicast, or broadcast address.

Authentication or encryption are not available.

diff --git a/doc/socat.yo b/doc/socat.yo index 4befd5b..866b995 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -10,7 +10,7 @@ def(Filan)(0)(bf(Filan)) def(procan)(0)(bf(procan)) def(Procan)(0)(bf(Procan)) -manpage(socat)(1)(Feb 2008)(socat)() +manpage(socat)(1)(Oct 2008)()() whenhtml( label(CONTENTS) @@ -127,7 +127,8 @@ dit(bf(tt(-lf))tt( )) dit(bf(tt(-ls))) Writes messages to stderr (this is the default). label(option_lp)dit(bf(tt(-lp))tt()) - Overrides the program name printed in error messages. + Overrides the program name printed in error messages and used for + constructing environment variable names. dit(bf(tt(-lu))) Extends the timestamp of error messages to microsecond resolution. Does not work when logging to syslog. @@ -347,6 +348,15 @@ label(ADDRESS_IP_SENDTO)dit(bf(tt(IP-SENDTO::))) link(IP-RECV)(ADDRESS_IP_RECV), link(UDP-SENDTO)(ADDRESS_UDP_SENDTO) link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO) +label(ADDRESS_INTERFACE)dit(bf(tt(INTERFACE:))) + Communicate with a network connected on an interface using raw packets + including link level data. link()(TYPE_INTERFACE) is the name of + the network interface. Currently only available on Linux. + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET) nl() + Useful options: + link(pf)(OPTION_PROTOCOL_FAMILY) + link(type)(OPTION_SO_TYPE)nl() + See also: link(ip-recv)(ADDRESS_IP_RECV) label(ADDRESS_IP4_SENDTO)dit(bf(tt(IP4-SENDTO::))) Like link(IP-SENDTO)(ADDRESS_IP_SENDTO), but always uses IPv4.nl() Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4) nl() @@ -364,6 +374,7 @@ label(ADDRESS_IP_DATAGRAM)dit(bf(tt(IP-DATAGRAM:
:))) Option groups: link(FD)(GROUP_FD), link(SOCKET)(GROUP_SOCKET), link(IP4)(GROUP_IP4), link(IP6)(GROUP_IP6), link(RANGE)(GROUP_RANGE) nl() Useful options: + link(bind)(OPTION_BIND), link(range)(OPTION_RANGE), link(tcpwrap)(OPTION_TCPWRAPPERS), link(broadcast)(OPTION_SO_BROADCAST), @@ -373,7 +384,6 @@ label(ADDRESS_IP_DATAGRAM)dit(bf(tt(IP-DATAGRAM:
:))) link(ip-add-membership)(OPTION_IP_ADD_MEMBERSHIP), link(ttl)(OPTION_TTL), link(tos)(OPTION_TOS), - link(bind)(OPTION_BIND), link(pf)(OPTION_PROTOCOL_FAMILY)nl() See also: link(IP4-DATAGRAM)(ADDRESS_IP4_DATAGRAM), @@ -599,6 +609,209 @@ label(ADDRESS_READLINE)dit(bf(tt(READLINE))) link(noecho)(OPTION_NOECHO)nl() See also: link(STDIO)(ADDRESS_STDIO) +label(ADDRESS_SCTP_CONNECT)dit(bf(tt(SCTP-CONNECT::))) + Establishes an SCTP stream connection to the specified [link(IP + address)(TYPE_IP_ADDRESS)] and [link(TCP service)(TYPE_TCP_SERVICE)] + using TCP/IP version 4 or 6 depending on address specification, name + resolution, or option link(pf)(OPTION_PROTOCOL_FAMILY) (link(example)(EXAMPLE_SCTP_OPENSSL_IP6)).nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(SCTP)(GROUP_SCTP),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY) nl() + Useful options: + link(bind)(OPTION_BIND), + link(pf)(OPTION_PROTOCOL_FAMILY), + link(connect-timeout)(OPTION_CONNECT_TIMEOUT), + link(tos)(OPTION_TOS), + link(mtudiscover)(OPTION_MTUDISCOVER), + link(sctp-maxseg)(OPTION_SCTP_MAXSEG), + link(sctp-nodelay)(OPTION_SCTP_NODELAY), + link(nonblock)(OPTION_NONBLOCK), + link(sourceport)(OPTION_SOURCEPORT), + link(retry)(OPTION_RETRY), + link(readbytes)(OPTION_READBYTES)nl() + See also: + link(SCTP4-CONNECT)(ADDRESS_SCTP4_CONNECT), + link(SCTP6-CONNECT)(ADDRESS_SCTP6_CONNECT), + link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN), + link(TCP-CONNECT)(ADDRESS_TCP_CONNECT) +label(ADDRESS_SCTP4_CONNECT)dit(bf(tt(SCTP4-CONNECT::))) + Like link(SCTP-CONNECT)(ADDRESS_SCTP_CONNECT), but only supports IPv4 protocol.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(SCTP)(GROUP_SCTP),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY) nl() +label(ADDRESS_SCTP6_CONNECT)dit(bf(tt(SCTP6-CONNECT::))) + Like link(SCTP-CONNECT)(ADDRESS_SCTP_CONNECT), but only supports IPv6 protocol.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6),link(SCTP)(GROUP_SCTP),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY) nl() +label(ADDRESS_SCTP_LISTEN)dit(bf(tt(SCTP-LISTEN:))) + Listens on [link(TCP service)(TYPE_TCP_SERVICE)] and accepts a + TCP/IP connection. The IP version is 4 or the one specified with + address option link(pf)(OPTION_PROTOCOL_FAMILY), socat option + (link(-4)(option_4), link(-6)(option_6)), or environment variable link(SOCAT_DEFAULT_LISTEN_IP)(ENV_SOCAT_DEFAULT_LISTEN_IP). + Note that opening + this address usually blocks until a client connects.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(SCTP)(GROUP_SCTP),link(RETRY)(GROUP_RETRY) nl() + Useful options: + link(crnl)(OPTION_CRNL), + link(fork)(OPTION_FORK), + link(bind)(OPTION_BIND), + link(range)(OPTION_RANGE), + link(tcpwrap)(OPTION_TCPWRAPPERS), + link(pf)(OPTION_PROTOCOL_FAMILY), + link(backlog)(OPTION_BACKLOG), + link(sctp-maxseg)(OPTION_SCTP_MAXSEG), + link(sctp-nodelay)(OPTION_SCTP_NODELAY), + link(su)(OPTION_SUBSTUSER), + link(reuseaddr)(OPTION_REUSEADDR), + link(retry)(OPTION_RETRY), + link(cool-write)(OPTION_COOL_WRITE)nl() + See also: + link(SCTP4-LISTEN)(ADDRESS_SCTP4_LISTEN), + link(SCTP6-LISTEN)(ADDRESS_SCTP6_LISTEN), + link(TCP-LISTEN)(ADDRESS_TCP_LISTEN), + link(SCTP-CONNECT)(ADDRESS_SCTP_CONNECT) +label(ADDRESS_SCTP4_LISTEN)dit(bf(tt(SCTP4-LISTEN:))) + Like link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN), but only supports IPv4 + protocol.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP4)(GROUP_IP4),link(SCTP)(GROUP_SCTP),link(RETRY)(GROUP_RETRY) nl() +label(ADDRESS_SCTP6_LISTEN)dit(bf(tt(SCTP6-LISTEN:))) + Like link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN), but only supports IPv6 + protocol.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP6)(GROUP_IP6),link(SCTP)(GROUP_SCTP),link(RETRY)(GROUP_RETRY) nl() +label(ADDRESS_SOCKET_CONNECT)dit(bf(tt(SOCKET-CONNECT:::))) + Creates a stream socket using the first and second given socket parameters + and tt(SOCK_STREAM) (see man socket(2)) and connects to the remote-address. + The two socket parameters have to be specified by link(int)(TYPE_INT) + numbers. Consult your OS documentation and include files to find the + appropriate values. The remote-address must be the link(data)(TYPE_DATA) + representation of a sockaddr structure without sa_family and (BSD) sa_len + components.nl() + Please note that you can - beyond the options of the specified groups - also + use options of higher level protocols when you apply socat option + link(-g)(option_g).nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY)nl() + Useful options: + link(bind)(OPTION_BIND), + link(setsockopt-int)(OPTION_SETSOCKOPT_INT), + link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN), + link(setsockopt-string)(OPTION_SETSOCKOPT_STRING) + nl() + See also: + link(TCP)(ADDRESS_TCP_CONNECT), + link(UDP-CONNECT)(ADDRESS_UDP_CONNECT), + link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT), + link(SOCKET-LISTEN)(ADDRESS_SOCKET_LISTEN), + link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO) +label(ADDRESS_SOCKET_DATAGRAM)dit(bf(tt(SOCKET-DATAGRAM::::))) + Creates a datagram socket using the first three given socket parameters (see + man socket(2)) and sends outgoing data to the remote-address. The three + socket parameters have to be specified by link(int)(TYPE_INT) + numbers. Consult your OS documentation and include files to find the + appropriate values. The remote-address must be the link(data)(TYPE_DATA) + representation of a sockaddr structure without sa_family and (BSD) sa_len + components.nl() + Please note that you can - beyond the options of the specified groups - also + use options of higher level protocols when you apply socat option + link(-g)(option_g).nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(RANGE)(GROUP_RANGE)nl() + Useful options: + link(bind)(OPTION_BIND), + link(range)(OPTION_RANGE), + link(setsockopt-int)(OPTION_SETSOCKOPT_INT), + link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN), + link(setsockopt-string)(OPTION_SETSOCKOPT_STRING) + nl() + See also: + link(UDP-DATAGRAM)(ADDRESS_UDP_DATAGRAM), + link(IP-DATAGRAM)(ADDRESS_IP_DATAGRAM), + link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO), + link(SOCKET-RECV)(ADDRESS_SOCKET_RECV), + link(SOCKET-RECVFROM)(ADDRESS_SOCKET_RECVFROM) +label(ADDRESS_SOCKET_LISTEN)dit(bf(tt(SOCKET-LISTEN:::))) + Creates a stream socket using the first and second given socket parameters + and tt(SOCK_STREAM) (see man socket(2)) and waits for incoming connections + on local-address. The two socket parameters have to be specified by + link(int)(TYPE_INT) numbers. Consult your OS documentation and include files + to find the appropriate values. The local-address must be the + link(data)(TYPE_DATA) representation of a sockaddr structure without + sa_family and (BSD) sa_len components.nl() + Please note that you can - beyond the options of the specified groups - also + use options of higher level protocols when you apply socat option + link(-g)(option_g).nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(RANGE)(GROUP_RANGE),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY)nl() + Useful options: + link(setsockopt-int)(OPTION_SETSOCKOPT_INT), + link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN), + link(setsockopt-string)(OPTION_SETSOCKOPT_STRING) + nl() + See also: + link(TCP)(ADDRESS_TCP_LISTEN), + link(UDP-CONNECT)(ADDRESS_UDP_LISTEN), + link(UNIX-CONNECT)(ADDRESS_UNIX_LISTEN), + link(SOCKET-LISTEN)(ADDRESS_SOCKET_CONNECT), + link(SOCKET-SENDTO)(ADDRESS_SOCKET_RECVFROM), + link(SOCKET-SENDTO)(ADDRESS_SOCKET_RECV) +label(ADDRESS_SOCKET_RECV)dit(bf(tt(SOCKET-RECV::::))) + Creates a socket using the three given socket parameters (see man socket(2)) + and binds it to . Receives arriving data. The three + parameters have to be specified by link(int)(TYPE_INT) numbers. Consult your + OS documentation and include files to find the appropriate values. The + local-address must be the link(data)(TYPE_DATA) representation of a sockaddr + structure without sa_family and (BSD) sa_len components.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(RANGE)(GROUP_RANGE)nl() + Useful options: + link(range)(OPTION_RANGE), + link(setsockopt-int)(OPTION_SETSOCKOPT_INT), + link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN), + link(setsockopt-string)(OPTION_SETSOCKOPT_STRING) + nl() + See also: + link(UDP-RECV)(ADDRESS_UDP_RECV), + link(IP-RECV)(ADDRESS_IP_RECV), + link(UNIX-RECV)(ADDRESS_UNIX_RECV), + link(SOCKET-DATAGRAM)(ADDRESS_SOCKET_DATAGRAM), + link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO), + link(SOCKET-RECVFROM)(ADDRESS_SOCKET_RECVFROM) +label(ADDRESS_SOCKET_RECVFROM)dit(bf(tt(SOCKET-RECVFROM::::))) + Creates a socket using the three given socket parameters (see man socket(2)) + and binds it to . Receives arriving data and sends replies + back to the sender. The first three parameters have to be specified as + link(int)(TYPE_INT) numbers. Consult your OS documentation and include files + to find the appropriate values. The local-address must be the + link(data)(TYPE_DATA) representation of a sockaddr structure without + sa_family and (BSD) sa_len components.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE)nl() + Useful options: + link(fork)(OPTION_FORK), + link(range)(OPTION_RANGE), + link(setsockopt-int)(OPTION_SETSOCKOPT_INT), + link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN), + link(setsockopt-string)(OPTION_SETSOCKOPT_STRING) + nl() + See also: + link(UDP-RECVFROM)(ADDRESS_UDP_RECVFROM), + link(IP-RECVFROM)(ADDRESS_IP_RECVFROM), + link(UNIX-RECVFROM)(ADDRESS_UNIX_RECVFROM), + link(SOCKET-DATAGRAM)(ADDRESS_SOCKET_DATAGRAM), + link(SOCKET-SENDTO)(ADDRESS_SOCKET_SENDTO), + link(SOCKET-RECV)(ADDRESS_SOCKET_RECV) +label(ADDRESS_SOCKET_SENDTO)dit(bf(tt(SOCKET-SENDTO::::))) + Creates a socket using the three given socket parameters (see man + socket(2)). Sends outgoing data to the given address and receives replies. + The three parameters have to be specified as link(int)(TYPE_INT) + numbers. Consult your OS documentation and include files to find the + appropriate values. The remote-address must be the link(data)(TYPE_DATA) + representation of a sockaddr structure without sa_family and (BSD) sa_len + components.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET)nl() + Useful options: + link(bind)(OPTION_BIND), + link(setsockopt-int)(OPTION_SETSOCKOPT_INT), + link(setsockopt-bin)(OPTION_SETSOCKOPT_BIN), + link(setsockopt-string)(OPTION_SETSOCKOPT_STRING) + nl() + See also: + link(UDP-SENDTO)(ADDRESS_UDP_SENDTO), + link(IP-SENDTO)(ADDRESS_IP_SENDTO), + link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO), + link(SOCKET-DATAGRAM)(ADDRESS_SOCKET_DATAGRAM), + link(SOCKET-RECV)(ADDRESS_SOCKET_RECV) + link(SOCKET-RECVFROM)(ADDRESS_SOCKET_RECVFROM) label(ADDRESS_SOCKS4)dit(bf(tt(SOCKS4:::))) Connects via [link(IP address)(TYPE_IP_ADDRESS)] to [link(IPv4 address)(TYPE_IPV4_ADDRESS)] @@ -689,6 +902,7 @@ label(ADDRESS_TCP_CONNECT)dit(bf(tt(TCP::))) link(TCP6)(ADDRESS_TCP6_CONNECT), link(TCP-LISTEN)(ADDRESS_TCP_LISTEN), link(UDP)(ADDRESS_UDP_CONNECT), + link(SCTP-CONNECT)(ADDRESS_SCTP_CONNECT), link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT) label(ADDRESS_TCP4_CONNECT)dit(bf(tt(TCP4::))) Like link(TCP)(ADDRESS_TCP_CONNECT), but only supports IPv4 protocol (link(example)(EXAMPLE_ADDRESS_TCP4_CONNECT)).nl() @@ -699,7 +913,8 @@ label(ADDRESS_TCP6_CONNECT)dit(bf(tt(TCP6::))) label(ADDRESS_TCP_LISTEN)dit(bf(tt(TCP-LISTEN:))) Listens on [link(TCP service)(TYPE_TCP_SERVICE)] and accepts a TCP/IP connection. The IP version is 4 or the one specified with - link(pf)(OPTION_PROTOCOL_FAMILY). + address option link(pf)(OPTION_PROTOCOL_FAMILY), socat option + (link(-4)(option_4), link(-6)(option_6)), or environment variable link(SOCAT_DEFAULT_LISTEN_IP)(ENV_SOCAT_DEFAULT_LISTEN_IP). Note that opening this address usually blocks until a client connects.nl() Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(RETRY)(GROUP_RETRY) nl() @@ -715,13 +930,15 @@ label(ADDRESS_TCP_LISTEN)dit(bf(tt(TCP-LISTEN:))) link(su)(OPTION_SUBSTUSER), link(reuseaddr)(OPTION_REUSEADDR), link(retry)(OPTION_RETRY), - link(retry)(OPTION_COOL_WRITE)nl() + link(cool-write)(OPTION_COOL_WRITE)nl() See also: - link(TCP4-LISTEN)(ADDRESS_TCP4_CONNECT), + link(TCP4-LISTEN)(ADDRESS_TCP4_LISTEN), link(TCP6-LISTEN)(ADDRESS_TCP6_LISTEN), link(UDP-LISTEN)(ADDRESS_UDP_LISTEN), + link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN), link(UNIX-LISTEN)(ADDRESS_UNIX_LISTEN), - link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN) + link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN), + link(TCP-CONNECT)(ADDRESS_TCP_CONNECT) label(ADDRESS_TCP4_LISTEN)dit(bf(tt(TCP4-LISTEN:))) Like link(TCP-LISTEN)(ADDRESS_TCP_LISTEN), but only supports IPv4 protocol (link(example)(EXAMPLE_ADDRESS_TCP4_LISTEN)).nl() @@ -783,7 +1000,8 @@ label(ADDRESS_UDP_DATAGRAM)dit(bf(tt(UDP-DATAGRAM:
:))) options. This address type can for example be used for implementing symmetric or asymmetric broadcast or multicast communications.nl() Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(RANGE)(GROUP_RANGE) nl() - Useful options: + Useful options: + link(bind)(OPTION_BIND), link(range)(OPTION_RANGE), link(tcpwrap)(OPTION_TCPWRAPPERS), link(broadcast)(OPTION_SO_BROADCAST), @@ -793,7 +1011,6 @@ label(ADDRESS_UDP_DATAGRAM)dit(bf(tt(UDP-DATAGRAM:
:))) link(ip-add-membership)(OPTION_IP_ADD_MEMBERSHIP), link(ttl)(OPTION_TTL), link(tos)(OPTION_TOS), - link(bind)(OPTION_BIND), link(sourceport)(OPTION_SOURCEPORT), link(pf)(OPTION_PROTOCOL_FAMILY)nl() See also: @@ -1264,6 +1481,24 @@ label(OPTION_END_CLOSE)dit(bf(tt(end-close))) 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. +label(OPTION_IOCTL_VOID)dit(bf(tt(ioctl-void=))) + Calls tt(ioctl()) with the request value as second argument and NULL as + third argument. This option allows to utilize ioctls that are not + explicitely implemented in socat. +label(OPTION_IOCTL_INT)dit(bf(tt(ioctl-int=:))) + Calls tt(ioctl()) with the request value as second argument and the integer + value as third argument. +label(OPTION_IOCTL_INTP)dit(bf(tt(ioctl-intp=:))) + Calls tt(ioctl()) with the request value as second argument and a pointer to + the integer value as third argument. +label(OPTION_IOCTL_BIN)dit(bf(tt(ioctl-bin=:))) + Calls tt(ioctl()) with the request value as second argument and a pointer to + the given data value as third argument. This data must be specified in + link()(TYPE_DATA) form. +label(OPTION_IOCTL_STRING)dit(bf(tt(ioctl-string=:))) + Calls tt(ioctl()) with the request value as second argument and a pointer to + the given string as third argument. + link()(TYPE_DATA) form. enddit() startdit()enddit()nl() @@ -1516,6 +1751,10 @@ label(OPTION_LOCKFILE)dit(bf(tt(lockfile=))) label(OPTION_WAITLOCK)dit(bf(tt(waitlock=))) If lockfile exists, waits until it disappears. When lockfile does not exist, creates it and continues, unlinks lockfile on exit. +label(OPTION_ESCAPE)dit(bf(tt(escape=))) + Specifies the numeric code of a character that triggers EOF on the input + stream. It is useful with a terminal in raw mode + (link(example)(EXAMPLE_OPTION_ESCAPE)). enddit() startdit()enddit()nl() @@ -1539,8 +1778,8 @@ label(OPTION_INTERFACE)dit(bf(tt(interface=))) label(OPTION_SO_BROADCAST)dit(bf(tt(broadcast))) For datagram sockets, allows sending to broadcast addresses and receiving packets addressed to broadcast addresses. -label(OPTION_BSDCOMPAT)dit(bf(tt(bsdcompat))) - Emulates some (old?) bugs of the BSD socket implementation. +COMMENT(label(OPTION_BSDCOMPAT)dit(bf(tt(bsdcompat))) + Emulates some (old?) bugs of the BSD socket implementation.) label(OPTION_DEBUG)dit(bf(tt(debug))) Enables socket debugging. label(OPTION_DONTROUTE)dit(bf(tt(dontroute))) @@ -1585,11 +1824,23 @@ label(OPTION_SNDLOWAT)dit(bf(tt(sndlowat=))) layer will send the data to [link(int)(TYPE_INT)]. label(OPTION_SNDTIMEO)dit(bf(tt(sndtimeo=))) Sets the send timeout to seconds [link(timeval)(TYPE_TIMEVAL)]. -label(OPTION_TYPE)dit(bf(tt(type=))) - Sets the type of the socket, usually as argument to the code(socket()) or - code(socketpair()) call, to [link(int)(TYPE_INT)]. +label(OPTION_PROTOCOL_FAMILY)dit(bf(tt(pf=))) + Forces the use of the specified IP version or protocol. can be + something like "ip4" or "ip6". The resulting value is + used as first argument to the code(socket()) or code(socketpair()) calls. + This option affects address resolution and the required syntax of bind and + range options. +label(OPTION_SO_TYPE)dit(bf(tt(type=))) + Sets the type of the socket, specified as second argument to the + code(socket()) or code(socketpair()) calls, to + [link(int)(TYPE_INT)]. Address resolution is not affected by this option. Under Linux, 1 means stream oriented socket, 2 means datagram socket, and 3 means raw socket. +label(OPTION_SO_PROTOTYPE)dit(bf(tt(prototype))) + Sets the protocol of the socket, specified as third argument to the + code(socket()) or code(socketpair()) calls, to + [link(int)(TYPE_INT)]. Address resolution is not affected by this option. + 6 means TCP, 17 means UDP. COMMENT(label(OPTION_USELOOPBACK)dit(bf(tt(useloopback))) Sets the code(SO_USELOOPBACK) socket option.) COMMENT(label(OPTION_ACCEPTCONN)dit(bf(tt(acceptconn))) @@ -1618,8 +1869,6 @@ COMMENT(label(OPTION_PASSCRED)dit(bf(tt(passcred))) Set the code(SO_PASSCRED) socket option.) COMMENT(label(OPTION_PEERCRED)dit(bf(tt(peercred))) This is a read-only socket option.) -COMMENT(label(OPTION_PROTOTYPE)dit(bf(tt(prototype))) - Tries to set the code(SO_PROTOTYPE) socket option.) COMMENT(label(OPTION_REUSEPORT)dit(bf(tt(reuseport))) Set the code(SO_REUSEPORT) socket option.) COMMENT(label(OPTION_SECUTIYAUTHENTICATION)dit(bf(tt(securityauthentication))) @@ -1632,9 +1881,27 @@ COMMENT(label(OPTION_SIOCSPGRP)dit(bf(tt(siocspgrp=))) Set the SIOCSPGRP with code(ioclt()) to enable SIGIO.) COMMENT(label(OPTION_USEIFBUFS)dit(bf(tt(useifbufs))) Set the code(SO_USE_IFBUFS) socket option.) -label(OPTION_PROTOCOL_FAMILY)dit(bf(tt(pf=))) - Forces the use of the specified IP version. can be - something like "ip4" or "ip6". +label(OPTION_SO_TIMESTAMP)dit(bf(tt(so-timestamp))) + Sets the SO_TIMESTAMP socket option. This enables receiving and logging of + timestamp ancillary messages. +label(OPTION_SETSOCKOPT_INT)dit(bf(tt(setsockopt-int=::))) + Invokes tt(setsockopt()) for the socket with the given parameters. tt(level) + [link(int)(TYPE_INT)] is used as second argument to tt(setsockopt()) and + specifies the layer, e.g. SOL_TCP for TCP (6 on Linux), or SOL_SOCKET for + the socket layer (1 on Linux). tt(optname) [link(int)(TYPE_INT)] is the + third argument to tt(setsockopt()) and tells which socket option is to be + set. For the actual numbers you might have to look up the appropriate include + files of your system. The 4th tt(setsockopt()) parameter, tt(value) + [link(int)(TYPE_INT)], is passed to the function per pointer, and for the + length parameter sizeof(int) is taken implicitely. +label(OPTION_SETSOCKOPT_BIN)dit(bf(tt(setsockopt-bin=::))) + Like tt(setsockopt-int), but must be provided in + link(dalan)(TYPE_DATA) format and specifies an arbitrary sequence of bytes; + the length parameter is automatically derived from the data. +label(OPTION_SETSOCKOPT_STRING)dit(bf(tt(setsockopt-string=::))) + Like tt(setsockopt-int), but must be a link(string)(TYPE_STRING). + This string is passed to the function with trailing null character, and the + length parameter is automatically derived from the data. enddit() startdit()enddit()nl() @@ -1661,13 +1928,13 @@ label(OPTION_TOS)dit(bf(tt(tos=))) label(OPTION_TTL)dit(bf(tt(ttl=))) Sets the TTL (time to live) field of outgoing packets to [link(byte)(TYPE_BYTE)]. -label(OPTION_IPOPTIONS)dit(bf(tt(ipoptions=))) +label(OPTION_IPOPTIONS)dit(bf(tt(ip-options=))) Sets IP options like source routing. Must be given in binary form, recommended format is a leading "x" followed by an even number of hex digits. This option may be used multiple times, data are appended. E.g., to connect to host 10.0.0.1 via some gateway using a loose source route, use the gateway as address parameter and set a loose source route - using the option code(ipoptions=x8307040a000001).nl() + using the option code(ip-options=x8307040a000001).nl() IP options are defined in RFC 791. COMMENT(, RFC 2113)nl() COMMENT( x00 end of option list x01 no operation (nop) @@ -1680,26 +1947,39 @@ COMMENT( x00 end of option list label(OPTION_MTUDISCOVER)dit(bf(tt(mtudiscover=<0|1|2>))) Takes 0, 1, 2 to never, want, or always use path MTU discover on this socket. -COMMENT(label(OPTION_HRDINCL)dit(bf(tt(hdrincl))) +COMMENT(label(OPTION_HRDINCL)dit(bf(tt(ip-hdrincl))) Tell the raw socket that the application data includes the IP header.) -COMMENT(label(OPTION_IP_MULTICAST_LOOP)dit(bf(tt(multicastloop))) +COMMENT(label(OPTION_IP_MULTICAST_LOOP)dit(bf(tt(ip-multicastloop))) Allow looping back outgoing multicast to the local interface.) -COMMENT(label(OPTION_IP_MULTICAST_TTL)dit(bf(tt(multicastttl))) +COMMENT(label(OPTION_IP_MULTICAST_TTL)dit(bf(tt(ip-multicastttl))) Set the TTL for outgoing multicast packets.) -COMMENT(label(OPTION_PKTINFO)dit(bf(tt(pktinfo))) - Set the IP_PKTINFO socket option.) -COMMENT(label(OPTION_PKTOPTS)dit(bf(tt(pktopts))) +label(OPTION_IP_PKTINFO)dit(bf(tt(ip-pktinfo))) + Sets the IP_PKTINFO socket option. This enables receiving and logging of + ancillary messages containing destination address and interface (Linux) + (link(example)(EXAMPLE_ANCILLARY)). +COMMENT(label(OPTION_PKTOPTS)dit(bf(tt(ip-pktopts))) Set the IP_PKTOPTIONS socket option.) -COMMENT(label(OPTION_RECVERR)dit(bf(tt(recverr))) - Set the IP_RECVERR socket option.) -COMMENT(label(OPTION_RECVOPTS)dit(bf(tt(recvopts))) - Set the IP_RECVOPTS socket option.) -COMMENT(label(OPTION_RECVTOS)dit(bf(tt(recvtos))) - Set the IP_RECVTOS socket option.) -COMMENT(label(OPTION_RECVTTL)dit(bf(tt(recvttl))) - Set the IP_RECVTTL socket option.) -COMMENT(label(OPTION_RETOPTS)dit(bf(tt(retopts))) +label(OPTION_IP_RECVERR)dit(bf(tt(ip-recverr))) + Sets the IP_RECVERR socket option. This enables receiving and logging of + ancillary messages containing detailled error information. +label(OPTION_IP_RECVOPTS)dit(bf(tt(ip-recvopts))) + Sets the IP_RECVOPTS socket option. This enables receiving and logging of IP + options ancillary messages (Linux, *BSD). +label(OPTION_IP_RECVTOS)dit(bf(tt(ip-recvtos))) + Sets the IP_RECVTOS socket option. This enables receiving and logging of TOS + (type of service) ancillary messages (Linux). +label(OPTION_IP_RECVTTL)dit(bf(tt(ip-recvttl))) + Sets the IP_RECVTTL socket option. This enables receiving and logging of TTL + (time to live) ancillary messages (Linux, *BSD). +COMMENT(label(OPTION_RETOPTS)dit(bf(tt(ip-retopts))) Set the IP_RETOPTS socket option.) +label(OPTION_IP_RECVDSTADDR)dit(bf(tt(ip-recvdstaddr))) + Sets the IP_RECVDSTADDR socket option. This enables receiving and logging of + ancillary messages containing destination address (*BSD) + (link(example)(EXAMPLE_ANCILLARY)). +label(OPTION_IP_RECVIF)dit(bf(tt(ip-recvif))) + Sets the IP_RECVIF socket option. This enables receiving and logging of + interface ancillary messages (*BSD) (link(example)(EXAMPLE_ANCILLARY)). COMMENT(label(OPTION_ROUTERALERT)dit(bf(tt(routeralert))) Set the IP_ROUTER_ALERT socket option.) label(OPTION_IP_ADD_MEMBERSHIP) @@ -1754,6 +2034,30 @@ label(OPTION_IPV6_V6ONLY)dit(bf(tt(ipv6only=))) Sets the IPV6_V6ONLY socket option. If 0, the TCP stack will also accept connections using IPv4 protocol on the same port. The default is system dependent. +label(OPTION_IPV6_RECVDSTOPTS)dit(bf(tt(ipv6-recvdstopts))) + Sets the IPV6_RECVDSTOPTS socket option. This enables receiving and logging + of ancillary messages containing the destination options. +label(OPTION_IPV6_RECVHOPLIMIT)dit(bf(tt(ipv6-recvhoplimit))) + Sets the IPV6_RECVHOPLIMIT socket option. This enables receiving and logging + of ancillary messages containing the hoplimit. +label(OPTION_IPV6_RECVHOPOPTS)dit(bf(tt(ipv6-recvhopopts))) + Sets the IPV6_RECVHOPOPTS socket option. This enables receiving and logging + of ancillary messages containing the hop options. +label(OPTION_IPV6_RECVPKTINFO)dit(bf(tt(ipv6-recvpktinfo))) + Sets the IPV6_RECVPKTINFO socket option. This enables receiving and logging + of ancillary messages containing destination address and interface. +label(OPTION_IPV6_UNICAST_HOPS)dit(bf(tt(ipv6-unicast-hops=link(TYPE_INT)()))) + Sets the IPV6_UNICAST_HOPS socket option. This sets the hop count limit + (TTL) for outgoing unicast packets. +label(OPTION_IPV6_RECVRTHDR)dit(bf(tt(ipv6-recvrthdr))) + Sets the IPV6_RECVRTHDR socket option. This enables receiving and logging + of ancillary messages containing routing information. +label(OPTION_IPV6_TCLASS)dit(bf(tt(ipv6-tclass))) + Sets the IPV6_TCLASS socket option. This sets the transfer class of outgoing + packets. +label(OPTION_IPV6_RECVTCLASS)dit(bf(tt(ipv6-recvtclass))) + Sets the IPV6_RECVTCLASS socket option. This enables receiving and logging + of ancillary messages containing the transfer class. enddit() startdit()enddit()nl() @@ -1832,10 +2136,24 @@ enddit() startdit()enddit()nl() -em(bf(UDP and TCP option groups)) +label(GROUP_SCTP)em(bf(SCTP option group)) -Here we find options that are related to the network port mechanism and that -thus can be used with UDP and TCP, client and server addresses. +These options may be applied to SCTP stream sockets. +startdit() +label(OPTION_SCTP_NODELAY)dit(bf(tt(sctp-nodelay))) + Sets the SCTP_NODELAY socket option that disables the Nagle algorithm. +label(OPTION_SCTP_MAXSEG)dit(bf(tt(sctp-maxseg=))) + Sets the SCTP_MAXSEG socket option to [link(int)(TYPE_INT)]. This + value is then proposed to the peer with the SYN or SYN/ACK packet. +enddit() + +startdit()enddit()nl() + + +em(bf(UDP, TCP, and SCTP option groups)) + +Here we find options that are related to the network port mechanism and thus +can be used with UDP, TCP, and SCTP client and server addresses. startdit() label(OPTION_SOURCEPORT)dit(bf(tt(sourceport=))) For outgoing (client) TCP and UDP connections, it sets the source @@ -2196,6 +2514,13 @@ label(OPTION_VTDLY)dit(bf(tt(vtdly=))) label(OPTION_WERASE)dit(bf(tt(werase=))) label(OPTION_XCASE)dit(bf(tt(xcase=))) label(OPTION_XTABS)dit(bf(tt(xtabs))) +label(OPTION_I_POP_ALL)dit(bf(tt(i-pop-all))) + With UNIX System V STREAMS, removes all drivers from the stack. +label(OPTION_I_PUSH)dit(bf(tt(i-push=))) + With UNIX System V STREAMS, pushes the driver (module) with the given name + (link(string)(TYPE_STRING)) onto the stack. For example, to make sure that a + character device on Solaris supports termios etc, use the following options: + tt(i-pop-all,i-push=ptem,i-push=ldterm,i-push=ttcompat) enddit() startdit()enddit()nl() @@ -2413,8 +2738,9 @@ label(TYPE_COMMAND_LINE)dit(command-line) A string specifying a program name and its arguments, separated by single spaces. label(TYPE_DATA)dit(data) - A raw data specification following em(dalan) syntax. The only documented - form is a string starting with 'x' followed by an even number of hex digits. + A raw data specification following em(dalan) syntax. Currently the only + valid form is a string starting with 'x' followed by an even number of hex + digits, specifying a sequence of bytes. label(TYPE_DIRECTORY)dit(directory) A string with usual unix() directory name semantics. label(TYPE_FACILITY)dit(facility) @@ -2433,7 +2759,8 @@ label(TYPE_INT)dit(int) "0", i.e. decimal number, octal number with leading "0", or hexadecimal number with leading "0x". The value must fit into a C int. label(TYPE_INTERFACE)dit(interface) - A string specifying the device name of a network interface, e.g. "eth0". + A string specifying the device name of a network interface + as shown by ifconfig or procan, e.g. "eth0". label(TYPE_IP_ADDRESS)dit(IP address) An IPv4 address in numbers-and-dots notation, an IPv6 address in hex notation enclosed in brackets, or a hostname that resolves to an IPv4 or an @@ -2509,7 +2836,7 @@ startdit() label(EXAMPLE_ADDRESS_TCP4_CONNECT) dit(bf(tt(socat - TCP4:www.domain.org:80))) -Transfers data between link(STDIO)(ADDRESS_STDIO) (-) and a +transfers data between link(STDIO)(ADDRESS_STDIO) (-) and a link(TCP4)(ADDRESS_TCP4_CONNECT) connection to port 80 of host www.domain.org. This example results in an interactive connection similar to telnet or netcat. The stdin terminal parameters are not changed, so you may @@ -2526,22 +2853,22 @@ mancommand(\.fi) htmlcommand(
socat -d -d READLINE,history=$HOME/.http_history \
TCP4:www.domain.org:www,crnl
) -This is similar to the previous example, but you can edit the current line in a +this is similar to the previous example, but you can edit the current line in a bash like manner (link(READLINE)(ADDRESS_READLINE)) and use the -link(history)(OPTION_HISTORY) file .http_history; socat() -prints messages about progress (link(-d -d)(option_d_d)). The port is specified by service name -(www), and correct network line termination characters (link(crnl)(OPTION_CRNL)) instead of NL -are used. +link(history)(OPTION_HISTORY) file .http_history; socat() prints messages about +progress (link(-d -d)(option_d_d)). The port is specified by service name +(www), and correct network line termination characters +(link(crnl)(OPTION_CRNL)) instead of NL are used. label(EXAMPLE_ADDRESS_TCP4_LISTEN) dit(bf(tt(socat TCP4-LISTEN:www TCP4:www.domain.org:www))) -Installs a simple TCP port forwarder. With +installs a simple TCP port forwarder. With link(TCP4-LISTEN)(ADDRESS_TCP4_LISTEN) it listens on local port "www" until a connection comes in, accepts it, then connects to the remote host -(link(TCP4)(ADDRESS_TCP4_CONNECT)) and starts data transfer. It will not accept a -second connection. +(link(TCP4)(ADDRESS_TCP4_CONNECT)) and starts data transfer. It will not accept +a econd connection. label(EXAMPLE_OPTION_BIND_TCP4) label(EXAMPLE_OPTION_REUSEADDR) @@ -2565,9 +2892,10 @@ arbitrary number of parallel or consecutive connections by link(fork)(OPTION_FORK)'ing a new process after each code(accept()). It provides a little security by link(su)(OPTION_SUBSTUSER)'ing to user -nobody after forking; it only permits connections from the private 10 network (link(range)(OPTION_RANGE)); -due to link(reuseaddr)(OPTION_REUSEADDR), it allows immediate restart after master process's -termination, even if some child sockets are not completely shut down. +nobody after forking; it only permits connections from the private 10 network +(link(range)(OPTION_RANGE)); due to link(reuseaddr)(OPTION_REUSEADDR), it +allows immediate restart after master process's termination, even if some child +sockets are not completely shut down. With link(-lmlocal2)(option_lm), socat logs to stderr until successfully reaching the accept loop. Further logging is directed to syslog with facility local2. @@ -2587,7 +2915,7 @@ mancommand(\.fi) htmlcommand(
socat TCP4-LISTEN:5555,fork,tcpwrap=script \
EXEC:/bin/myscript,chroot=/home/sandbox,su-d=sandbox,pty,stderr
) -A simple server that accepts connections +a simple server that accepts connections (link(TCP4-LISTEN)(ADDRESS_TCP4_LISTEN)) and link(fork)(OPTION_FORK)'s a new child process for each connection; every child acts as single relay. The client must match the rules for daemon process name "script" in @@ -2630,13 +2958,15 @@ at most 512 data bytes per packet (link(mss)(OPTION_MSS)). label(EXAMPLE_ADDRESS_GOPEN) label(EXAMPLE_OPTION_RAW) label(EXAMPLE_OPTION_ECHO) -dit(bf(tt(socat - /dev/ttyS0,raw,echo=0,crnl))) +label(EXAMPLE_OPTION_ESCAPE) +dit(bf(tt(socat -,raw,echo=0,escape=0x0f /dev/ttyS0,raw,echo=0,crnl))) -Opens an interactive connection via the serial line, e.g. for talking with a -modem. link(raw)(OPTION_RAW) and link(echo)(OPTION_ECHO) set ttyS0's terminal -parameters to practicable values, link(crnl)(OPTION_CRNL) -converts to correct newline characters. Consider using -link(READLINE)(ADDRESS_READLINE) instead of `-'. +opens an interactive connection via the serial line, e.g. for talking with a +modem. link(raw)(OPTION_RAW) and link(echo)(OPTION_ECHO) set the console's and +ttyS0's terminal parameters to practicable values, link(crnl)(OPTION_CRNL) +converts to correct newline characters. link(escape)(OPTION_ESCAPE) allows to +terminate the socat process with character control-O. +Consider using link(READLINE)(ADDRESS_READLINE) instead of the first address. label(EXAMPLE_ADDRESS_UNIX_LISTEN) @@ -2652,7 +2982,7 @@ mancommand(\.fi) htmlcommand(
socat UNIX-LISTEN:/tmp/.X11-unix/X1,fork \
SOCKS4:host.victim.org:127.0.0.1:6000,socksuser=nobody,sourceport=20
) -With link(UNIX-LISTEN)(ADDRESS_UNIX_LISTEN), socat() opens a listening +with link(UNIX-LISTEN)(ADDRESS_UNIX_LISTEN), socat() opens a listening unixdomain() socket file(/tmp/.X11-unix/X1). This path corresponds to local XWindow display :1 on your machine, so XWindow client connections to DISPLAY=:1 are accepted. Socat() then speaks with @@ -2672,7 +3002,7 @@ label(EXAMPLE_option_u) label(EXAMPLE_OPTION_IGNOREEOF) dit(bf(tt(socat -u /tmp/readdata,seek-end=0,ignoreeof -))) -This is an example for unidirectional data transfer +this is an example for unidirectional data transfer (link(-u)(option_u)). Socat() transfers data from file /tmp/readdata (implicit address link(GOPEN)(ADDRESS_GOPEN)), starting at its current end (link(seek-end)(OPTION_SEEK_END)=0 lets socat() start @@ -2711,7 +3041,7 @@ mancommand(\.fi) htmlcommand(
socat -u TCP4-LISTEN:3334,reuseaddr,fork \
OPEN:/tmp/in.log,creat,append
) -Implements a simple network based message collector. +implements a simple network based message collector. For each client connecting to port 3334, a new child process is generated (option link(fork)(OPTION_FORK)). All data sent by the clients are link(append)(OPTION_APPEND)'ed to the file /tmp/in.log. If the file does not exist, socat link(creat)(OPTION_CREAT)'s it. @@ -2721,7 +3051,7 @@ process. COMMENT( dit(bf(tt(socat TCP4-LISTEN:3335,reuseaddr,fork OPEN:/tmp/motd,rdonly))) -Implements a simple network based motd server. +implements a simple network based motd server. For each client connecting to port 3335, a new child process is generated (option link(fork)(OPTION_FORK)). The contents of the file /tmp/motd is sent to each client. @@ -2732,7 +3062,7 @@ process. COMMENT( dit(bf(tt(socat - TCP4-LISTEN:8080,mtudiscover=0,rcvbuf=2048))) -Changes some socket parameters to confuse active OS fingerprinting methods. +changes some socket parameters to confuse active OS fingerprinting methods. link(mtudiscover)(OPTION_MTUDISCOVER)=0 sets the DF (don'ft fragment flag) in the IP packets to 0 and link(rcvbuf)(OPTION_RCVBUF) changes the initial TCP window size. @@ -2741,7 +3071,7 @@ window size. label(EXAMPLE_OPTION_NOECHO) dit(bf(tt(socat READLINE,noecho='[Pp]assword:' EXEC:'ftp ftp.server.com',pty,setsid,ctty))) -Wraps a command line history (link(READLINE)(ADDRESS_READLINE)) around the link(EXEC)(ADDRESS_EXEC)'uted ftp client utility. +wraps a command line history (link(READLINE)(ADDRESS_READLINE)) around the link(EXEC)(ADDRESS_EXEC)'uted ftp client utility. This allows editing and reuse of FTP commands for relatively comfortable browsing through the ftp directory hierarchy. The password is echoed! link(pty)(OPTION_PTY) is required to have ftp issue a prompt. @@ -2755,7 +3085,7 @@ label(EXAMPLE_OPTION_WAITSLAVE) label(EXAMPLE_OPTION_NONBLOCK) (bf(tt(socat PTY,link=$HOME/dev/vmodem0,raw,echo=0,waitslave EXEC:'"ssh modemserver.us.org socat - /dev/ttyS0,nonblock,raw,echo=0"'))) -Generates a pseudo terminal +generates a pseudo terminal device (link(PTY)(ADDRESS_PTY)) on the client that can be reached under the symbolic link(link)(OPTION_SYMBOLIC_LINK) file($HOME/dev/vmodem0). An application that expects a serial line or modem @@ -2853,6 +3183,15 @@ 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. +label(EXAMPLE_ADDRESS_GENERIC_CLIENT) +dit(bf(tt(socat - SOCKET-DATAGRAM:2:2:17:x007bxc0a80100x0000000000000000,bind=x007bx00000000x0000000000000000,setsockopt-int=1:6:1,range=x0000xc0a80100x0000000000000000:x0000xffffff00x0000000000000000))) + +is semantically equivalent to the link(previous +example)(EXAMPLE_ADDRESS_UDP4_BROADCAST_CLIENT), but all parameters are +specified in generic form. the value 6 of setsockopt-int is the Linux value for +tt(SO_BROADCAST). + + label(EXAMPLE_ADDRESS_IP4_BROADCAST_CLIENT) dit(bf(tt(socat - IP4-DATAGRAM:255.255.255.255:44,broadcast,range=10.0.0.0/8))) @@ -2883,6 +3222,48 @@ client and server authentication (see OpenSSL link(client)(EXAMPLE_ADDRESS_OPENSSL_CONNECT) and link(server)(EXAMPLE_ADDRESS_OPENSSL_LISTEN)). + +label(EXAMPLE_INTERFACE) +dit(bf(tt(socat PTY,link=/var/run/ppp,raw,echo=0 INTERFACE:hdlc0))) + +circumvents the problem that pppd requires a serial device and thus might not +be able to work on a synchronous line that is represented by a network device. +socat creates a PTY to make pppd happy, binds to the network +link(interface)(ADDRESS_INTERFACE) tt(hdlc0), and can transfer data between +both devices. Use pppd on device tt(/var/run/ppp) then. + + +label(EXAMPLE_HTTPECHO) +dit(bf(tt(socat -T 1 -d -d TCP-L:10081,reuseaddr,fork,crlf SYSTEM:"echo -e \"\\\"HTTP/1.0 200 OK\\\nDocumentType: text/plain\\\n\\\ndate: \$\(date\)\\\nserver:\$SOCAT_SOCKADDR:\$SOCAT_SOCKPORT\\\nclient: \$SOCAT_PEERADDR:\$SOCAT_PEERPORT\\\n\\\"\"; cat; echo -e \"\\\"\\\n\\\"\""))) + +creates a simple HTTP echo server: each HTTP client that connects gets a valid +HTTP reply that contains information about the client address and port as it is +seen by the server host, the host address (which might vary on multihomed +servers), and the original client request. + + +label(EXAMPLE_ANCILLARY) +dit(bf(tt(socat -d -d UDP4-RECVFROM:9999,so-broadcast,so-timestamp,ip-pktinfo,ip-recverr,ip-recvopts,ip-recvtos,ip-recvttl!!- SYSTEM:'export; sleep 1' |grep SOCAT))) + +waits for incoming UDP packets on port 9999 and prints the environment +variables provided by socat. On BSD based systems you have to replace +link(tt(ip-pktinfo))(OPTION_IP_PKTINFO) with link(tt(ip-recvdstaddr))(OPTION_IP_RECVDSTADDR),link(tt(ip-recvif))(OPTION_IP_RECVIF). Especially interesting is +SOCAT_IP_DSTADDR: it contains the target address of the packet which may be a +unicast, multicast, or broadcast address. + + +label(EXAMPLE_SCTP_OPENSSL_IP6) +dit(bf(tt(socat 'SCTP6-L:8888,reuseaddr,fork' '^SSL-L,fork,cert=testsrv.pem,verify=0|SYSTEM:export'))) + +dit(bf(tt(socat - 'SSL,verify=0|SCTP6:ip6hostname:8888'))) + +here two processes on different hosts communicate using openssl over SCTP on +IPv6. + +dit(bf(tt())) + + + enddit() @@ -2926,45 +3307,128 @@ manpagefiles() label(ENVIRONMENT_VARIABLES) manpagesection(ENVIRONMENT VARIABLES) -startdit() -dit(bf(SOCAT_DEFAULT_LISTEN_IP)) (Values 4 or 6) Sets the IP version to be used -for listen, recv, and recvfrom addresses if no link(pf)(OPTION_PROTOCOL_FAMILY) -(protocol-family) option is given. Is overridden by socat options -link(-4)(option_4) or link(-6)(option_6). +Input variables carry information from the environment to socat, output +variables are set by socat for use in executed scripts and programs. -dit(bf(SOCAT_PREFERRED_RESOLVE_IP)) (Values 0, 4, or 6) Sets the IP version to +In the output variables beginning with "SOCAT" this prefix is actually replaced +by the upper case name of the executable or the value of option +link(-lp)(option_lp). + +startdit() +label(ENV_SOCAT_DEFAULT_LISTEN_IP) +dit(bf(SOCAT_DEFAULT_LISTEN_IP) (input)) (Values 4 or 6) Sets the IP version to +be used for listen, recv, and recvfrom addresses if no +link(pf)(OPTION_PROTOCOL_FAMILY) (protocol-family) option is given. Is +overridden by socat options link(-4)(option_4) or link(-6)(option_6). + +dit(bf(SOCAT_PREFERRED_RESOLVE_IP) (input)) (Values 0, 4, or 6) Sets the IP +version to be used when resolving target host names when version is not specified by address type, option link(pf)(OPTION_PROTOCOL_FAMILY) (protocol-family), or address format. If name resolution does not return a matching entry, the first result (with differing IP version) is taken. With value 0, socat always selects the first record and its IP version. -dit(bf(SOCAT_FORK_WAIT)) Specifies the time (seconds) to sleep the parent and -child processes after successful fork(). Useful for debugging. +dit(bf(SOCAT_FORK_WAIT) (input)) Specifies the time (seconds) to sleep the +parent and child processes after successful fork(). Useful for debugging. -dit(bf(HOSTNAME)) Is used to determine the hostname for logging (see +dit(bf(SOCAT_VERSION) (output)) Socat sets this variable to its version string, +e.g. tt("1.7.0.0") for released versions or e.g. tt("1.6.0.1+envvar") for +temporary versions; can be used in scripts invoked by socat. + +dit(bf(SOCAT_PID) (output)) Socat sets this variable to its process id. In case +of link(fork)(OPTION_FORK) address option, SOCAT_PID gets the child processes +id. Forking for link(exec)(ADDRESS_EXEC) and link(system)(ADDRESS_SYSTEM) does +not change SOCAT_PID. + +dit(bf(SOCAT_PPID) (output)) Socat sets this variable to its process id. In +case of link(fork)(OPTION_FORK), SOCAT_PPID keeps the pid of the master process. + +dit(bf(SOCAT_PEERADDR) (output)) With passive socket addresses (all LISTEN and +RECVFROM addresses), this variable is set to a string describing the peers +socket address. Port information is not included. + +dit(bf(SOCAT_PEERPORT) (output)) With appropriate passive socket addresses +(TCP, UDP, and SCTP - LISTEN and RECVFROM), this variable is set to a string containing the +number of the peer port. + +dit(bf(SOCAT_SOCKADDR) (output)) With all LISTEN addresses, this variable is +set to a string describing the local socket address. Port information is not +included link(example)(EXAMPLE_HTTPECHO) + +dit(bf(SOCAT_SOCKPORT) (output)) With link(TCP-LISTEN)(ADDRESS_TCP_LISTEN), +link(UDP-LISTEN)(ADDRESS_UDP_LISTEN), and +link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN) addresses, this variable is set to the +local port. + +dit(bf(SOCAT_TIMESTAMP) (output)) With all RECVFROM addresses where address +option link(so-timestamp)(OPTION_SO_TIMESTAMP) is applied, socat sets this +variable to the resulting timestamp. + +dit(bf(SOCAT_IP_OPTIONS) (output)) With all IPv4 based RECVFROM addresses where +address option link(ip-recvopts)(OPTION_IP_RECVOPTS) is applied, socat fills +this variable with the IP options of the received packet. + +dit(bf(SOCAT_IP_DSTADDR) (output)) With all IPv4 based RECVFROM addresses where +address option link(ip-recvdstaddr)(OPTION_IP_RECVDSTADDR) (BSD) or +link(ip-pktinfo)(OPTION_IP_PKTINFO) (other platforms) is applied, socat sets +this variable to the destination address of the received packet. This is +particularly useful to identify broadcast and multicast addressed packets. + +dit(bf(SOCAT_IP_IF) (output)) With all IPv4 based RECVFROM addresses where +address option link(ip-recvif)(OPTION_IP_RECVIF) (BSD) or +link(ip-pktinfo)(OPTION_IP_PKTINFO) (other platforms) is applied, socat sets +this variable to the name of the interface where the packet was received. + +dit(bf(SOCAT_IP_LOCADDR) (output)) With all IPv4 based RECVFROM +addresses where address option link(ip-pktinfo)(OPTION_IP_PKTINFO) is applied, +socat sets this variable to the address of the interface where the packet was +received. + +dit(bf(SOCAT_IP_TOS) (output)) With all IPv4 based RECVFROM addresses where +address option link(ip-recvtos)(OPTION_IP_RECVTOS) is applied, socat sets this +variable to the TOS (type of service) of the received packet. + +dit(bf(SOCAT_IP_TTL) (output)) With all IPv4 based RECVFROM addresses where +address option link(ip-recvttl)(OPTION_IP_RECVTTL) is applied, socat sets this +variable to the TTL (time to live) of the received packet. + +dit(bf(SOCAT_IPV6_HOPLIMIT) (output)) With all IPv6 based RECVFROM addresses +where address option link(ipv6-recvhoplimit)(OPTION_IPV6_RECVHOPLIMIT) is +applied, socat sets this variable to the hoplimit value of the received packet. + +dit(bf(SOCAT_IPV6_DSTADDR) (output)) With all IPv6 based RECVFROM +addresses where address option link(ipv6-recvpktinfo)(OPTION_IPV6_RECVPKTINFO) +is applied, socat sets this variable to the destination address of the received +packet. + +dit(bf(SOCAT_IPV6_TCLASS) (output)) With all IPv6 based RECVFROM addresses +where address option link(ipv6-recvtclass)(OPTION_IPV6_RECVTCLASS) is applied, +socat sets this variable to the transfer class of the received packet. + +dit(bf(HOSTNAME) (input)) Is used to determine the hostname for logging (see link(-lh)(option_lh)). -dit(bf(LOGNAME)) Is used as name for the socks client user name if no +dit(bf(LOGNAME) (input)) Is used as name for the socks client user name if no link(socksuser)(OPTION_SOCKSUSER) is given.nl() With options link(su)(OPTION_SUBSTUSER) and link(su-d)(OPTION_SUBSTUSER_DELAYED), LOGNAME is set to the given user name. -dit(bf(USER)) Is used as name for the socks client user name if no +dit(bf(USER) (input)) Is used as name for the socks client user name if no link(socksuser)(OPTION_SOCKSUSER) is given and LOGNAME is empty.nl() With options link(su)(OPTION_SUBSTUSER) and link(su-d)(OPTION_SUBSTUSER_DELAYED), USER is set to the given user name. -dit(bf(SHELL)) +dit(bf(SHELL) (output)) With options link(su)(OPTION_SUBSTUSER) and link(su-d)(OPTION_SUBSTUSER_DELAYED), SHELL is set to the login shell of the given user. -dit(bf(PATH)) +dit(bf(PATH) (output)) Can be set with option link(path)(OPTION_PATH) for link(exec)(ADDRESS_EXEC) and link(system)(ADDRESS_SYSTEM) addresses. -dit(bf(HOME)) +dit(bf(HOME) (output)) With options link(su)(OPTION_SUBSTUSER) and link(su-d)(OPTION_SUBSTUSER_DELAYED), HOME is set to the home directory of the given user. @@ -2991,7 +3455,7 @@ standard specifications available on the Internet for free. label(VERSION) manpagesection(VERSION) -This man page describes version 1.6.0 of socat(). +This man page describes version 2.0.0-b2 of socat(). label(BUGS) diff --git a/error.c b/error.c index 54e2dd5..9130936 100644 --- a/error.c +++ b/error.c @@ -1,5 +1,5 @@ /* source: error.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* the logging subsystem */ @@ -39,7 +39,6 @@ struct diag_opts { const char *progname; int msglevel; int exitlevel; - int logstderr; int syslog; FILE *logfile; int logfacility; @@ -51,7 +50,7 @@ struct diag_opts { struct diag_opts diagopts = - { NULL, E_ERROR, E_ERROR, 1, 0, NULL, LOG_DAEMON, false, 0 } ; + { NULL, E_ERROR, E_ERROR, 0, NULL, LOG_DAEMON, false, 0 } ; static void _msg(int level, const char *buff, const char *syslp); @@ -89,7 +88,21 @@ static struct wordent facilitynames[] = { } ; +static int diaginitialized; +static int diag_init(void) { + if (diaginitialized) { + return 0; + } + diaginitialized = 1; + /* gcc with GNU libc refuses to set this in the initializer */ + diagopts.logfile = stderr; + return 0; +} +#define DIAG_INIT ((void)(diaginitialized || diag_init())) + + void diag_set(char what, const char *arg) { + DIAG_INIT; switch (what) { const struct wordent *keywd; @@ -100,18 +113,28 @@ void diag_set(char what, const char *arg) { sizeof(facilitynames)/sizeof(struct wordent))) == NULL) { Error1("unknown syslog facility \"%s\"", arg); } else { - diagopts.logfacility = (int)keywd->desc; + diagopts.logfacility = (int)(size_t)keywd->desc; } } openlog(diagopts.progname, LOG_PID, diagopts.logfacility); - diagopts.logstderr = false; break; - case 'f': if ((diagopts.logfile = fopen(arg, "a")) == NULL) { - Error2("cannot open log file \"%s\": %s", arg, strerror(errno)); - break; - } else { - diagopts.logstderr = false; break; + if (diagopts.logfile != NULL && diagopts.logfile != stderr) { + fclose(diagopts.logfile); } - case 's': diagopts.logstderr = true; break; /* logging to stderr is default */ + diagopts.logfile = NULL; + break; + case 'f': + if (diagopts.logfile != NULL && diagopts.logfile != stderr) { + fclose(diagopts.logfile); + } + if ((diagopts.logfile = fopen(arg, "a")) == NULL) { + Error2("cannot open log file \"%s\": %s", arg, strerror(errno)); + } + break; + case 's': + if (diagopts.logfile != NULL && diagopts.logfile != stderr) { + fclose(diagopts.logfile); + } + diagopts.logfile = stderr; break; /* logging to stderr is default */ case 'p': diagopts.progname = arg; openlog(diagopts.progname, LOG_PID, diagopts.logfacility); break; @@ -122,6 +145,7 @@ void diag_set(char what, const char *arg) { } void diag_set_int(char what, int arg) { + DIAG_INIT; switch (what) { case 'D': diagopts.msglevel = arg; break; case 'e': diagopts.exitlevel = arg; break; @@ -138,9 +162,10 @@ void diag_set_int(char what, int arg) { } int diag_get_int(char what) { + DIAG_INIT; switch (what) { case 'y': return diagopts.syslog; - case 's': return diagopts.logstderr; + case 's': return diagopts.logfile == stderr; case 'd': case 'D': return diagopts.msglevel; case 'e': return diagopts.exitlevel; } @@ -148,6 +173,7 @@ int diag_get_int(char what) { } const char *diag_get_string(char what) { + DIAG_INIT; switch (what) { case 'p': return diagopts.progname; } @@ -170,6 +196,7 @@ void msg(int level, const char *format, ...) { size_t bytes; va_list ap; + DIAG_INIT; if (level < diagopts.msglevel) return; va_start(ap, format); #if HAVE_GETTIMEOFDAY || 1 @@ -237,9 +264,6 @@ void msg(int level, const char *format, ...) { static void _msg(int level, const char *buff, const char *syslp) { - if (diagopts.logstderr) { - fputs(buff, stderr); fflush(stderr); - } if (diagopts.syslog) { /* prevent format string attacks (thanks to CoKi) */ syslog(syslevel[level], "%s", syslp); @@ -248,3 +272,24 @@ static void _msg(int level, const char *buff, const char *syslp) { fputs(buff, diagopts.logfile); fflush(diagopts.logfile); } } + + +/* use a new log output file descriptor that is dup'ed from the current one. + this is useful when socat logs to stderr but fd 2 should be redirected to + serve other purposes */ +int diag_dup(void) { + int newfd; + + DIAG_INIT; + if (diagopts.logfile == NULL) { + return -1; + } + newfd = dup(fileno(diagopts.logfile)); + if (diagopts.logfile != stderr) { + fclose(diagopts.logfile); + } + if (newfd >= 0) { + diagopts.logfile = fdopen(newfd, "w"); + } + return newfd; +} diff --git a/error.h b/error.h index 537987f..385738c 100644 --- a/error.h +++ b/error.h @@ -1,5 +1,5 @@ /* source: error.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __error_h_included @@ -50,6 +50,9 @@ #define Error6(m,a1,a2,a3,a4,a5,a6) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6) #define Error7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6,a7) #define Error8(m,a1,a2,a3,a4,a5,a6,a7,a8) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6,a7,a8) +#define Error9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6,a7,a8,a9) +#define Error10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) +#define Error11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) #else /* !(WITH_MSGLEVEL >= E_ERROR) */ #define Error(m) #define Error1(m,a1) @@ -60,6 +63,9 @@ #define Error6(m,a1,a2,a3,a4,a5,a6) #define Error7(m,a1,a2,a3,a4,a5,a6,a7) #define Error8(m,a1,a2,a3,a4,a5,a6,a7,a8) +#define Error9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9) +#define Error10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) +#define Error11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) #endif /* !(WITH_MSGLEVEL <= E_ERROR) */ #if WITH_MSGLEVEL <= E_WARN @@ -202,7 +208,8 @@ extern void diag_set(char what, const char *arg); extern void diag_set_int(char what, int arg); extern int diag_get_int(char what); extern const char *diag_get_string(char what); - +extern int diag_dup(void); +extern int diag_dup2(int newfd); extern void msg(int level, const char *format, ...); #endif /* !defined(__error_h_included) */ diff --git a/fdname.c b/fdname.c index 8ede9fe..bc15103 100644 --- a/fdname.c +++ b/fdname.c @@ -1,5 +1,5 @@ /* source: fdname.c */ -/* Copyright Gerhard Rieger 2003-2007 */ +/* Copyright Gerhard Rieger 2003-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* the subroutine sockname prints the basic info about the address of a socket @@ -32,7 +32,7 @@ int unixame(int fd, FILE *outfile); int tcpname(int fd, FILE *outfile); -int fdname(const char *file, int fd, FILE *outfile) { +int fdname(const char *file, int fd, FILE *outfile, const char *numform) { struct stat buf = {0}; int filetype; Debug1("checking file descriptor %u", fd); @@ -46,6 +46,9 @@ int fdname(const char *file, int fd, FILE *outfile) { } } filetype = (buf.st_mode&S_IFMT)>>12; + if (numform != NULL) { + fprintf(outfile, numform, fd); + } return statname(file, fd, filetype, outfile); } else { if (Stat(file, &buf) < 0) { @@ -139,7 +142,7 @@ int statname(const char *file, int fd, int filetype, FILE *outfile) { if (file) fprintf(outfile, " %s", file); break; case (S_IFSOCK>>12): /* 12, socket */ -#if WITH_SOCKET +#if _WITH_SOCKET if (fd >= 0) { result = sockname(fd, outfile); } else if (file) { @@ -150,7 +153,7 @@ int statname(const char *file, int fd, int filetype, FILE *outfile) { #else Error("SOCKET support not compiled in"); return -1; -#endif /* !WITH_SOCKET */ +#endif /* !_WITH_SOCKET */ break; } /* ioctl() */ @@ -185,7 +188,7 @@ int cdevname(int fd, FILE *outfile) { } -#if WITH_SOCKET +#if _WITH_SOCKET int sockname(int fd, FILE *outfile) { #define FDNAME_OPTLEN 256 #define FDNAME_NAMELEN 256 @@ -320,7 +323,7 @@ int sockname(int fd, FILE *outfile) { #undef FDNAME_OPTLEN #undef FDNAME_NAMELEN } -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ diff --git a/filan.c b/filan.c index e0477d1..6461e47 100644 --- a/filan.c +++ b/filan.c @@ -1,5 +1,5 @@ /* source: filan.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* the subroutine filan makes a "FILe descriptor ANalysis". It checks the @@ -26,7 +26,9 @@ struct sockopt { char *name; }; -/* dirty workaround so we dont get an error on AIX when getting linked with +static int filan_streams_analyze(int fd, FILE *outfile); + +/* dirty workaround so we dont get an error on AIX when being linked with libwrap */ int allow_severity, deny_severity; @@ -127,7 +129,17 @@ int filan_fd(int fd, FILE *outfile) { { /* see if data is available */ struct pollfd ufds; ufds.fd = fd; - ufds.events = POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|POLLWRNORM|POLLWRBAND + ufds.events = POLLIN|POLLPRI|POLLOUT +#ifdef POLLRDNORM + |POLLRDNORM +#endif +#ifdef POLLRDBAND + |POLLRDBAND +#endif + |POLLWRNORM +#ifdef POLLWRBAND + |POLLWRBAND +#endif #ifdef POLLMSG |POLLMSG #endif @@ -150,7 +162,7 @@ int filan_fd(int fd, FILE *outfile) { } } #endif /* defined(FIONREAD) */ -#if WITH_SOCKET && defined(MSG_DONTWAIT) +#if _WITH_SOCKET && defined(MSG_DONTWAIT) if ((ufds.revents & POLLIN) && isasocket(fd)) { char _peername[SOCKADDR_MAX]; struct sockaddr *pa = (struct sockaddr *)_peername; @@ -186,7 +198,7 @@ int filan_fd(int fd, FILE *outfile) { fprintf(outfile, "recvmsg="F_Zd", ", bytes); } } -#endif /* WITH_SOCKET && defined(MSG_DONTWAIT) */ +#endif /* _WITH_SOCKET && defined(MSG_DONTWAIT) */ } } } @@ -353,6 +365,9 @@ int filan_stat( , outfile); } + /* ever heard of POSIX streams? here we handle these */ + filan_streams_analyze(statfd, outfile); + /* now see for type specific infos */ if (statfd >= 0) { /*!indent */ switch (buf->st_mode&S_IFMT) { @@ -371,12 +386,12 @@ int filan_stat( break; #ifdef S_IFSOCK case (S_IFSOCK): /* 12, socket */ -#if WITH_SOCKET +#if _WITH_SOCKET result = sockan(statfd, outfile); #else Warn("SOCKET support not compiled in"); return -1; -#endif /* !WITH_SOCKET */ +#endif /* !_WITH_SOCKET */ break; #endif /* S_IFSOCK */ } @@ -408,10 +423,53 @@ int devinfo(int fd) { #endif +/* returns 0 on success (not a stream descriptor, or no module) + returns <0 on failure */ +static int filan_streams_analyze(int fd, FILE *outfile) { +#ifdef I_LIST +# define SL_NMODS 8 /* max number of module names we can store */ + struct str_list modnames; + int i; + + if (!isastream(fd)) { + fprintf(outfile, "\t(no STREAMS modules)"); + return 0; + } +#if 0 /* uncomment for debugging */ + fprintf(outfile, "\tfind=%d", ioctl(fd, I_FIND, "ldterm")); +#endif + modnames.sl_nmods = ioctl(fd, I_LIST, 0); + if (modnames.sl_nmods < 0) { + fprintf(stderr, "ioctl(%d, I_LIST, 0): %s\n", fd, strerror(errno)); + return -1; + } + modnames.sl_modlist = Malloc(modnames.sl_nmods*(sizeof(struct str_mlist))); + if (modnames.sl_modlist == NULL) { + fprintf(stderr, "out of memory\n"); + return -1; + } + if (ioctl(fd, I_LIST, &modnames) < 0) { + fprintf(stderr, "ioctl(%d, I_LIST, %p): %s\n", + fd, &modnames, strerror(errno)); + free(modnames.sl_modlist); + return -1; + } + fprintf(outfile, "\tSTREAMS: "); + for (i = 0; i < modnames.sl_nmods; ++i) { + fprintf(outfile, "\"%s\"", modnames.sl_modlist[i].l_name); + if (i+1 < modnames.sl_nmods) fputc(',', outfile); + } + free(modnames.sl_modlist); +#endif /* defined(I_LIST) */ + return 0; +} + + /* character device analysis */ int cdevan(int fd, FILE *outfile) { int ret; +#if _WITH_TERMIOS if ((ret = Isatty(fd)) < 0) { Warn2("isatty(%d): %s", fd, strerror(errno)); return -1; @@ -458,11 +516,12 @@ int cdevan(int fd, FILE *outfile) { } } } +#endif /* _WITH_TERMIOS */ return 0; } -#if WITH_SOCKET +#if _WITH_SOCKET int sockan(int fd, FILE *outfile) { #define FILAN_OPTLEN 256 #define FILAN_NAMELEN 256 @@ -479,6 +538,9 @@ int sockan(int fd, FILE *outfile) { {SO_REUSEADDR, "REUSEADDR"}, {SO_TYPE, "TYPE"}, {SO_ERROR, "ERROR"}, +#ifdef SO_PROTOTYPE + {SO_PROTOTYPE, "PROTOTYPE"}, +#endif {SO_DONTROUTE, "DONTROUTE"}, {SO_BROADCAST, "BROADCAST"}, {SO_SNDBUF, "SNDBUF"}, @@ -634,7 +696,7 @@ int sockan(int fd, FILE *outfile) { #undef FILAN_OPTLEN #undef FILAN_NAMELEN } -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ #if WITH_IP4 || WITH_IP6 @@ -823,7 +885,7 @@ int tcpan(int fd, FILE *outfile) { #endif /* WITH_TCP */ -#if WITH_SOCKET +#if _WITH_SOCKET int sockoptan(int fd, const struct sockopt *optname, int socklay, FILE *outfile) { #define FILAN_OPTLEN 256 char optval[FILAN_OPTLEN]; @@ -859,10 +921,10 @@ int sockoptan(int fd, const struct sockopt *optname, int socklay, FILE *outfile) return 0; #undef FILAN_OPTLEN } -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ -#if WITH_SOCKET +#if _WITH_SOCKET int isasocket(int fd) { int retval; #if HAVE_STAT64 @@ -883,7 +945,7 @@ int isasocket(int fd) { /* note: when S_ISSOCK was undefined, it always gives 0 */ return S_ISSOCK(props.st_mode); } -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ const char *getfiletypestring(int st_mode) { diff --git a/filan.h b/filan.h index 8ed3484..bea30f4 100644 --- a/filan.h +++ b/filan.h @@ -1,5 +1,5 @@ /* source: filan.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ @@ -26,13 +26,14 @@ extern int filan_stat( extern int cdevan(int fd, FILE *outfile); -#if WITH_SOCKET +#if _WITH_SOCKET extern int isasocket(int fd); extern int sockan(int fd, FILE *outfile); extern int ipan(int fd, FILE *outfile); extern int ip6an(int fd, FILE *outfile); -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ -extern int fdname(const char *file, int fd, FILE *outfile); +extern + int fdname(const char *file, int fd, FILE *outfile, const char *numform); #endif /* !defined(__filan_h_included) */ diff --git a/filan_main.c b/filan_main.c index 3a52f2b..866b271 100644 --- a/filan_main.c +++ b/filan_main.c @@ -1,5 +1,5 @@ /* source: filan_main.c */ -/* Copyright Gerhard Rieger 2001-2006 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ const char copyright[] = "filan by Gerhard Rieger - see http://www.dest-unreach.org/socat/"; @@ -23,7 +23,8 @@ static void filan_usage(FILE *fd); int main(int argc, const char *argv[]) { const char **arg1, *a; const char *filename = NULL, *waittimetxt; - unsigned int m = 0, n = 1024; /* this is default on my Linux */ + unsigned int m = 0; /* first FD (default) */ + unsigned int n = FD_SETSIZE; /* last excl. */ unsigned int i; int style = 0; struct timespec waittime = { 0, 0 }; @@ -57,7 +58,7 @@ int main(int argc, const char *argv[]) { } } m = strtoul(a, (char **)&a, 0); - n = m+1; + n = m; break; case 'n': if (arg1[0][2]) { a = *arg1+2; @@ -127,11 +128,11 @@ int main(int argc, const char *argv[]) { exit(1); } if (outfname) { - // special cases + /* special cases */ if (!strcmp(outfname,"stdin")) { fdout=stdin; } else if (!strcmp(outfname,"stdout")) { fdout=stdout; } else if (!strcmp(outfname,"stderr")) { fdout=stderr; } - // file descriptor + /* file descriptor */ else if (*outfname == '+') { a = outfname+1; fildes = strtoul(a, (char **)&a, 0); @@ -140,7 +141,7 @@ int main(int argc, const char *argv[]) { exit(1); } } else { - // file name + /* file name */ if ((fdout = fopen(outfname, "w")) == NULL) { Error2("can't fopen '%s': %s\n", outfname, strerror(errno)); @@ -168,6 +169,9 @@ int main(int argc, const char *argv[]) { #endif filan_file(filename, fdout); } else { + if (m == n) { + ++n; + } for (i = m; i < n; ++i) { filan_fd(i, fdout); } @@ -189,12 +193,16 @@ int main(int argc, const char *argv[]) { Debug2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s", filename, strerror(errno)); } - fdname(filename, fd, fdout); + fdname(filename, fd, fdout, NULL); #endif - fdname(filename, -1, fdout); + fdname(filename, -1, fdout, NULL); } else { - for (i = m; i < n; ++i) { - fdname("", i, fdout); + if (m == n) { + fdname("", m, fdout, NULL); + } else { + for (i = m; i < n; ++i) { + fdname("", i, fdout, "%5u "); + } } } } @@ -225,7 +233,7 @@ static void filan_usage(FILE *fd) { fputs(" -ls log to stderr (default if no other log)\n", fd); #endif fputs(" -i only analyze this fd\n", fd); - fputs(" -n analyze all fds from 0 up to fdnum-1 (default: 1024)\n", fd); + fprintf(fd, " -n analyze all fds from 0 up to fdnum-1 (default: %u)\n", FD_SETSIZE); fputs(" -s simple output with just type and socket address or path\n", fd); /* fputs(" -c alternate device visualization\n", fd);*/ fputs(" -f analyze file system entry\n", fd); diff --git a/hostan.c b/hostan.c index 8862bf5..9977914 100644 --- a/hostan.c +++ b/hostan.c @@ -20,22 +20,21 @@ static int iffan(FILE *outfile); int hostan(FILE *outfile) { -#if WITH_SOCKET +#if _WITH_SOCKET fprintf(outfile, "\nIP INTERFACES\n"); iffan(outfile); #endif return 0; } -#if WITH_SOCKET +#if _WITH_SOCKET static int iffan(FILE *outfile) { /* Linux: man 7 netdevice */ - /* FreeBSD: man 4 networking */ + /* FreeBSD, NetBSD: man 4 networking */ /* Solaris: man 7 if_tcp */ /* currently we support Linux and a little FreeBSD */ #ifdef SIOCGIFCONF /* not Solaris */ -#ifdef SIOCGIFINDEX /* not OpenBSD */ #define IFBUFSIZ 32*sizeof(struct ifreq) /*1024*/ int s; @@ -62,22 +61,24 @@ static int iffan(FILE *outfile) { struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i); struct ifreq ifr; +#if 0 || defined(SIOCGIFINDEX) /* not NetBSD, OpenBSD */ strcpy(ifr.ifr_name, ifp->ifr_name); if (Ioctl(s, SIOCGIFINDEX, &ifr) < 0) { Error3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}): %s", s, &ifr.ifr_name, strerror(errno)); return 1; } - /*fprintf(outfile, "%2d: %s\n", ifr.ifr_ifindex, ifp->ifr_ifrn.ifrn_name);*/ #if HAVE_STRUCT_IFREQ_IFR_INDEX fprintf(outfile, "%2d: %s\n", ifr.ifr_index, ifp->ifr_name); #elif HAVE_STRUCT_IFREQ_IFR_IFINDEX fprintf(outfile, "%2d: %s\n", ifr.ifr_ifindex, ifp->ifr_name); #endif /* HAVE_STRUCT_IFREQ_IFR_INDEX */ +#else /* !defined(SIOCGIFINDEX) */ + fprintf(outfile, "%2d: %s\n", i/sizeof(struct ifreq), ifp->ifr_name); +#endif /* defined(SIOCGIFINDEX) */ } Close(s); #endif /* defined(SIOCGIFCONF) */ -#endif /* defined(SIOCGIFINDEX) */ return 0; } -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ diff --git a/procan-cdefs.c b/procan-cdefs.c index 14333de..f7442f9 100644 --- a/procan-cdefs.c +++ b/procan-cdefs.c @@ -20,7 +20,7 @@ int procan_cdefs(FILE *outfile) { fprintf(outfile, "#define FD_SETSIZE %u\n", FD_SETSIZE); #endif #ifdef NFDBITS - fprintf(outfile, "#define NFDBITS %u\n", NFDBITS); + fprintf(outfile, "#define NFDBITS "F_Zu"\n", NFDBITS); #endif #ifdef O_RDONLY fprintf(outfile, "#define O_RDONLY %u\n", O_RDONLY); @@ -75,10 +75,90 @@ int procan_cdefs(FILE *outfile) { #ifdef CSIZE fprintf(outfile, "#define CSIZE 0%011o\n", CSIZE); #endif +#ifdef TIOCEXCL + fprintf(outfile, "#define TIOCEXCL 0x%lx\n", (unsigned long)TIOCEXCL); +#endif /* stdio constants */ #ifdef FOPEN_MAX fprintf(outfile, "#define FOPEN_MAX %u\n", FOPEN_MAX); #endif + + /* socket constants */ +#ifdef PF_UNIX + fprintf(outfile, "#define PF_UNIX %d\n", PF_UNIX); +#elif defined(PF_LOCAL) + fprintf(outfile, "#define PF_LOCAL %d\n", PF_LOCAL); +#endif +#ifdef PF_INET + fprintf(outfile, "#define PF_INET %d\n", PF_INET); +#endif +#ifdef PF_INET6 + fprintf(outfile, "#define PF_INET6 %d\n", PF_INET6); +#endif +#ifdef PF_APPLETALK + fprintf(outfile, "#define PF_APPLETALK %d\n", PF_APPLETALK); +#endif +#ifdef PF_PACKET + fprintf(outfile, "#define PF_PACKET %d\n", PF_PACKET); +#endif +#ifdef SOCK_STREAM + fprintf(outfile, "#define SOCK_STREAM %d\n", SOCK_STREAM); +#endif +#ifdef SOCK_DGRAM + fprintf(outfile, "#define SOCK_DGRAM %d\n", SOCK_DGRAM); +#endif +#ifdef SOCK_RAW + fprintf(outfile, "#define SOCK_RAW %d\n", SOCK_RAW); +#endif +#ifdef SOCK_SEQPACKET + fprintf(outfile, "#define SOCK_SEQPACKET %d\n", SOCK_SEQPACKET); +#endif +#ifdef SOCK_PACKET + fprintf(outfile, "#define SOCK_PACKET %d\n", SOCK_PACKET); +#endif +#ifdef IPPROTO_IP + fprintf(outfile, "#define IPPROTO_IP %d\n", IPPROTO_IP); +#endif +#ifdef IPPROTO_TCP + fprintf(outfile, "#define IPPROTO_TCP %d\n", IPPROTO_TCP); +#endif +#ifdef IPPROTO_UDP + fprintf(outfile, "#define IPPROTO_UDP %d\n", IPPROTO_UDP); +#endif +#ifdef IPPROTO_SCTP + fprintf(outfile, "#define IPPROTO_SCTP %d\n", IPPROTO_SCTP); +#endif +#ifdef IPPROTO_DCCP + fprintf(outfile, "#define IPPROTO_DCCP %d\n", IPPROTO_DCCP); +#endif +#ifdef SOL_SOCKET + fprintf(outfile, "#define SOL_SOCKET 0x%x\n", SOL_SOCKET); +#endif +#ifdef SOL_PACKET + fprintf(outfile, "#define SOL_PACKET 0x%x\n", SOL_PACKET); +#endif +#ifdef SOL_IP + fprintf(outfile, "#define SOL_IP 0x%x\n", SOL_IP); +#endif +#ifdef SOL_IPV6 + fprintf(outfile, "#define SOL_IPV6 0x%x\n", SOL_IPV6); +#endif +#ifdef SOL_TCP + fprintf(outfile, "#define SOL_TCP 0x%x\n", SOL_TCP); +#endif +#ifdef SOL_UDP + fprintf(outfile, "#define SOL_UDP 0x%x\n", SOL_UDP); +#endif +#ifdef SOL_SCTP + fprintf(outfile, "#define SOL_SCTP 0x%x\n", SOL_SCTP); +#endif +#ifdef SOL_DCCP + fprintf(outfile, "#define SOL_DCCP 0x%x\n", SOL_DCCP); +#endif +#ifdef SO_REUSEADDR + fprintf(outfile, "#define SO_REUSEADDR %d\n", SO_REUSEADDR); +#endif + return 0; } diff --git a/readline-test.sh b/readline-test.sh index 569bff6..2242ea9 100755 --- a/readline-test.sh +++ b/readline-test.sh @@ -1,6 +1,6 @@ #! /bin/bash # source: readline-test.sh -# Copyright Gerhard Rieger 2003 +# Copyright Gerhard Rieger 2003-2008 # Published under the GNU General Public License V.2, see file COPYING # script that simulates a simple program with authentication. @@ -29,8 +29,9 @@ trap "$ECHO $0 got SIGQUIT" QUIT # print banner $ECHO "$BANNER" -read -r -p "$($ECHO "$USERPROMPT")" USERNAME -read -rs -p "$PWDPROMPT" PASSWORD +# on (some) ksh read -p does not mean prompt +$ECHO "$USERPROMPT\c"; read -r USERNAME +$ECHO "$PWDPROMPT\c"; read -rs PASSWORD $ECHO if [ "$USERNAME" != "$CREDUSER" -o "$PASSWORD" != "$CREDPASS" ]; then @@ -38,7 +39,7 @@ if [ "$USERNAME" != "$CREDUSER" -o "$PASSWORD" != "$CREDPASS" ]; then exit -1 fi -while read -r -p "$PROMPT" COMMAND; do +while $ECHO "$PROMPT\c"; read -r COMMAND; do if [ "$COMMAND" = "exit" ]; then break; fi diff --git a/socat.c b/socat.c index f77feb8..5a4003f 100644 --- a/socat.c +++ b/socat.c @@ -63,12 +63,16 @@ bool havelock; int main(int argc, const char *argv[]) { const char **arg1, *a; + char *mainwaitstring; char buff[10]; double rto; int i, argc0, result; struct utsname ubuf; int lockrc; + if (mainwaitstring = getenv("SOCAT_MAIN_WAIT")) { + sleep(atoi(mainwaitstring)); + } diag_set('p', strchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]); /* we must init before applying options because env settings have lower @@ -249,12 +253,14 @@ int main(int argc, const char *argv[]) { Error("-U and -u must not be combined"); } + xioinitialize2(); Info(copyright_socat); #if WITH_OPENSSL Info(copyright_openssl); Info(copyright_ssleay); #endif Debug2("socat version %s on %s", socatversion, timestamp); + xiosetenv("VERSION", socatversion, 1); /* SOCAT_VERSION */ uname(&ubuf); /* ! here we circumvent internal tracing (Uname) */ Debug4("running on %s version %s, release %s, machine %s\n", ubuf.sysname, ubuf.version, ubuf.release, ubuf.machine); @@ -428,6 +434,16 @@ void socat_version(FILE *fd) { #else fputs(" #undef WITH_RAWIP\n", fd); #endif +#ifdef WITH_GENERICSOCKET + fprintf(fd, " #define WITH_GENERICSOCKET %d\n", WITH_GENERICSOCKET); +#else + fputs(" #undef WITH_GENERICSOCKET\n", fd); +#endif +#ifdef WITH_INTERFACE + fprintf(fd, " #define WITH_INTERFACE %d\n", WITH_INTERFACE); +#else + fputs(" #undef WITH_INTERFACE\n", fd); +#endif #ifdef WITH_TCP fprintf(fd, " #define WITH_TCP %d\n", WITH_TCP); #else @@ -438,6 +454,11 @@ void socat_version(FILE *fd) { #else fputs(" #undef WITH_UDP\n", fd); #endif +#ifdef WITH_SCTP + fprintf(fd, " #define WITH_SCTP %d\n", WITH_SCTP); +#else + fputs(" #undef WITH_SCTP\n", fd); +#endif #ifdef WITH_LISTEN fprintf(fd, " #define WITH_LISTEN %d\n", WITH_LISTEN); #else @@ -590,677 +611,23 @@ int socat(int argc, const char *address1, const char *address2) { } -#if 0 -/* 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) && - (/*0 XIO_RDSTREAM(xfd)->howtoclose == END_KILL ||*/ - XIO_RDSTREAM(xfd)->howtoclose == END_CLOSE_KILL || - XIO_RDSTREAM(xfd)->howtoclose == END_SHUTDOWN_KILL) && - XIO_RDSTREAM(xfd)->child.pid == 0) { - struct timeval time0 = { 0,0 }; +/* childleftdata() has been moved to xioengine.c */ - 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; - closing = MAX(closing, 1); - } - } - return 0; -} -#endif /* 0 */ +/* _socat() has been moved to xioengine.c */ -#if 0 -bool mayrd1; /* sock1 has read data or eof, according to select() */ -bool mayrd2; /* sock2 has read data or eof, according to select() */ -bool maywr1; /* sock1 can be written to, according to select() */ -bool maywr2; /* sock2 can be written to, according to select() */ +/* gettimestamp() has been moved to xiotransfer.c */ -/* 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) { - 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 */ - sock1 = xfd1; - sock2 = xfd2; +/* xioprintblockheader has been moved to xiotransfer.c */ -#if WITH_FILAN - if (socat_opts.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 */ +/* xiotransfer has been moved to xiotransfer.c */ - 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); - } +/* cv_newline has been moved to xiotransfer.c */ - 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 (socat_opts.logopt == 'm' && xioinqopt('l', NULL, 0) == 'm') { - Info("switching to syslog"); - diag_set('y', xioopts.syslogfac); - xiosetopt('l', "\0"); - } - total_timeout = socat_opts.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; - - Debug6("data loop: sock1->eof=%d, sock2->eof=%d, closing=%d, wasaction=%d, total_to={"F_tv_sec"."F_tv_usec"}", - XIO_RDSTREAM(sock1)->eof, XIO_RDSTREAM(sock2)->eof, - closing, 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 (socat_opts.pollintv.tv_sec) Sleep(socat_opts.pollintv.tv_sec); - if (socat_opts.pollintv.tv_usec) Usleep(socat_opts.pollintv.tv_usec); - - if (socat_opts.total_timeout.tv_sec != 0 || - socat_opts.total_timeout.tv_usec != 0) { - if (total_timeout.tv_usec < socat_opts.pollintv.tv_usec) { - total_timeout.tv_usec += 1000000; - total_timeout.tv_sec -= 1; - } - total_timeout.tv_sec -= socat_opts.pollintv.tv_sec; - total_timeout.tv_usec -= socat_opts.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 = socat_opts.pollintv; - to = &timeout; - } else if (socat_opts.total_timeout.tv_sec != 0 || - socat_opts.total_timeout.tv_usec != 0) { - /* there might occur a total inactivity timeout */ - timeout = socat_opts.total_timeout; - to = &timeout; - } else { - to = NULL; - } - - if (closing>=1) { - /* first eof already occurred, start end timer */ - timeout = socat_opts.closwait; - to = &timeout; - closing = 2; - } - - do { - int _errno; - FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt); - - childleftdata(sock1); - childleftdata(sock2); - - if (closing>=1) { - /* first eof already occurred, start end timer */ - timeout = socat_opts.closwait; - to = &timeout; - closing = 2; - } - - if (XIO_READABLE(sock1) && - !(XIO_RDSTREAM(sock1)->eof > 1 && !XIO_RDSTREAM(sock1)->ignoreeof) && - !socat_opts.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) && - !socat_opts.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)", - closing>=1?socat_opts.closwait.tv_sec:socat_opts.total_timeout.tv_sec, - closing>=1?socat_opts.closwait.tv_usec:socat_opts.total_timeout.tv_usec); - if (polling && !wasaction) { - /* there was a ignoreeof poll timeout, use it */ - ; - } else if (socat_opts.total_timeout.tv_sec != 0 || - socat_opts.total_timeout.tv_usec != 0) { - /* there was a total inactivity timeout */ - Notice("inactivity timeout triggered"); - return 0; - } - - if (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; - } - - if (XIO_READABLE(sock1) && XIO_GETRDFD(sock1) >= 0 && - FD_ISSET(XIO_GETRDFD(sock1), &in)) { - mayrd1 = true; - } - if (XIO_READABLE(sock2) && XIO_GETRDFD(sock2) >= 0 && - FD_ISSET(XIO_GETRDFD(sock2), &in)) { - mayrd2 = true; - } - 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) { - closing = MAX(closing, 1); - Notice("socket 1 to socket 2 is in error"); - if (socat_opts.lefttoright) { - break; - } - } - } else if (bytes1 > 0) { - maywr2 = false; - total_timeout = socat_opts.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 { /* bytes2 == 0 */ - if (XIO_RDSTREAM(sock1)->ignoreeof && !closing) { - ; - } else { - XIO_RDSTREAM(sock1)->eof = 2; - closing = MAX(closing, 1); - } - /* (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) { - closing = MAX(closing, 1); - Notice("socket 2 to socket 1 is in error"); - if (socat_opts.righttoleft) { - break; - } - } - } else if (bytes2 > 0) { - maywr1 = false; - total_timeout = socat_opts.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 && !closing) { - ; - } else { - XIO_RDSTREAM(sock2)->eof = 2; - closing = MAX(closing, 1); - } - /* (bytes2 == 0) handled later */ - } - } else { - bytes2 = -1; - } - - /* NOW handle EOFs */ - - if (bytes1 == 0 || XIO_RDSTREAM(sock1)->eof >= 2) { - if (XIO_RDSTREAM(sock1)->ignoreeof && !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); - if (socat_opts.lefttoright) { - break; - } - } - } - - if (bytes2 == 0 || XIO_RDSTREAM(sock2)->eof >= 2) { - if (XIO_RDSTREAM(sock2)->ignoreeof && !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); - if (socat_opts.righttoleft) { - break; - } - } - } - } - - /* close everything that's still open */ - xioclose(sock1); - xioclose(sock2); - - return 0; -} -#endif /* 0 */ - -#if 0 -#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; -} -#endif - -#if 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; -} -#endif /* 0 */ - -#if 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, xioparams->bufsiz); - if (bytes < 0) { - if (errno != EAGAIN) - XIO_RDSTREAM(inpipe)->eof = 2; - /*xioshutdown(inpipe, SHUT_RD);*/ - return -1; - } - if (bytes == 0 && XIO_RDSTREAM(inpipe)->ignoreeof && !closing) { - writt = 0; - } else if (bytes == 0) { - XIO_RDSTREAM(inpipe)->eof = 2; - closing = MAX(closing, 1); - 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 (socat_opts.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; -} -#endif /* 0 */ - -#if 0 - -#define CR '\r' -#define LF '\n' - -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; -} -#endif /* 0 */ void socat_signal(int signum) { switch (signum) { diff --git a/socat.spec b/socat.spec index b3a6561..370c246 100644 --- a/socat.spec +++ b/socat.spec @@ -1,6 +1,6 @@ -%define majorver 1.6 -%define minorver 0.1 +%define majorver 1.7 +%define minorver 0.0 Summary: socat - multipurpose relay Name: socat diff --git a/sycls.c b/sycls.c index 3102419..14766f3 100644 --- a/sycls.c +++ b/sycls.c @@ -1,5 +1,5 @@ /* source: sycls.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* explicit system call and C library trace function, for those who miss strace @@ -593,6 +593,16 @@ int Ioctl(int d, int request, void *argp) { return retval; } +int Ioctl_int(int d, int request, int arg) { + int retval, _errno; + Debug3("ioctl(%d, 0x%x, %d)", d, request, arg); + retval = ioctl(d, request, arg); + _errno = errno; + Debug1("ioctl() -> %d", retval); + errno = _errno; + return retval; +} + int Close(int fd) { int retval, _errno; Info1("close(%d)", fd); @@ -677,9 +687,21 @@ int Chmod(const char *path, mode_t mode) { /* we only show the first struct pollfd; hope this is enough for most cases. */ int Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { int result; - Debug4("poll({%d, 0x%02hx, }, %u, %d)", ufds[0].fd, ufds[0].events, nfds, timeout); + if (nfds == 4) { + Debug10("poll({%d,0x%02hx,}{%d,0x%02hx,}{%d,0x%02hx,}{%d,0x%02hx,}, %u, %d)", + ufds[0].fd, ufds[0].events, ufds[1].fd, ufds[1].events, + ufds[2].fd, ufds[2].events, ufds[3].fd, ufds[3].events, + nfds, timeout); + } else { + Debug4("poll({%d,0x%02hx,}, , %u, %d)", ufds[0].fd, ufds[0].events, nfds, timeout); + } result = poll(ufds, nfds, timeout); - Debug2("poll(, {,, 0x%02hx}) -> %d", ufds[0].revents, result); + if (nfds == 4) { + Debug5("poll(, {,,0x%02hx}{,,0x%02hx}{,,0x%02hx}{,,0x%02hx}) -> %d", + ufds[0].revents, ufds[1].revents, ufds[2].revents, ufds[3].revents, result); + } else { + Debug2("poll(, {,,0x%02hx}) -> %d", ufds[0].revents, result); + } return result; } #endif /* HAVE_POLL */ @@ -1081,12 +1103,28 @@ int Recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, int Recvmsg(int s, struct msghdr *msgh, int flags) { int retval, _errno; char infobuff[256]; - Debug3("recvmsg(%d, %p, %d)", s, msgh, flags); +#if defined(HAVE_STRUCT_MSGHDR_MSGCONTROL) && defined(HAVE_STRUCT_MSGHDR_MSGCONTROLLEN) && defined(HAVE_STRUCT_MSGHDR_MSGFLAGS) + Debug10("recvmsg(%d, %p{%p,%u,%p,%u,%p,%u,%d}, %d)", s, msgh, + msgh->msg_name, msgh->msg_namelen, msgh->msg_iov, msgh->msg_iovlen, + msgh->msg_control, msgh->msg_controllen, msgh->msg_flags, flags); +#else + Debug7("recvmsg(%d, %p{%p,%u,%p,%u}, %d)", s, msgh, + msgh->msg_name, msgh->msg_namelen, msgh->msg_iov, msgh->msg_iovlen, + flags); +#endif retval = recvmsg(s, msgh, flags); _errno = errno; - Debug2("recvmsg(, {%s}, ) -> %d", +#if defined(HAVE_STRUCT_MSGHDR_MSGCONTROLLEN) + Debug5("recvmsg(, {%s,%u,,%u,,%u,}, ) -> %d", msgh->msg_name?sockaddr_info(msgh->msg_name, msgh->msg_namelen, infobuff, sizeof(infobuff)):"NULL", + msgh->msg_namelen, msgh->msg_iovlen, msgh->msg_controllen, retval); +#else + Debug4("recvmsg(, {%s,%u,,%u,,}, ) -> %d", + msgh->msg_name?sockaddr_info(msgh->msg_name, msgh->msg_namelen, infobuff, sizeof(infobuff)):"NULL", + msgh->msg_namelen, msgh->msg_iovlen, + retval); +#endif errno = _errno; return retval; } @@ -1271,6 +1309,7 @@ void *Realloc(void *ptr, size_t size) { return result; } +#if _WITH_TERMIOS int Tcgetattr(int fd, struct termios *termios_p) { int i, result, _errno; char chars[5*NCCS], *cp = chars; @@ -1290,7 +1329,9 @@ int Tcgetattr(int fd, struct termios *termios_p) { errno = _errno; return result; } +#endif /* _WITH_TERMIOS */ +#if _WITH_TERMIOS int Tcsetattr(int fd, int optional_actions, struct termios *termios_p) { int i, result, _errno; char chars[5*NCCS], *cp = chars; @@ -1308,6 +1349,7 @@ int Tcsetattr(int fd, int optional_actions, struct termios *termios_p) { errno = _errno; return result; } +#endif /* _WITH_TERMIOS */ char *Ttyname(int fd) { char *result; @@ -1466,6 +1508,30 @@ int Mkstemp(char *template) { return result; } +int Setenv(const char *name, const char *value, int overwrite) { + int result, _errno; + Debug3("setenv(\"%s\", \"%s\", %d)", name, value, overwrite); + result = setenv(name, value, overwrite); + _errno = errno; + Debug1("setenv() -> %d", result); + errno = _errno; + return result; +} + +#if HAVE_UNSETENV +/* on Linux it returns int but on FreeBSD void. + we do not expect many errors, so we take void which works on all systems. */ +void Unsetenv(const char *name) { + int _errno; + Debug1("unsetenv(\"%s\")", name); + unsetenv(name); + _errno = errno; + Debug("unsetenv() ->"); + errno = _errno; + return; +} +#endif + #if WITH_READLINE char *Readline(const char *prompt) { diff --git a/sycls.h b/sycls.h index c518bc9..fa795dd 100644 --- a/sycls.h +++ b/sycls.h @@ -1,5 +1,5 @@ /* source: sycls.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __sycls_h_included @@ -64,6 +64,7 @@ int Ftruncate64(int fd, off64_t length); #endif /* HAVE_FTRUNCATE64 */ int Flock(int fd, int operation); int Ioctl(int d, int request, void *argp); +int Ioctl_int(int d, int request, int arg); int Close(int fd); int Fchown(int fd, uid_t owner, gid_t group); int Fchmod(int fd, mode_t mode); @@ -143,6 +144,8 @@ 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 Setenv(const char *name, const char *value, int overwrite); +void Unsetenv(const char *name); char *Readline(const char *prompt); void Using_history(void); @@ -207,6 +210,7 @@ int Gzclose(gzFile file) { #define Ftruncate64(f,l) ftruncate64(f,l) #define Flock(f,o) flock(f,o) #define Ioctl(d,r,a) ioctl(d,r,a) +#define Ioctl_int(d,r,a) ioctl(d,r,a) #define Close(f) close(f) #define Fchown(f,o,g) fchown(f,o,g) #define Fchmod(f,m) fchmod(f,m) @@ -272,6 +276,8 @@ int Gzclose(gzFile file) { #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 Setenv(n,v,o) setenv(n,v,o) +#define Unsetenv(n) unsetenv(n) #define Readline(p) readline(p) #define Using_history() using_history() diff --git a/sysincludes.h b/sysincludes.h index 35e5257..6806049 100644 --- a/sysincludes.h +++ b/sysincludes.h @@ -1,5 +1,5 @@ /* source: sysincludes.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __sysincludes_h_included @@ -24,7 +24,9 @@ #endif #include /* signal(), SIGPIPE, SIG_IGN */ #include /* struct timeval, strftime() */ +#if 0 #include /* struct timeb */ +#endif #if HAVE_UNISTD_H #include /* select(), read(), write(), stat(), fork() */ #endif @@ -34,7 +36,7 @@ #if HAVE_GRP_H #include /* getgrnam() */ #endif -#if HAVE_PTY_H +#if HAVE_PTY_H && _WITH_TERMIOS #include #endif #if HAVE_SYS_PARAM_H @@ -109,6 +111,9 @@ #include /* req for resolv.h (esp. on MacOSX) */ #endif #include +#if HAVE_NET_IF_DL_H +#include /* FreeBSD: struct sockaddr_dl */ +#endif #if HAVE_RESOLV_H #include /* _res */ #endif @@ -117,11 +122,23 @@ #if HAVE_NET_IF_H #include #endif /* HAVE_NET_IF_H */ +#if HAVE_LINUX_TYPES_H +#include /* __u32 for linux/errqueue.h */ +#endif +#if HAVE_LINUX_ERRQUEUE_H +#include /* struct sock_extended_err */ +#endif +#if HAVE_NETPACKET_PACKET_H +#include +#endif +#if HAVE_NETINET_IF_ETHER_H +#include +#endif #if HAVE_LINUX_IF_TUN_H #include #endif -#if HAVE_TERMIOS_H && WITH_TERMIOS +#if HAVE_TERMIOS_H && _WITH_TERMIOS #include #endif #if HAVE_SYS_UTSNAME_H diff --git a/sysutils.c b/sysutils.c index 050a94a..e7489fb 100644 --- a/sysutils.c +++ b/sysutils.c @@ -1,5 +1,5 @@ /* source: sysutils.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* translate socket addresses into human readable form */ @@ -106,6 +106,7 @@ void socket_in6_init(struct sockaddr_in6 *sa) { length of the specific socket address, or 0 on error. */ socklen_t socket_init(int af, union sockaddr_union *sa) { switch (af) { + case AF_UNSPEC: memset(sa, 0, sizeof(*sa)); return sizeof(*sa); #if WITH_UNIX case AF_UNIX: socket_un_init(&sa->un); return sizeof(sa->un); #endif @@ -115,7 +116,7 @@ socklen_t socket_init(int af, union sockaddr_union *sa) { #if WITH_IP6 case AF_INET6: socket_in6_init(&sa->ip6); return sizeof(sa->ip6); #endif - default: Error1("socket_init(): unknown address family %d", af); + default: Info1("socket_init(): unknown address family %d", af); memset(sa, 0, sizeof(union sockaddr_union)); sa->soa.sa_family = af; return 0; @@ -129,64 +130,65 @@ socklen_t socket_init(int af, union sockaddr_union *sa) { #if _WITH_SOCKET char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size_t blen) { - char ubuff[5*UNIX_PATH_MAX+3]; + union sockaddr_union *sau = (union sockaddr_union *)sa; char *lbuff = buff; char *cp = lbuff; int n; - if ((n = snprintf(cp, blen, "AF=%d ", sa->sa_family)) < 0) { +#if HAVE_STRUCT_SOCKADDR_SALEN + if ((n = snprintf(cp, blen, "LEN=%d ", sau->soa.sa_len)) < 0) { + Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen); + *buff = '\0'; + return buff; + } + cp += n, blen -= n; +#endif + if ((n = snprintf(cp, blen, "AF=%d ", sau->soa.sa_family)) < 0) { Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen); *buff = '\0'; return buff; } cp += n, blen -= n; - switch (sa->sa_family) { + switch (sau->soa.sa_family) { #if WITH_UNIX case 0: - case AF_UNIX: -#if WITH_ABSTRACT_UNIXSOCKET - if (salen > XIOUNIXSOCKOVERHEAD && - sa->sa_data[0] == '\0') { - char *nextc; -// nextc = -// sanitize_string((char *)&sa->sa_data+1, salen-XIOUNIXSOCKOVERHEAD-1, -// ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3); - nextc = - sanitize_string((char *)&sa->sa_data, salen-XIOUNIXSOCKOVERHEAD, - ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3); - *nextc = '\0'; -// snprintf(cp, blen, "\"\\0%s\"", ubuff); - snprintf(cp, blen, "\"%s\"", ubuff); - } else -#endif /* WITH_ABSTRACT_UNIXSOCKET */ - { - char *nextc; - nextc = - sanitize_string((char *)&sa->sa_data, - MIN(UNIX_PATH_MAX, strlen((char *)&sa->sa_data)), - ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3); - *nextc = '\0'; - snprintf(cp, blen, "\"%s\"", ubuff); - } + case AF_UNIX: sockaddr_unix_info(&sau->un, salen, cp+1, blen-1); + cp[0] = '"'; + *strchr(cp+1, '\0') = '"'; break; #endif #if WITH_IP4 - case AF_INET: sockaddr_inet4_info((struct sockaddr_in *)sa, cp, blen); + case AF_INET: sockaddr_inet4_info(&sau->ip4, cp, blen); break; #endif #if WITH_IP6 - case AF_INET6: sockaddr_inet6_info((struct sockaddr_in6 *)sa, cp, blen); + case AF_INET6: sockaddr_inet6_info(&sau->ip6, cp, blen); break; #endif default: + if ((n = snprintf(cp, blen, "AF=%d ", sa->sa_family)) < 0) { + Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen); + *buff = '\0'; + return buff; + } + cp += n, blen -= n; if ((snprintf(cp, blen, "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - sa->sa_data[0], sa->sa_data[1], sa->sa_data[2], - sa->sa_data[3], sa->sa_data[4], sa->sa_data[5], - sa->sa_data[6], sa->sa_data[7], sa->sa_data[8], - sa->sa_data[9], sa->sa_data[10], sa->sa_data[11], - sa->sa_data[12], sa->sa_data[13])) < 0) { + ((unsigned char *)sau->soa.sa_data)[0], + ((unsigned char *)sau->soa.sa_data)[1], + ((unsigned char *)sau->soa.sa_data)[2], + ((unsigned char *)sau->soa.sa_data)[3], + ((unsigned char *)sau->soa.sa_data)[4], + ((unsigned char *)sau->soa.sa_data)[5], + ((unsigned char *)sau->soa.sa_data)[6], + ((unsigned char *)sau->soa.sa_data)[7], + ((unsigned char *)sau->soa.sa_data)[8], + ((unsigned char *)sau->soa.sa_data)[9], + ((unsigned char *)sau->soa.sa_data)[10], + ((unsigned char *)sau->soa.sa_data)[11], + ((unsigned char *)sau->soa.sa_data)[12], + ((unsigned char *)sau->soa.sa_data)[13])) < 0) { Warn("sockaddr_info(): buffer too short"); *buff = '\0'; return buff; @@ -199,10 +201,26 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size #if WITH_UNIX char *sockaddr_unix_info(const struct sockaddr_un *sa, socklen_t salen, char *buff, size_t blen) { - blen = Min(blen, sizeof(sa->sun_path)); - strncpy(buff, sa->sun_path, blen); - if (strlen(buff) >= blen) { - buff[blen-1] = '\0'; + char ubuff[5*UNIX_PATH_MAX+3]; + char *nextc; + +#if WITH_ABSTRACT_UNIXSOCKET + if (salen > XIOUNIXSOCKOVERHEAD && + sa->sun_path[0] == '\0') { + nextc = + sanitize_string(sa->sun_path, salen-XIOUNIXSOCKOVERHEAD, + ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3); + *nextc = '\0'; + strncpy(buff, ubuff, blen); + } else +#endif /* WITH_ABSTRACT_UNIXSOCKET */ + { + nextc = + sanitize_string(sa->sun_path, + MIN(UNIX_PATH_MAX, strlen(sa->sun_path)), + ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3); + *nextc = '\0'; + strncpy(buff, ubuff, blen); } return buff; } @@ -253,6 +271,7 @@ const char *inet_ntop(int pf, const void *binaddr, return NULL; /* errno is valid */ } break; +#if WITH_IP6 case PF_INET6: if ((retlen = snprintf(addrtext, textlen, "%x:%x:%x:%x:%x:%x:%x:%x", @@ -269,6 +288,7 @@ const char *inet_ntop(int pf, const void *binaddr, return NULL; /* errno is valid */ } break; +#endif /* WITH_IP6 */ default: errno = EAFNOSUPPORT; return NULL; @@ -280,7 +300,7 @@ const char *inet_ntop(int pf, const void *binaddr, #if WITH_IP6 /* convert the IP6 socket address to human readable form. buff should be at - least 50 chars long */ + least 50 chars long. output includes the port number */ char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen) { if (snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%hu", #if HAVE_IP6_SOCKADDR==0 @@ -400,10 +420,68 @@ const char *hstrerror(int err) { return h_messages[err]; } #endif /* !HAVE_HSTRERROR */ + + +/* this function behaves like poll(). It tries to do so even when the poll() + system call is not available. */ +/* note: glibc 5.4 does not know nfds_t */ +int xiopoll(struct pollfd fds[], unsigned long nfds, struct timeval *timeout) { + int i, n = 0; + int result = 0; + + while (true) { /* should be if (), but we want to break */ + fd_set readfds; + fd_set writefds; + fd_set exceptfds; + + FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds); + for (i = 0; i < nfds; ++i) { + fds[i].revents = 0; + if (fds[i].fd < 0) { continue; } + if (fds[i].fd > FD_SETSIZE) { break; /* use poll */ } + if (fds[i].events & POLLIN) { + FD_SET(fds[i].fd, &readfds); n = MAX(n, fds[i].fd); } + if (fds[i].events & POLLOUT) { + FD_SET(fds[i].fd, &writefds); n = MAX(n, fds[i].fd); } + } + if (i < nfds) { break; /* use poll */ } + + result = Select(n+1, &readfds, &writefds, &exceptfds, timeout); + if (result < 0) { return result; } + for (i = 0; i < nfds; ++i) { + if (fds[i].fd < 0) { continue; } + if ((fds[i].events & POLLIN) && FD_ISSET(fds[i].fd, &readfds)) { + fds[i].revents |= POLLIN; ++result; + } + if ((fds[i].events & POLLOUT) && FD_ISSET(fds[i].fd, &writefds)) { + fds[i].revents |= POLLOUT; ++result; + } + } + return result; + } +#if HAVE_POLL + { + int ms = 0; + if (timeout == NULL) { + ms = -1; + } else { + ms = 1000*timeout->tv_sec + timeout->tv_usec/1000; + } + /*! timeout */ + return Poll(fds, nfds, ms); +#else /* HAVE_POLL */ + } else { + Error("poll() not available"); + return -1; +#endif /* !HAVE_POLL */ + } +} #if _WITH_TCP || _WITH_UDP -/* returns port in network byte order */ +/* returns port in network byte order; + ipproto==IPPROTO_UDP resolves as UDP service, every other value resolves as + TCP */ int parseport(const char *portname, int ipproto) { struct servent *se; char *extra; @@ -418,7 +496,7 @@ int parseport(const char *portname, int ipproto) { return result; } - if ((se = getservbyname(portname, ipproto==IPPROTO_TCP?"tcp":"udp")) == NULL) { + if ((se = getservbyname(portname, ipproto==IPPROTO_UDP?"udp":"tcp")) == NULL) { Error2("cannot resolve service \"%s/%d\"", portname, ipproto); return 0; } @@ -427,10 +505,15 @@ int parseport(const char *portname, int ipproto) { } #endif /* _WITH_TCP || _WITH_UDP */ -#if WITH_IP4 || WITH_IP6 + +#if WITH_IP4 || WITH_IP6 || WITH_INTERFACE /* check the systems interfaces for ifname and return its index - or -1 if no interface with this name was found */ -int ifindexbyname(const char *ifname) { + or -1 if no interface with this name was found + The system calls require an arbitrary socket; the calling program may + provide one in anysock to avoid creation of a dummy socket. anysock must be + <0 if it does not specify a socket fd. + */ +int ifindexbyname(const char *ifname, int anysock) { /* Linux: man 7 netdevice */ /* FreeBSD: man 4 networking */ /* Solaris: man 7 if_tcp */ @@ -438,29 +521,35 @@ int ifindexbyname(const char *ifname) { #if defined(HAVE_STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX) /* currently we support Linux, FreeBSD; not Solaris */ -#define IFBUFSIZ 1024 +#define IFBUFSIZ 32*sizeof(struct ifreq) /*1024*/ int s; struct ifreq ifr; if (ifname[0] == '\0') { return -1; } - if ((s = Socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { + if (anysock >= 0) { + s = anysock; + } else if ((s = Socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { Error1("socket(PF_INET, SOCK_DGRAM, IPPROTO_IP): %s", strerror(errno)); return -1; } strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if (Ioctl(s, SIOCGIFINDEX, &ifr) < 0) { - Close(s); - Info3("ioctl(%d, SIOCGIFINDEX, {%s}): %s", + Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}): %s", s, ifr.ifr_name, strerror(errno)); + Close(s); return -1; } Close(s); #if HAVE_STRUCT_IFREQ_IFR_INDEX + Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}) -> { %d }", + s, ifname, ifr.ifr_index); return ifr.ifr_index; #elif HAVE_STRUCT_IFREQ_IFR_IFINDEX + Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}) -> { %d }", + s, ifname, ifr.ifr_ifindex); return ifr.ifr_ifindex; #endif /* HAVE_STRUCT_IFREQ_IFR_IFINDEX */ @@ -468,12 +557,15 @@ int ifindexbyname(const char *ifname) { return -1; #endif /* !defined(HAVE_ STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX) */ } +#endif /* WITH_IP4 || WITH_IP6 || WITH_INTERFACE */ -/* like ifindexbyname(), but allows an index number as input. +#if WITH_IP4 || WITH_IP6 || WITH_INTERFACE +/* like ifindexbyname(), but also allows the index number as input - in this + case it does not lookup the index. writes the resulting index to *ifindex and returns 0, or returns -1 on error */ -int ifindex(const char *ifname, unsigned int *ifindex) { +int ifindex(const char *ifname, unsigned int *ifindex, int anysock) { char *endptr; long int val; @@ -486,10 +578,91 @@ int ifindex(const char *ifname, unsigned int *ifindex) { return 0; } - if ((val = ifindexbyname(ifname)) < 0) { + if ((val = ifindexbyname(ifname, anysock)) < 0) { return -1; } *ifindex = val; return 0; } -#endif /* WITH_IP4 || WITH_IP6 */ +#endif /* WITH_IP4 || WITH_IP6 || WITH_INTERFACE */ + + +/* constructs an environment variable whose name is built from socats uppercase + program name, and underscore and varname; if a variable of this name already + exists a non zero value of overwrite lets the old value be overwritten. + returns 0 on success or <0 if an error occurred. */ +int xiosetenv(const char *varname, const char *value, int overwrite) { +# define XIO_ENVNAMELEN 256 + const char *progname; + char envname[XIO_ENVNAMELEN]; + size_t i, l; + + progname = diag_get_string('p'); + strncpy(envname, progname, XIO_ENVNAMELEN-1); + l = strlen(progname); + strncpy(envname+l, "_", XIO_ENVNAMELEN-1-l); + for (i = 0; i < l; ++i) envname[i] = toupper(envname[i]); + strncpy(envname+l+1, varname, XIO_ENVNAMELEN-1-l); + if (Setenv(envname, value, overwrite) < 0) { + Warn3("setenv(\"%s\", \"%s\", 1): %s", + envname, value, strerror(errno)); +#if HAVE_UNSETENV + Unsetenv(envname); /* dont want to have a wrong value */ +#endif + return -1; + } + return 0; +# undef XIO_ENVNAMELEN +} + +int xiosetenv2(const char *varname, const char *varname2, const char *value, + int overwrite) { +# define XIO_ENVNAMELEN 256 + const char *progname; + char envname[XIO_ENVNAMELEN]; + size_t i, l; + + progname = diag_get_string('p'); + strncpy(envname, progname, XIO_ENVNAMELEN-1); + l = strlen(progname); + strncpy(envname+l, "_", XIO_ENVNAMELEN-1-l); + l += 1; + strncpy(envname+l, varname, XIO_ENVNAMELEN-1-l); + l += strlen(varname); + strncpy(envname+l, "_", XIO_ENVNAMELEN-1-l); + l += 1; + strncpy(envname+l, varname2, XIO_ENVNAMELEN-1-l); + l += strlen(varname2); + for (i = 0; i < l; ++i) envname[i] = toupper(envname[i]); + if (Setenv(envname, value, overwrite) < 0) { + Warn3("setenv(\"%s\", \"%s\", 1): %s", + envname, value, strerror(errno)); +#if HAVE_UNSETENV + Unsetenv(envname); /* dont want to have a wrong value */ +#endif + return -1; + } + return 0; +# undef XIO_ENVNAMELEN +} + + +/* like xiosetenv(), but uses an unsigned long value */ +int xiosetenvulong(const char *varname, unsigned long value, int overwrite) { +# define XIO_LONGLEN 21 /* should suffice for 64bit longs with \0 */ + char envbuff[XIO_LONGLEN]; + + snprintf(envbuff, XIO_LONGLEN, "%lu", value); + return xiosetenv(varname, envbuff, overwrite); +# undef XIO_LONGLEN +} + +/* like xiosetenv(), but uses an unsigned short value */ +int xiosetenvushort(const char *varname, unsigned short value, int overwrite) { +# define XIO_SHORTLEN 11 /* should suffice for 32bit shorts with \0 */ + char envbuff[XIO_SHORTLEN]; + + snprintf(envbuff, XIO_SHORTLEN, "%hu", value); + return xiosetenv(varname, envbuff, overwrite); +# undef XIO_SHORTLEN +} diff --git a/sysutils.h b/sysutils.h index 68a5459..e5e47b2 100644 --- a/sysutils.h +++ b/sysutils.h @@ -1,5 +1,5 @@ /* source: sysutils.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __sysutils_h_included @@ -15,6 +15,7 @@ union xioin6_u { } ; #endif /* WITH_IP6 */ +#if _WITH_SOCKET union sockaddr_union { struct sockaddr soa; #if _WITH_UNIX @@ -27,29 +28,12 @@ union sockaddr_union { struct sockaddr_in6 ip6; #endif /* _WITH_IP6 */ } ; - -#if _WITH_IP4 -struct xiorange_ip4 { - struct in_addr netaddr; /* network byte order */ - struct in_addr netmask; /* network byte order */ -} ; -#endif /* _WITH_IP4 */ - -#if _WITH_IP6 -struct xiorange_ip6 { - struct in6_addr addr; - struct in6_addr mask; -} ; -#endif /* _WITH_IP4 */ +#endif /* _WITH_SOCKET */ #if _WITH_SOCKET -union xiorange_union { -#if _WITH_IP4 - struct xiorange_ip4 ip4; -#endif /* _WITH_IP4 */ -#if _WITH_IP6 - struct xiorange_ip6 ip6; -#endif /* _WITH_IP6 */ +struct xiorange { + union sockaddr_union netaddr; + union sockaddr_union netmask; } ; #endif /* _WITH_SOCKET */ @@ -90,9 +74,20 @@ extern int getusergroups(const char *user, gid_t *list, size_t *ngroups); extern const char *hstrerror(int err); #endif +extern int xiopoll(struct pollfd fds[], unsigned long nfds, struct timeval *timeout); + extern int parseport(const char *portname, int proto); -extern int ifindexbyname(const char *ifname); -extern int ifindex(const char *ifname, unsigned int *ifindex); +extern int ifindexbyname(const char *ifname, int anysock); +extern int ifindex(const char *ifname, unsigned int *ifindex, int anysock); + +extern int xiosetenv(const char *varname, const char *value, int overwrite); +extern int +xiosetenv2(const char *varname, const char *varname2, const char *value, + int overwrite); +extern int xiosetenvulong(const char *varname, unsigned long value, + int overwrite); +extern int xiosetenvushort(const char *varname, unsigned short value, + int overwrite); #endif /* !defined(__sysutils_h_included) */ diff --git a/test.sh b/test.sh index 93c485c..9795efa 100755 --- a/test.sh +++ b/test.sh @@ -11,6 +11,37 @@ #set -vx +val_t=0.1 +NUMCOND=true +#NUMCOND="test \$N -gt 70" +while [ "$1" ]; do + case "X$1" in + X-t?*) val_t="${1#-t}" ;; + X-t) shift; val_t="$1" ;; + X-n?*) NUMCOND="test \$N -eq ${1#-t}" ;; + X-n) shift; NUMCOND="test \$N -eq $1" ;; + X-N?*) NUMCOND="test \$N -gt ${1#-t}" ;; + X-N) shift; NUMCOND="test \$N -ge $1" ;; + *) break; + esac + shift +done + +opt_t="-t $val_t" + + +#MICROS=100000 +case "X$val_t" in + X*.???????*) S="${val_t%.*}"; uS="${val_t#*.}"; uS="${uS:0:6}" ;; + X*.*) S="${val_t%.*}"; uS="${val_t#*.}"; uS="${uS}000000"; uS="${uS:0:6}" ;; + X*) S="${val_t}"; uS="000000" ;; +esac +MICROS=${S}${uS} +MICROS=${MICROS##0000}; MICROS=${MICROS##00}; MICROS=${MICROS##0} +# +_MICROS=$((MICROS+999999)); SECONDs="${_MICROS%??????}" +[ -z "$SECONDs" ] && SECONDs=0 + withroot=0 # perform privileged tests even if not run by root #PATH=$PATH:/opt/freeware/bin #PATH=$PATH:/usr/local/ssl/bin @@ -20,29 +51,41 @@ MISCDELAY=1 [ -z "$SOCAT" ] && SOCAT="./socat" [ -z "$PROCAN" ] && PROCAN="./procan" [ -z "$FILAN" ] && FILAN="./filan" -opts="-t0.1 $OPTS" +opts="$opt_t $OPTS" export SOCAT_OPTS="$opts" #debug="1" debug= -TESTS="$@" -INTERFACE=eth1; # not used for function tests +TESTS="$@"; export TESTS +INTERFACE=eth0; # not used for function tests MCINTERFACE=lo # !!! Linux only #LOCALHOST=192.168.58.1 #LOCALHOST=localhost LOCALHOST=127.0.0.1 LOCALHOST6=[::1] -PROTO=$((192+RANDOM/1024)) +#PROTO=$(awk '{print($2);}' /etc/protocols |sort -n |tail -n 1) +#PROTO=$(($PROTO+1)) +PROTO=$((144+RANDOM/2048)) PORT=12002 SOURCEPORT=2002 CAT=cat OD_C="od -c" +# precision sleep; takes seconds with fractional part +psleep () { + local T="$1" + #[ "$T" = 0 ] && T=0.000002 + [ "$T" = 0 ] && return + $SOCAT -T "$T" pipe pipe +} # time in microseconds to wait in some situations -MICROS=100000 if ! type usleep >/dev/null 2>&1; then usleep () { local n="$1" - # older bashes do not accept $1 here: - sleep $(((n+999999)/1000000)) + case "$n" in + *???????) S="${n%??????}"; uS="${n:${#n}-6}" ;; + *) S=0; uS="00000$n"; uS="${uS:${#uS}-6}" ;; + esac + [ "$S.$uS" = "0.000000" ] && return + $SOCAT -T $S.$uS pipe pipe } fi @@ -93,18 +136,19 @@ NetBSD)IFCONFIG=/sbin/ifconfig ;; OpenBSD)IFCONFIG=/sbin/ifconfig ;; OSF1) IFCONFIG=/sbin/ifconfig ;; SunOS) IFCONFIG=/sbin/ifconfig ;; +Darwin)IFCONFIG=/sbin/ifconfig ;; #*) IFCONFIG=/sbin/ifconfig ;; esac # for some tests we need a second local IPv4 address case "$UNAME" in Linux) - BROADCASTIF=eth1 + BROADCASTIF=eth0 SECONDADDR=127.0.0.2 BCADDR=127.255.255.255 BCIFADDR=$($IFCONFIG $BROADCASTIF |grep 'inet ' |awk '{print($2);}' |cut -d: -f2) ;; FreeBSD|NetBSD|OpenBSD) - MAINIF=$($IFCONFIG -a |grep '^[a-z]' |head -1 |cut -d: -f1) + MAINIF=$($IFCONFIG -a |grep '^[a-z]' |grep -v '^lo0: ' |head -1 |cut -d: -f1) BROADCASTIF="$MAINIF" SECONDADDR=$($IFCONFIG $BROADCASTIF |grep 'inet ' |awk '{print($2);}') BCIFADDR="$SECONDADDR" @@ -115,16 +159,25 @@ HP-UX) SECONDADDR=$($IFCONFIG $MAINIF |tail -n 1 |awk '{print($2);}') BCADDR=$($IFCONFIG $BROADCASTIF |grep 'broadcast ' |sed 's/.*broadcast/broadcast/' |awk '{print($2);}') ;; SunOS) + MAINIF=$($IFCONFIG -a |grep '^[a-z]' |grep -v '^lo0: ' |head -1 |cut -d: -f1) + BROADCASTIF="$MAINIF" #BROADCASTIF=hme0 - BROADCASTIF=eri0 - SECONDADDR=$($IFCONFIG $BROADCASTIF |grep 'inet ' |awk '{print($2);}') - BCIFADDR="$SECONDADDR" - BCADDR=$($IFCONFIG $BROADCASTIF |grep 'broadcast ' |sed 's/.*broadcast/broadcast/' |awk '{print($2);}') ;; + #BROADCASTIF=eri0 + #SECONDADDR=$($IFCONFIG $BROADCASTIF |grep 'inet ' |awk '{print($2);}') + SECONDADDR=$(expr "$($IFCONFIG -a |grep 'inet ' |fgrep -v ' 127.0.0.1 '| head -n 1)" : '.*inet \([0-9.]*\) .*') + #BCIFADDR="$SECONDADDR" + #BCADDR=$($IFCONFIG $BROADCASTIF |grep 'broadcast ' |sed 's/.*broadcast/broadcast/' |awk '{print($2);}') + ;; #AIX|FreeBSD|Solaris) *) - SECONDADDR=$(expr "$($IFCONFIG -a |grep 'inet ' |fgrep -v ' 127.0.0.1 '| head -n 1)" : '.*inet \([0-9.]*\) .*') + SECONDADDR=$(expr "$($IFCONFIG -a |grep 'inet ' |fgrep -v ' 127.0.0.1 ' |head -n 1)" : '.*inet \([0-9.]*\) .*') ;; esac +# for generic sockets we need this address in hex form +if [ "$SECONDADDR" ]; then + SECONDADDRHEX="$(printf "%02x%02x%02x%02x\n" $(echo "$SECONDADDR" |tr '.' ' +'))" +fi # for some tests we need a second local IPv6 address case "$UNAME" in @@ -133,9 +186,12 @@ case "$UNAME" in ;; esac if [ -z "$SECONDIP6ADDR" ]; then - case "$TESTS" in - *%root2%*) $IFCONFIG eth1 ::2/128 - esac +# case "$TESTS" in +# *%root2%*) $IFCONFIG eth0 ::2/128 +# esac + SECONDIP6ADDR="$LOCALHOST6" +else + SECONDIP6ADDR="[$SECONDIP6ADDR]" fi TRUE=$(which true) @@ -150,27 +206,27 @@ ECHO="echo $E" PRINTF="printf" case "$TERM" in -vt100|vt320|linux|xterm|cons25|dtterm|aixterm|sun-color) +vt100|vt320|linux|xterm|cons25|dtterm|aixterm|sun-color|xterm-color) # there are different behaviours of printf (and echo) # on some systems, echo behaves different than printf... if [ $($PRINTF "\0101") = "A" ]; then RED="\0033[31m" GREEN="\0033[32m" YELLOW="\0033[33m" - if [ "$UNAME" = SunOS ]; then - NORMAL="\0033[30m" - else +# if [ "$UNAME" = SunOS ]; then +# NORMAL="\0033[30m" +# else NORMAL="\0033[39m" - fi +# fi else RED="\033[31m" GREEN="\033[32m" YELLOW="\033[33m" - if [ "$UNAME" = SunOS ]; then - NORMAL="\033[30m" - else +# if [ "$UNAME" = SunOS ]; then +# NORMAL="\033[30m" +# else NORMAL="\033[39m" - fi +# fi fi OK="${GREEN}OK${NORMAL}" FAILED="${RED}FAILED${NORMAL}" @@ -217,6 +273,7 @@ $SOCAT -? |sed '1,/address-head:/ d' |egrep 'groups=' |while IFS="$IFS:" read x if [ -s "$TF-diff" ]; then $ECHO "\n*** address array is not sorted. Wrong entries:" >&2 cat "$TD/socat-q-diff" >&2 + exit 1 else echo " ok" fi @@ -229,11 +286,12 @@ case "$TESTS" in # test if address options array ("optionnames") is sorted alphabetically: $ECHO "testing if address options are sorted...\c" TF="$TD/socat-qq" -$SOCAT -??? |sed '1,/opt:/ d' |egrep 'groups=' |awk '{print($1);}' >"$TF" -$SOCAT -??? |sed '1,/opt:/ d' |egrep 'groups=' |awk '{print($1);}' |LC_ALL=C sort |diff "$TF" - >"$TF-diff" +$SOCAT -??? |sed '1,/opt:/ d' |awk '{print($1);}' >"$TF" +LC_ALL=C sort "$TF" |diff "$TF" - >"$TF-diff" if [ -s "$TF-diff" ]; then $ECHO "\n*** option array is not sorted. Wrong entries:" >&2 cat "$TD/socat-qq-diff" >&2 + exit 1 else echo " ok" fi @@ -467,7 +525,7 @@ N=1 #TEST="$METHOD on file accepts all its options" # echo "### $TEST" #TF=$TD/file$N -#DA="$(date)" +#DA="test$N $(date) $RANDOM" #OPTGROUPS=$($SOCAT -? |fgrep " $method:" |sed 's/.*=//') #for g in $(echo $OPTGROUPS |tr ',' ' '); do # eval "OPTG=\$OPTS_$(echo $g |tr a-z- A-Z_)"; @@ -1430,7 +1488,8 @@ numCANT=0 # test if selected socat features work ("FUNCTIONS") testecho () { - local num="$1" +#set -vx + local N="$1" local title="$2" local arg1="$3"; [ -z "$arg1" ] && arg1="-" local arg2="$4"; [ -z "$arg2" ] && arg2="echo" @@ -1439,12 +1498,13 @@ testecho () { local tf="$td/test$N.stdout" local te="$td/test$N.stderr" local tdiff="$td/test$N.diff" - local da="$(date)" + local da="test$N $(date) $RANDOM" + if ! eval $NUMCOND; then :; else #local cmd="$SOCAT $opts $arg1 $arg2" - #$ECHO "testing $title (test $num)... \c" - $PRINTF "test $F_n %s... " $num "$title" + #$ECHO "testing $title (test $N)... \c" + $PRINTF "test $F_n %s... " $N "$title" #echo "$da" |$cmd >"$tf" 2>"$te" - (echo "$da"; rsleep $T) |($SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te"; echo $? >"$td/test$N.rc") & + (psleep $T; echo "$da"; psleep $T) |($SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te"; echo $? >"$td/test$N.rc") & export rc1=$! #sleep 5 && kill $rc1 2>/dev/null & # rc2=$! @@ -1467,12 +1527,14 @@ testecho () { cat "$tdiff" numFAIL=$((numFAIL+1)) fi + fi # NUMCOND +set +vx } # special function for use with the test address of socat V2 chains testchain () { - local num="$1" + local N="$1" local title="$2" local arg1="$3"; [ -z "$arg1" ] && arg1="-" local arg2="$4"; [ -z "$arg2" ] && arg2="echo" @@ -1483,7 +1545,8 @@ testchain () { local te="$td/test$N.stderr" local tdiff="$td/test$N.diff" local da="$(date)" - $PRINTF "test $F_n %s... " $num "$title" + if ! eval $NUMCOND; then :; else + $PRINTF "test $F_n %s... " $N "$title" (echo "$da"; rsleep $T) |$SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te" & export rc1=$! wait $rc1 @@ -1504,6 +1567,7 @@ testchain () { cat "$tdiff" numFAIL=$((numFAIL+1)) fi + fi # NUMCOND } @@ -1518,17 +1582,21 @@ testod () { local T="$6"; [ -z "$T" ] && T=0; export T local tf="$td/test$N.stdout" local te="$td/test$N.stderr" + local tr="$td/test$N.ref" local tdiff="$td/test$N.diff" - local dain="$(date)" - local daout="$(echo "$dain" |$OD_C)" + local dain="$(date) $RANDOM" + if ! eval $NUMCOND; then :; else + echo "$dain" |$OD_C >"$tr" +# local daout="$(echo "$dain" |$OD_C)" $PRINTF "test $F_n %s... " $num "$title" - (echo "$dain"; rsleep $T) |$SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te" + (psleep $T; echo "$dain"; psleep $T) |$SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te" if [ "$?" != 0 ]; then $PRINTF "$FAILED: $SOCAT:\n" echo "$SOCAT $opts $arg1 $arg2" cat "$te" numFAIL=$((numFAIL+1)) - elif echo "$daout" |diff - "$tf" >"$tdiff" 2>&1; then +# elif echo "$daout" |diff - "$tf" >"$tdiff" 2>&1; then + elif diff "$tr" "$tf" >"$tdiff" 2>&1; then $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) @@ -1539,6 +1607,7 @@ testod () { cat "$tdiff" numFAIL=$((numFAIL+1)) fi + fi # NUMCOND } # test if the socat executable has these address types compiled in @@ -1583,6 +1652,9 @@ ifprocess () { FreeBSD) l="$(ps -faje |grep "^........ $(printf %5u $1)")" ;; HP-UX) l="$(ps -fade |grep "^........ $(printf %5u $1)")" ;; Linux) l="$(ps -fade |grep "^........ $(printf %5u $1)")" ;; +# NetBSD) l="$(ps -aj |grep "^........ $(printf %4u $1)")" ;; + NetBSD) l="$(ps -aj |grep "^[^ ][^ ]*[ ][ ]*$(printf %5u $1) ")" ;; + OpenBSD) l="$(ps -kaj |grep "^........ $(printf %5u $1)")" ;; SunOS) l="$(ps -fade |grep "^........ $(printf %5u $1)")" ;; *) l="$(ps -fade |grep "^[^ ][^ ]*[ ][ ]*$(printf %5u $1) ")" ;; esac @@ -1603,6 +1675,9 @@ childprocess () { FreeBSD) l="$(ps -faje |grep "^........ ..... $(printf %5u $1)")" ;; HP-UX) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;; Linux) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;; +# NetBSD) l="$(ps -aj |grep "^........ ..... $(printf %4u $1)")" ;; + NetBSD) l="$(ps -aj |grep "^[^ ][^ ]*[ ][ ]*..... $(printf %5u $1)")" ;; + OpenBSD) l="$(ps -aj |grep "^........ ..... $(printf %5u $1)")" ;; SunOS) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;; *) l="$(ps -fade |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]**[ ][ ]*$(printf %5u $1) ")" ;; esac if [ -z "$l" ]; then @@ -1642,6 +1717,7 @@ runsip4 () { OpenBSD)l=$($IFCONFIG -a |fgrep 'inet 127.0.0.1 ');; OSF1) l=$($IFCONFIG -a |grep ' inet ') ;; SunOS) l=$($IFCONFIG -a |grep 'inet ') ;; + Darwin)l=$($IFCONFIG lo0 |fgrep 'inet 127.0.0.1 ') ;; # *) l=$($IFCONFIG -a |grep ' ::1[^:0-9A-Fa-f]') ;; esac [ -z "$l" ] && return 1 @@ -1667,12 +1743,13 @@ runsip6 () { NetBSD)l=$(/sbin/ifconfig -a |grep 'inet6 ::1 ');; OSF1) l=$(/sbin/ifconfig -a |grep ' inet6 ') ;; SunOS) l=$(/sbin/ifconfig -a |grep 'inet6 ') ;; + Darwin)l=$(/sbin/ifconfig lo0 |grep 'inet6 ::1 ') ;; *) l=$(/sbin/ifconfig -a |grep ' ::1[^:0-9A-Fa-f]') ;; esac [ -z "$l" ] && return 1 # existence of interface might not suffice, check for routeability: case "$UNAME" in - Darwin) ping -c 1 ::1; l="$?" ;; + Darwin) ping6 -c 1 ::1; l="$?" ;; Linux) ping6 -c 1 ::1; l="$?" ;; *) if [ -n "$l" ]; then l=0; else l=1; fi ;; esac @@ -1680,6 +1757,26 @@ runsip6 () { return $l; } +# check if SCTP on IPv4 is available on host +runssctp4 () { + PORT="$1" + $SOCAT /dev/null SCTP4-LISTEN:$PORT 2>"$td/sctp4.stderr" & + pid=$! + sleep 1 + kill "$pid" 2>/dev/null + test ! -s "$td/sctp4.stderr" +} + +# check if SCTP on IPv6 is available on host +runssctp6 () { + PORT="$1" + $SOCAT /dev/null SCTP6-LISTEN:$PORT 2>"$td/sctp6.stderr" & + pid=$! + sleep 1 + kill "$pid" 2>/dev/null + test ! -s "$td/sctp6.stderr" +} + # wait until an IP4 protocol is ready waitip4proto () { local proto="$1" @@ -1691,7 +1788,7 @@ waitip4proto () { while [ $timeout -gt 0 ]; do case "$UNAME" in Linux) l=$(netstat -n -w -l |grep '^raw .* .*[0-9*]:'$proto' [ ]*0\.0\.0\.0:\*') ;; -# FreeBSD) l=$(netstat -an |grep '^raw4[6 ] .*[0-9*]\.'$proto' .* \*\.\*') ;; +# FreeBSD) l=$(netstat -an |egrep '^raw46? .*[0-9*]\.'$proto' .* \*\.\*') ;; # NetBSD) l=$(netstat -an |grep '^raw .*[0-9*]\.'$proto' [ ]* \*\.\*') ;; # OpenBSD) l=$(netstat -an |grep '^raw .*[0-9*]\.'$proto' [ ]* \*\.\*') ;; # Darwin) case "$(uname -r)" in @@ -1731,8 +1828,8 @@ waitip6proto () { [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do case "$UNAME" in - Linux) l=$(netstat -n -w -l |grep '^raw .* .*:[0-9*]*:'$proto' [ ]*:::\*') ;; -# FreeBSD) l=$(netstat -an |grep '^raw4[6 ] .*[0-9*]\.'$proto' .* \*\.\*') ;; + Linux) l=$(netstat -n -w -l |grep '^raw[6 ] .* .*:[0-9*]*:'$proto' [ ]*:::\*') ;; +# FreeBSD) l=$(netstat -an |egrep '^raw46? .*[0-9*]\.'$proto' .* \*\.\*') ;; # NetBSD) l=$(netstat -an |grep '^raw .*[0-9*]\.'$proto' [ ]* \*\.\*') ;; # OpenBSD) l=$(netstat -an |grep '^raw .*[0-9*]\.'$proto' [ ]* \*\.\*') ;; # Darwin) case "$(uname -r)" in @@ -1744,7 +1841,7 @@ waitip6proto () { # SunOS) l=$(netstat -an -f inet -P raw |grep '.*[1-9*]\.'$proto' [ ]*Idle') ;; # HP-UX) l=$(netstat -an |grep '^raw 0 0 .*[0-9*]\.'$proto' .* \*\.\* ') ;; # OSF1) l=$(/usr/sbin/netstat -an |grep '^raw 0 0 .*[0-9*]\.'$proto' [ ]*\*\.\*') ;; - *) #l=$(netstat -an |grep -i 'raw .*[0-9*][:.]'$proto' ') ;; + *) #l=$(netstat -an |egrep -i 'raw6? .*[0-9*][:.]'$proto' ') ;; sleep 1; return 0 ;; esac [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \ @@ -1762,6 +1859,30 @@ waitip6port () { waitip6proto "$1" "$2" "$3" } +# check if a TCP4 port is in use +# exits with 0 when it is not used +checktcp4port () { + local port="$1" + local l + case "$UNAME" in + Linux) l=$(netstat -n -t |grep '^tcp .* .*[0-9*]:'$port' .* LISTEN') ;; + FreeBSD) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; + NetBSD) l=$(netstat -an |grep '^tcp .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]* LISTEN.*') ;; + Darwin) case "$(uname -r)" in + [1-5]*) l=$(netstat -an |grep '^tcp.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; + *) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; + esac ;; + AIX) l=$(netstat -an |grep '^tcp[^6] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;; + SunOS) l=$(netstat -an -f inet -P tcp |grep '.*[1-9*]\.'$port' .*\* 0 .* LISTEN') ;; + HP-UX) l=$(netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' .* LISTEN$') ;; + OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') ;; + CYGWIN*) l=$(netstat -an -p TCP |grep '^ TCP [0-9.]*:'$port' .* LISTENING') ;; + *) l=$(netstat -an |grep -i 'tcp .*[0-9*][:.]'$port' .* listen') ;; + esac + [ -z "$l" ] && return 0 + return 1 +} + # wait until a TCP4 listen port is ready waittcp4port () { local port="$1" @@ -1779,7 +1900,7 @@ waittcp4port () { [1-5]*) l=$(netstat -an |grep '^tcp.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; *) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; esac ;; - AIX) l=$(netstat -an |grep '^tcp[^6] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;; + AIX) l=$(netstat -an |grep '^tcp[^6] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;; SunOS) l=$(netstat -an -f inet -P tcp |grep '.*[1-9*]\.'$port' .*\* 0 .* LISTEN') ;; HP-UX) l=$(netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' .* LISTEN$') ;; OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') ;; @@ -1807,7 +1928,7 @@ waitudp4port () { while [ $timeout -gt 0 ]; do case "$UNAME" in Linux) l=$(netstat -n -u -l |grep '^udp .* .*[0-9*]:'$port' [ ]*0\.0\.0\.0:\*') ;; - FreeBSD) l=$(netstat -an |grep '^udp4[6 ] .*[0-9*]\.'$port' .* \*\.\*') ;; + FreeBSD) l=$(netstat -an |egrep '^udp46? .*[0-9*]\.'$port' .* \*\.\*') ;; NetBSD) l=$(netstat -an |grep '^udp .*[0-9*]\.'$port' [ ]* \*\.\*') ;; OpenBSD) l=$(netstat -an |grep '^udp .*[0-9*]\.'$port' [ ]* \*\.\*') ;; Darwin) case "$(uname -r)" in @@ -1830,6 +1951,40 @@ waitudp4port () { return 1 } +# wait until an SCTP4 listen port is ready +waitsctp4port () { + local port="$1" + local logic="$2" # 0..wait until free; 1..wait until listening + local timeout="$3" + local l + [ "$logic" ] || logic=1 + [ "$timeout" ] || timeout=5 + while [ $timeout -gt 0 ]; do + case "$UNAME" in + Linux) l=$(netstat -n -a |grep '^sctp .* .*[0-9*]:'$port' .* LISTEN') ;; +# FreeBSD) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; +# NetBSD) l=$(netstat -an |grep '^tcp .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]* LISTEN.*') ;; +# Darwin) case "$(uname -r)" in +# [1-5]*) l=$(netstat -an |grep '^tcp.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; +# *) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; +# esac ;; +# AIX) l=$(netstat -an |grep '^tcp[^6] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;; + SunOS) l=$(netstat -an -f inet -P sctp |grep '.*[1-9*]\.'$port' .*\* 0 .* LISTEN') ;; +# HP-UX) l=$(netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' .* LISTEN$') ;; +# OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') ;; +# CYGWIN*) l=$(netstat -an -p TCP |grep '^ TCP [0-9.]*:'$port' .* LISTENING') ;; + *) l=$(netstat -an |grep -i 'sctp .*[0-9*][:.]'$port' .* listen') ;; + esac + [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \ + \( \( $logic -eq 0 \) -a -z "$l" \) ] && return 0 + sleep 1 + timeout=$((timeout-1)) + done + + $ECHO "!port $port timed out! \c" >&2 + return 1 +} + # wait until a tcp6 listen port is ready waittcp6port () { local port="$1" @@ -1840,10 +1995,11 @@ waittcp6port () { [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do case "$UNAME" in - Linux) l=$(netstat -an |grep '^tcp[6 ] .* [0-9a-f:]*:'$port' .* LISTEN') ;; - FreeBSD) l=$(netstat -an |grep -i 'tcp[46][6 ] .*[0-9*][:.]'$port' .* listen') ;; + Linux) l=$(netstat -an |grep -E '^tcp6? .* [0-9a-f:]*:'$port' .* LISTEN') ;; + FreeBSD) l=$(netstat -an |egrep -i 'tcp(6|46) .*[0-9*][:.]'$port' .* listen') ;; NetBSD) l=$(netstat -an |grep '^tcp6 .*[0-9*]\.'$port' [ ]* \*\.\*') ;; OpenBSD) l=$(netstat -an |grep -i 'tcp6 .*[0-9*][:.]'$port' .* listen') ;; + Darwin) l=$(netstat -an |egrep '^tcp4?6 +[0-9]+ +[0-9]+ +[0-9a-z:%*]+\.'$port' +[0-9a-z:%*.]+ +LISTEN') ;; AIX) l=$(netstat -an |grep '^tcp[6 ] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;; SunOS) l=$(netstat -an -f inet6 -P tcp |grep '.*[1-9*]\.'$port' .*\* [ ]* 0 .* LISTEN') ;; #OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp6 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') /*?*/;; @@ -1869,11 +2025,11 @@ waitudp6port () { [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do case "$UNAME" in - Linux) l=$(netstat -an |grep '^udp[6 ] .* .*[0-9*:]:'$port' [ ]*:::\*') ;; + Linux) l=$(netstat -an |grep -E '^udp6? .* .*[0-9*:]:'$port' [ ]*:::\*') ;; FreeBSD) l=$(netstat -an |egrep '^udp(6|46) .*[0-9*]\.'$port' .* \*\.\*') ;; NetBSD) l=$(netstat -an |grep '^udp6 .* \*\.'$port' [ ]* \*\.\*') ;; - OpenBSD) l=$(netstat -an |grep '^udp6 .*[0-9*]\.'$port' [ ]* \*\.\*') ;; - #Darwin) l=$(netstat -an |grep '^udp6.* .*[0-9*]\.'$port' .* \*\.\* ') ;; + OpenBSD) l=$(netstat -an |grep '^udp6 .*[0-9*]\.'$port' [ ]* \*\.\*') ;; + Darwin) l=$(netstat -an |egrep '^udp4?6 +[0-9]+ +[0-9]+ +[0-9a-z:%*]+\.'$port' +[0-9a-z:%*.]+') ;; AIX) l=$(netstat -an |grep '^udp[6 ] 0 0 .*[*0-9]\.'$port' .* \*\.\*[ ]*$') ;; SunOS) l=$(netstat -an -f inet6 -P udp |grep '.*[1-9*]\.'$port' [ ]*Idle') ;; #HP-UX) l=$(netstat -an |grep '^udp 0 0 .*[0-9*]\.'$port' ') ;; @@ -1890,14 +2046,51 @@ waitudp6port () { return 1 } +# wait until a sctp6 listen port is ready +# not all (Linux) variants show this in netstat +waitsctp6port () { + local port="$1" + local logic="$2" # 0..wait until free; 1..wait until listening + local timeout="$3" + local l + [ "$logic" ] || logic=1 + [ "$timeout" ] || timeout=5 + while [ $timeout -gt 0 ]; do + case "$UNAME" in + Linux) l=$(netstat -an |grep '^sctp[6 ] .* [0-9a-f:]*:'$port' .* LISTEN') ;; +# FreeBSD) l=$(netstat -an |grep -i 'tcp[46][6 ] .*[0-9*][:.]'$port' .* listen') ;; +# NetBSD) l=$(netstat -an |grep '^tcp6 .*[0-9*]\.'$port' [ ]* \*\.\*') ;; +# OpenBSD) l=$(netstat -an |grep -i 'tcp6 .*[0-9*][:.]'$port' .* listen') ;; +# AIX) l=$(netstat -an |grep '^tcp[6 ] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;; + SunOS) l=$(netstat -an -f inet6 -P sctp |grep '.*[1-9*]\.'$port' .*\* [ ]* 0 .* LISTEN') ;; +# #OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp6 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') /*?*/;; + *) l=$(netstat -an |grep -i 'stcp6 .*:'$port' .* listen') ;; + esac + [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \ + \( \( $logic -eq 0 \) -a -z "$l" \) ] && return 0 + sleep 1 + timeout=$((timeout-1)) + done + + $ECHO "!port $port timed out! \c" >&2 + return 1 +} + +# we need this misleading function name for canonical reasons +waitunixport () { + waitfile "$1" "$2" "$3" +} + # wait until a filesystem entry exists waitfile () { local crit=-e case "X$1" in X-*) crit="$1"; shift ;; esac local file="$1" - local logic="$2" # 0..wait until gone; 1..wait until exists (default) + local logic="$2" # 0..wait until gone; 1..wait until exists (default); + # 2..wait until not empty local timeout="$3" [ "$logic" ] || logic=1 + [ "$logic" -eq 2 ] && crit=-s [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do if [ \( \( $logic -ne 0 \) -a $crit "$file" \) -o \ @@ -2035,7 +2228,7 @@ NAME=SYSTEMSOCKET case "$TESTS" in *%functions%*|*%system%*|*%$NAME%*) TEST="$NAME: simple echo via system() of cat with socketpair" -testecho "$N" "$TEST" "" "system:$CAT" "$opts" +testecho "$N" "$TEST" "" "system:$CAT" "$opts" "$val_t" esac N=$((N+1)) @@ -2062,7 +2255,8 @@ NAME=EXECPTY case "$TESTS" in *%functions%*|*%exec%*|*%pty%*|*%$NAME%*) TEST="$NAME: simple echo via exec of cat with pseudo terminal" -if ! testaddrs pty >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -2076,7 +2270,8 @@ NAME=SYSTEMPTY case "$TESTS" in *%functions%*|*%system%*|*%pty%*|*%$NAME%*) TEST="$NAME: simple echo via system() of cat with pseudo terminal" -if ! testaddrs pty >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -2099,13 +2294,13 @@ NAME=DUALSYSTEMFDS case "$TESTS" in *%functions%*|*%system%*|*%$NAME%*) TEST="$NAME: echo via dual system() of cat" -#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" +#testecho "$N" "$TEST" "system:$CAT<&7,fdin=7%system:'strace -tt -o /tmp/cat.out cat'>&6,fdout=6" "" "$opts" "$T" +testecho "$N" "$TEST" "system:$CAT<&7,fdin=7%system:'cat'>&6,fdout=6" "" "$opts" "0.1" "$val_t" esac N=$((N+1)) -# test: send EOF to exec'ed sub process, let it finished its operation, and +# test: send EOF to exec'ed sub process, let it finish its operation, and # check if the sub process returns its data before terminating. NAME=EXECSOCKETFLUSH # idea: have socat exec'ing od; send data and EOF, and check if the od'ed data @@ -2122,7 +2317,7 @@ NAME=SYSTEMSOCKETFLUSH case "$TESTS" in *%functions%*|*%system%*|*%$NAME%*) TEST="$NAME: call to od via system() with socketpair" -testod "$N" "$TEST" "" "system:$OD_C" "$opts" "0.1" +testod "$N" "$TEST" "" "system:$OD_C" "$opts" $val_t esac N=$((N+1)) @@ -2206,7 +2401,8 @@ NAME=RAWIP4SELF case "$TESTS" in *%functions%*|*%ip4%*|*%rawip%*|*%root%*|*%$NAME%*) TEST="$NAME: simple echo via self receiving raw IPv4 protocol" -if ! feat=$(testaddrs ip4) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testaddrs rawip) >/dev/null; then @@ -2225,7 +2421,8 @@ NAME=RAWIPX4SELF case "$TESTS" in *%functions%*|*%ip4%*|*%rawip%*|*%root%*|*%$NAME%*) TEST="$NAME: simple echo via self receiving raw IP protocol, v4 by target" -if ! feat=$(testaddrs ip4) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testaddrs rawip) >/dev/null; then @@ -2236,7 +2433,7 @@ elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then numCANT=$((numCANT+1)) else testecho "$N" "$TEST" "" "ip:127.0.0.1:$IPPROTO" "$opts" -fi +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -2244,7 +2441,8 @@ NAME=RAWIP6SELF case "$TESTS" in *%functions%*|*%ip6%*|*%rawip%*|*%root%*|*%$NAME%*) TEST="$NAME: simple echo via self receiving raw IPv6 protocol" -if ! feat=$(testaddrs ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testaddrs rawip) || ! runsip6 >/dev/null; then @@ -2255,7 +2453,7 @@ elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then numCANT=$((numCANT+1)) else testecho "$N" "$TEST" "" "ip6:[::1]:$IPPROTO" "$opts" -fi +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -2263,7 +2461,8 @@ NAME=RAWIPX6SELF case "$TESTS" in *%functions%*|*%ip%*|*%ip6%*|*%rawip%*|*%rawip6%*|*%root%*|*%$NAME%*) TEST="$NAME: simple echo via self receiving raw IP protocol, v6 by target" -if ! feat=$(testaddrs ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testaddrs rawip) || ! runsip6 >/dev/null; then @@ -2283,7 +2482,8 @@ NAME=TCPSELF case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: echo via self connection of TCP IPv4 socket" -if [ "$UNAME" != Linux ]; then +if ! eval $NUMCOND; then :; +elif [ "$UNAME" != Linux ]; then #printf "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N $PRINTF "test $F_n $TEST... ${YELLOW}only on Linux$NORMAL\n" $N numCANT=$((numCANT+1)) @@ -2297,6 +2497,7 @@ N=$((N+1)) NAME=UDPSELF +if ! eval $NUMCOND; then :; else case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: echo via self connection of UDP IPv4 socket" @@ -2307,6 +2508,7 @@ else testecho "$N" "$TEST" "" "udp:127.100.0.1:$PORT,sp=$PORT,bind=127.100.0.1" "$opts" fi esac + fi # NUMCOND PORT=$((PORT+1)) N=$((N+1)) @@ -2315,7 +2517,8 @@ NAME=UDP6SELF case "$TESTS" in *%functions%*|*%udp%*|*%udp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: echo via self connection of UDP IPv6 socket" -if [ "$UNAME" != Linux ]; then +if ! eval $NUMCOND; then :; +elif [ "$UNAME" != Linux ]; then $PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs udp ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -2331,6 +2534,7 @@ N=$((N+1)) NAME=DUALUDPSELF +if ! eval $NUMCOND; then :; else case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: echo via two unidirectional UDP IPv4 sockets" @@ -2339,6 +2543,7 @@ p1=$PORT p2=$((PORT+1)) testecho "$N" "$TEST" "" "udp:127.0.0.1:$p1,sp=$p2%udp:127.0.0.1:$p2,sp=$p1" "$opts" esac +fi # NUMCOND PORT=$((PORT+2)) N=$((N+1)) @@ -2348,17 +2553,18 @@ N=$((N+1)) #} -NAME=UNIXSOCKET +NAME=UNIXSTREAM +if ! eval $NUMCOND; then :; else case "$TESTS" in -*%functions%*|*%$NAME%*) +*%functions%*|*%unix%*|*%$NAME%*) TEST="$NAME: echo via connection to UNIX domain socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" ts="$td/test$N.socket" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts UNIX-LISTEN:$ts PIPE" -CMD2="$SOCAT $opts -%- UNIX:$ts" +CMD2="$SOCAT $opts -%- UNIX-CONNECT:$ts" printf "test $F_n $TEST... " $N $CMD1 $tf 2>"${te}1" & bg=$! # background process id @@ -2381,10 +2587,12 @@ else fi kill $bg 2>/dev/null esac +fi # NUMCOND N=$((N+1)) NAME=TCP4 +if ! eval $NUMCOND; then :; else case "$TESTS" in *%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: echo via connection to TCP V4 socket" @@ -2393,7 +2601,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts TCP4-LISTEN:$tsl,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP4:$ts" printf "test $F_n $TEST... " $N @@ -2421,6 +2629,7 @@ kill $pid1 2>/dev/null wait ;; esac PORT=$((PORT+1)) +fi # NUMCOND N=$((N+1)) @@ -2428,7 +2637,8 @@ NAME=TCP6 case "$TESTS" in *%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: echo via connection to TCP V6 socket" -if ! testaddrs tcp ip6 >/dev/null || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -2437,7 +2647,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="[::1]:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts TCP6-listen:$tsl,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP6:$ts" printf "test $F_n $TEST... " $N @@ -2471,7 +2681,8 @@ NAME=TCPX4 case "$TESTS" in *%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: echo via connection to TCP socket, v4 by target" -if ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -2483,7 +2694,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts TCP-listen:$tsl,pf=ip4,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP:$ts" printf "test $F_n $TEST... " $N @@ -2517,7 +2728,8 @@ NAME=TCPX6 case "$TESTS" in *%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: echo via connection to TCP socket, v6 by target" -if ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -2529,7 +2741,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="[::1]:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts TCP-listen:$tsl,pf=ip6,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP:$ts" printf "test $F_n $TEST... " $N @@ -2562,7 +2774,8 @@ NAME=IPV6ONLY0 case "$TESTS" in *%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: option ipv6-v6only=0 listens on IPv4" -if ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -2577,7 +2790,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts TCP6-listen:$tsl,ipv6-v6only=0,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP4:$ts" printf "test $F_n $TEST... " $N @@ -2610,7 +2823,8 @@ NAME=IPV6ONLY1 case "$TESTS" in *%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: option ipv6-v6only=1 does not listen on IPv4" -if ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -2625,7 +2839,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts TCP6-listen:$tsl,ipv6-v6only=1,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP4:$ts" printf "test $F_n $TEST... " $N @@ -2655,7 +2869,8 @@ NAME=ENV_LISTEN_4 case "$TESTS" in *%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: env SOCAT_DEFAULT_LISTEN_IP for IPv4 preference on listen" -if ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -2670,7 +2885,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts TCP-listen:$tsl,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP4:$ts" printf "test $F_n $TEST... " $N @@ -2703,7 +2918,8 @@ NAME=ENV_LISTEN_6 case "$TESTS" in *%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: env SOCAT_DEFAULT_LISTEN_IP for IPv6 preference on listen" -if ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -2715,7 +2931,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="[::1]:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts TCP-listen:$tsl,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP6:$ts" printf "test $F_n $TEST... " $N @@ -2748,7 +2964,8 @@ NAME=LISTEN_OPTION_4 case "$TESTS" in *%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: option -4 for IPv4 preference on listen" -if ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -2763,7 +2980,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -4 TCP-listen:$tsl,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP4:$ts" printf "test $F_n $TEST... " $N @@ -2796,7 +3013,8 @@ NAME=LISTEN_OPTION_6 case "$TESTS" in *%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: option -6 for IPv6 preference on listen" -if ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -2808,7 +3026,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="[::1]:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -6 TCP-listen:$tsl,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP6:$ts" printf "test $F_n $TEST... " $N @@ -2842,7 +3060,8 @@ NAME=LISTEN_PF_IP4 case "$TESTS" in *%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: pf=4 overrides option -6 on listen" -if ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -2857,7 +3076,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -6 TCP-listen:$tsl,pf=ip4,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP4:$ts" printf "test $F_n $TEST... " $N @@ -2890,7 +3109,8 @@ NAME=LISTEN_PF_IP6 case "$TESTS" in *%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: pf=6 overrides option -4 on listen" -if ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -2902,7 +3122,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="[::1]:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -4 TCP-listen:$tsl,pf=ip6,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP6:$ts" printf "test $F_n $TEST... " $N @@ -2926,7 +3146,7 @@ else numOK=$((numOK+1)) fi kill $pid 2>/dev/null -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -2936,12 +3156,13 @@ NAME=UDP4STREAM case "$TESTS" in *%functions%*|*%ip4%*|*%ipapp%*|*%udp%*|*%$NAME%*) TEST="$NAME: echo via connection to UDP V4 socket" +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="$LOCALHOST:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts UDP4-LISTEN:$tsl,reuseaddr PIPE" CMD2="$SOCAT $opts - UDP4:$ts" printf "test $F_n $TEST... " $N @@ -2969,7 +3190,8 @@ else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) -fi ;; +fi +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -2979,7 +3201,8 @@ NAME=UDP6STREAM case "$TESTS" in *%functions%*|*%ip6%*|*%ipapp%*|*%udp%*|*%$NAME%*) TEST="$NAME: echo via connection to UDP V6 socket" -if ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -2988,7 +3211,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="$LOCALHOST6:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts UDP6-LISTEN:$tsl,reuseaddr PIPE" CMD2="$SOCAT $opts - UDP6:$ts" printf "test $F_n $TEST... " $N @@ -3023,11 +3246,12 @@ NAME=GOPENFILE case "$TESTS" in *%functions%*|*%gopen%*|*%file%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: file opening with gopen" +if ! eval $NUMCOND; then :; else tf1="$td/test$N.1.stdout" tf2="$td/test$N.2.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" echo "$da" >$tf1 CMD="$SOCAT $opts /dev/null%$tf1 -%/dev/null,ignoreeof" printf "test $F_n $TEST... " $N @@ -3046,6 +3270,7 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi +fi # NUMCOND esac N=$((N+1)) @@ -3054,11 +3279,12 @@ NAME=GOPENPIPE case "$TESTS" in *%functions%*|*%gopen%*|*%pipe%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: pipe opening with gopen for reading" +if ! eval $NUMCOND; then :; else tp="$td/pipe$N" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" CMD="$SOCAT $opts /dev/null%$tp $tf%/dev/null,ignoreeof" printf "test $F_n $TEST... " $N #mknod $tp p # no mknod p on FreeBSD @@ -3095,6 +3321,7 @@ else fi fi wait +fi # NUMCOND esac N=$((N+1)) @@ -3103,6 +3330,7 @@ NAME=GOPENUNIXSTREAM case "$TESTS" in *%functions%*|*%gopen%*|*%unix%*|*%listen%*|*%$NAME%*) TEST="$NAME: GOPEN on UNIX stream socket" +if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" @@ -3140,6 +3368,7 @@ else numOK=$((numOK+1)) fi # !(rc -ne 0) wait +fi # NUMCOND esac N=$((N+1)) @@ -3148,6 +3377,7 @@ NAME=GOPENUNIXDGRAM case "$TESTS" in *%functions%*|*%gopen%*|*%unix%*|*%dgram%*|*%$NAME%*) TEST="$NAME: GOPEN on UNIX datagram socket" +if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" @@ -3185,6 +3415,7 @@ else fi # !(rc -ne 0) kill "$pids" 2>/dev/null wait +fi ;; # NUMCOND esac N=$((N+1)) @@ -3194,29 +3425,24 @@ NAME=IGNOREEOF case "$TESTS" in *%functions%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: ignoreeof on file" +if ! eval $NUMCOND; then :; else ti="$td/test$N.file" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date) $RANDOM" +da="test$N $(date) $RANDOM" CMD="$SOCAT $opts -u file:\"$ti\",ignoreeof -" printf "test $F_n $TEST... " $N touch "$ti" $CMD >"$tf" 2>"$te" & bg=$! -sleep 1 +usleep 500000 echo "$da" >>"$ti" sleep 1 kill $bg 2>/dev/null if ! echo "$da" |diff - "$tf" >"$tdiff"; then - if [ -s "$te" ]; then - $PRINTF "$FAILED: $SOCAT:\n" - echo "$CMD" - cat "$te" - else - $PRINTF "$FAILED: diff:\n" - cat "$tdiff" - fi + $PRINTF "$FAILED: diff:\n" + cat "$tdiff" numFAIL=$((numFAIL+1)) else $PRINTF "$OK\n" @@ -3224,15 +3450,17 @@ else numOK=$((numOK+1)) fi wait +fi ;; # NUMCOND esac N=$((N+1)) -#set +vx +set +vx NAME=EXECIGNOREEOF case "$TESTS" in *%functions%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: exec against address with ignoreeof" +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" CMD="$SOCAT $opts -lf "$te" EXEC:$TRUE /dev/null,ignoreeof" @@ -3248,6 +3476,7 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi +fi ;; # NUMCOND esac N=$((N+1)) @@ -3256,7 +3485,8 @@ NAME=FAKEPTY case "$TESTS" in *%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: generation of pty for other processes" -if ! testaddrs pty >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -3264,7 +3494,7 @@ tt="$td/pty$N" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts pty,link=$tt pipe" CMD2="$SOCAT $opts - $tt,$PTYOPTS2" printf "test $F_n $TEST... " $N @@ -3292,7 +3522,7 @@ else fi kill $pid 2>/dev/null wait -fi +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -3301,11 +3531,12 @@ NAME=O_TRUNC case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: option o-trunc" +if ! eval $NUMCOND; then :; else ff="$td/test$N.file" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" CMD="$SOCAT -u $opts - open:$ff,append,o-trunc" printf "test $F_n $TEST... " $N rm -f $ff; $ECHO "prefix-\c" >$ff @@ -3321,6 +3552,7 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi +fi ;; # NUMCOND esac N=$((N+1)) @@ -3329,11 +3561,12 @@ NAME=FTRUNCATE case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: option ftruncate" +if ! eval $NUMCOND; then :; else ff="$td/test$N.file" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" CMD="$SOCAT -u $opts - open:$ff,append,ftruncate=0" printf "test $F_n $TEST... " $N rm -f $ff; $ECHO "prefix-\c" >$ff @@ -3349,6 +3582,7 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi +fi ;; # NUMCOND esac N=$((N+1)) @@ -3365,6 +3599,7 @@ N=$((N+1)) NAME=CHILDDEFAULT case "$TESTS" in *%functions%*|*%$NAME%*) +if ! eval $NUMCOND; then :; else TEST="$NAME: child process default properties" tf="$td/test$N.stdout" te="$td/test$N.stderr" @@ -3387,6 +3622,7 @@ else $PRINTF "$OK\n" numOK=$((numOK+1)) fi +fi ;; # NUMCOND esac N=$((N+1)) @@ -3395,6 +3631,7 @@ NAME=CHILDSETSID case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: child process with setsid" +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" CMD="$SOCAT $opts -u exec:$PROCAN,setsid -" @@ -3417,6 +3654,7 @@ else $PRINTF "$OK\n" numOK=$((numOK+1)) fi +fi ;; # NUMCOND esac N=$((N+1)) @@ -3425,6 +3663,7 @@ NAME=MAINSETSID case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: main process with setsid" +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" CMD="$SOCAT $opts -U -,setsid exec:$PROCAN" @@ -3447,6 +3686,7 @@ else $PRINTF "$OK\n" numOK=$((numOK+1)) fi +fi ;; # NUMCOND esac N=$((N+1)) @@ -3568,7 +3808,8 @@ NAME=OPENSSL_TCP4 case "$TESTS" in *%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: openssl connect" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! type openssl >/dev/null 2>&1; then @@ -3582,7 +3823,7 @@ gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" 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,pf=ip4,verify=0,$SOCAT_EGD" @@ -3590,6 +3831,7 @@ CMD="$SOCAT $opts - openssl,verify=0,$SOCAT_EGD|tcp4:$LOCALHOST:$PORT" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id +# this might timeout when openssl opens tcp46 port like " :::$PORT" waittcp4port $PORT # the openssl s_server program appears to not support half closed connections, # so we must delay EOF @@ -3609,7 +3851,7 @@ else fi kill $pid 2>/dev/null wait -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -3619,7 +3861,8 @@ NAME=OPENSSLLISTEN_TCP4 case "$TESTS" in *%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: openssl listen" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then @@ -3630,7 +3873,7 @@ gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" #CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,reuseaddr,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 pipe" 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" @@ -3655,7 +3898,7 @@ else fi kill $pid 2>/dev/null wait -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -3664,7 +3907,8 @@ NAME=OPENSSLLISTEN_TCP6 case "$TESTS" in *%functions%*|*%openssl%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: openssl listen" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -3675,7 +3919,7 @@ gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip6,reuseaddr,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 pipe" CMD="$SOCAT $opts - openssl:$LOCALHOST6:$PORT,verify=0,$SOCAT_EGD" printf "test $F_n $TEST... " $N @@ -3698,7 +3942,7 @@ else fi kill $pid 2>/dev/null wait -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -3710,7 +3954,8 @@ case "$TESTS" in TEST="$NAME: openssl half close" # have an SSL server that executes "$OD_C" and see if EOF on the SSL client # brings the result of od to the client -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then @@ -3721,9 +3966,9 @@ gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,reuseaddr,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 exec:'$OD_C'" -CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT,verify=0,$SOCAT_EGD" +CMD="$SOCAT -T1 $OPTS - openssl:$LOCALHOST:$PORT,verify=0,$SOCAT_EGD" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id @@ -3744,7 +3989,7 @@ else fi kill $pid 2>/dev/null wait -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -3754,7 +3999,8 @@ NAME=OPENSSL_SERVERAUTH case "$TESTS" in *%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: openssl server authentication" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then @@ -3766,7 +4012,7 @@ gentestcert testcli tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,reuseaddr,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 pipe" CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT,verify=1,cafile=testsrv.crt,$SOCAT_EGD" printf "test $F_n $TEST... " $N @@ -3789,7 +4035,7 @@ else fi kill $pid 2>/dev/null wait -fi # feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -3798,7 +4044,8 @@ NAME=OPENSSL_CLIENTAUTH case "$TESTS" in *%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: openssl client authentication" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then @@ -3810,7 +4057,7 @@ gentestcert testcli tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,reuseaddr,verify=1,cert=testsrv.crt,key=testsrv.key,cafile=testcli.crt,$SOCAT_EGD pipe" CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT,verify=0,cert=testcli.crt,key=testcli.key,$SOCAT_EGD" printf "test $F_n $TEST... " $N @@ -3833,7 +4080,7 @@ else fi kill $pid 2>/dev/null wait -fi # feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -3842,7 +4089,8 @@ NAME=OPENSSL_FIPS_BOTHAUTH case "$TESTS" in *%functions%*|*%openssl%*|*%fips%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: OpenSSL+FIPS client and server authentication" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then @@ -3857,7 +4105,7 @@ OPENSSL_FIPS=1 gentestcert testclifips tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,reuseaddr,fips,$SOCAT_EGD,cert=testsrvfips.crt,key=testsrvfips.key,cafile=testclifips.crt pipe" CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT,fips,verify=1,cert=testclifips.crt,key=testclifips.key,cafile=testsrvfips.crt,$SOCAT_EGD" printf "test $F_n $TEST... " $N @@ -3880,7 +4128,7 @@ else fi kill $pid 2>/dev/null wait -fi # feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -3890,7 +4138,8 @@ NAME=SOCKS4CONNECT_TCP4 case "$TESTS" in *%functions%*|*%socks%*|*%socks4%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: socks4 connect over TCP/IPv4" -if ! testaddrs socks4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs socks4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}SOCKS4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then @@ -3900,7 +4149,7 @@ else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date)" da="$da$($ECHO '\r')" +da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # we have a normal tcp echo listening - so the socks header must appear in answer CMD2="$SOCAT tcp4-l:$PORT,reuseaddr exec:\"./socks4echo.sh\"" #CMD="$SOCAT $opts - socks4:$LOCALHOST:32.98.76.54:32109,pf=ip4,socksport=$PORT",socksuser="nobody" @@ -3925,7 +4174,7 @@ else fi kill $pid 2>/dev/null wait -fi # feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -3934,7 +4183,8 @@ NAME=SOCKS4CONNECT_TCP6 case "$TESTS" in *%functions%*|*%socks%*|*%socks4%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: socks4 connect over TCP/IPv6" -if ! testaddrs socks4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs socks4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}SOCKS4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -3944,7 +4194,7 @@ else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date)" da="$da$($ECHO '\r')" +da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # we have a normal tcp echo listening - so the socks header must appear in answer CMD2="$SOCAT tcp6-l:$PORT,reuseaddr exec:\"./socks4echo.sh\"" CMD="$SOCAT $opts - socks4:$LOCALHOST6:32.98.76.54:32109,socksport=$PORT",socksuser="nobody" @@ -3968,7 +4218,7 @@ else fi kill $pid 2>/dev/null wait -fi # feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -3978,7 +4228,8 @@ NAME=SOCKS4ACONNECT_TCP4 case "$TESTS" in *%functions%*|*%socks%*|*%socks4a%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: socks4a connect over TCP/IPv4" -if ! testaddrs socks4a >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs socks4a >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}SOCKS4A not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then @@ -3988,7 +4239,7 @@ else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date)" da="$da$($ECHO '\r')" +da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # we have a normal tcp echo listening - so the socks header must appear in answer CMD2="$SOCAT tcp4-l:$PORT,reuseaddr exec:\"./socks4a-echo.sh\"" #CMD="$SOCAT $opts - socks4a:$LOCALHOST:localhost:32109,pf=ip4,socksport=$PORT",socksuser="nobody" @@ -4013,7 +4264,7 @@ else fi kill $pid 2>/dev/null wait -fi # feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -4022,7 +4273,8 @@ NAME=SOCKS4ACONNECT_TCP6 case "$TESTS" in *%functions%*|*%socks%*|*%socks4a%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: socks4a connect over TCP/IPv6" -if ! testaddrs socks4a >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs socks4a >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}SOCKS4A not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -4032,7 +4284,7 @@ else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date)" da="$da$($ECHO '\r')" +da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # we have a normal tcp echo listening - so the socks header must appear in answer CMD2="$SOCAT tcp6-l:$PORT,reuseaddr exec:\"./socks4a-echo.sh\"" CMD="$SOCAT $opts - socks4a:$LOCALHOST6:localhost:32109,socksport=$PORT",socksuser="nobody" @@ -4056,7 +4308,7 @@ else fi kill $pid 2>/dev/null wait -fi # feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -4066,7 +4318,8 @@ NAME=PROXYCONNECT_TCP4 case "$TESTS" in *%functions%*|*%proxyconnect%*|*%proxy%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: proxy connect over TCP/IPv4" -if ! testaddrs proxy >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs proxy >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PROXY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then @@ -4077,7 +4330,7 @@ ts="$td/test$N.sh" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date)" da="$da$($ECHO '\r')" +da="test$N $(date) $RANDOM"; 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,reuseaddr,crlf exec:\"/bin/bash proxyecho.sh\"" #CMD="$SOCAT $opts - proxy:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT" @@ -4102,7 +4355,7 @@ else fi kill $pid 2>/dev/null wait -fi # feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -4111,7 +4364,8 @@ NAME=PROXYCONNECT_TCP6 case "$TESTS" in *%functions%*|*%proxyconnect%*|*%proxy%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: proxy connect over TCP/IPv6" -if ! testaddrs proxy >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs proxy >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PROXY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip6 >/dev/null || ! runsip6 >/dev/null; then @@ -4122,7 +4376,7 @@ ts="$td/test$N.sh" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date)" da="$da$($ECHO '\r')" +da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" #CMD2="$SOCAT tcp6-l:$PORT,crlf system:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\"" CMD2="$SOCAT tcp6-l:$PORT,reuseaddr,crlf exec:\"/bin/bash proxyecho.sh\"" CMD="$SOCAT $opts - proxy:$LOCALHOST6:127.0.0.1:1000,proxyport=$PORT" @@ -4146,7 +4400,7 @@ else fi kill $pid 2>/dev/null wait -fi # feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -4156,12 +4410,13 @@ NAME=TCP4NOFORK case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: echo via connection to TCP V4 socket with nofork'ed exec" +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts TCP4-LISTEN:$tsl,reuseaddr exec:$CAT,nofork" CMD2="$SOCAT $opts stdout%stdin TCP4:$ts" printf "test $F_n $TEST... " $N @@ -4186,6 +4441,7 @@ else if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -4219,10 +4475,11 @@ N=$((N+1)) #============================================================================== #TEST="$NAME: echo via 'connection' to UDP V4 socket" +#if ! eval $NUMCOND; then :; else #tf="$td/file$N" #tsl=65534 #ts="127.0.0.1:$tsl" -#da=$(date) +#da="test$N $(date) $RANDOM" #$SOCAT UDP-listen:$tsl PIPE & #sleep 2 #echo "$da" |$SOCAT stdout%stdin UDP:$ts >"$tf" @@ -4233,13 +4490,15 @@ N=$((N+1)) # $ECHO "*** test $N $FAILED" # numFAIL=$((numFAIL+1)) #fi +#fi ;; # NUMCOND #N=$((N+1)) #============================================================================== # TEST 4 - simple echo via new file +#if ! eval $NUMCOND; then :; else #N=4 #tf="$td/file$N" #tp="$td/pipe$N" -#da=$(date) +#da="test$N $(date) $RANDOM" #rm -f "$tf.tmp" #echo "$da" |$SOCAT - FILE:$tf.tmp,ignoreeof >"$tf" #if [ $? -eq 0 ] && echo "$da" |diff "$tf" -; then @@ -4249,6 +4508,7 @@ N=$((N+1)) # $ECHO "*** test $N $FAILED" # numFAIL=$((numFAIL+1)) #fi +#fi ;; # NUMCOND #============================================================================== @@ -4256,14 +4516,12 @@ NAME=TOTALTIMEOUT case "$TESTS" in *%functions%*|*%timeout%*|*%$NAME%*) TEST="$NAME: socat inactivity timeout" -if ! true; then - : -else +if ! eval $NUMCOND; then :; else #set -vx tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date)" da="$da$($ECHO '\r')" +da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" CMD2="$SOCAT $opts -T 1 tcp4-listen:$PORT,reuseaddr pipe" CMD="$SOCAT $opts - tcp4-connect:$LOCALHOST:$PORT" printf "test $F_n $TEST... " $N @@ -4287,7 +4545,7 @@ fi kill $pid 2>/dev/null wait #set +vx -fi # feats +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -4297,21 +4555,19 @@ NAME=IGNOREEOF+TOTALTIMEOUT case "$TESTS" in *%functions%*|*%timeout%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: ignoreeof and inactivity timeout" -if ! true; then - : -else +if ! eval $NUMCOND; then :; else #set -vx ti="$td/test$N.file" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date) $RANDOM" +da="test$N $(date) $RANDOM" CMD="$SOCAT $opts -T 2 -u file:\"$ti\",ignoreeof -" printf "test $F_n $TEST... " $N touch "$ti" $CMD >"$tf" 2>"$te" & bg=$! # background process id -sleep 1 +psleep 0.5 echo "$da" >>"$ti" sleep 4 echo X >>"$ti" @@ -4329,7 +4585,7 @@ else numOK=$((numOK+1)) fi wait -fi # feats +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -4338,7 +4594,8 @@ NAME=PROXY2SPACES case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: proxy connect accepts status with multiple spaces" -if ! testaddrs proxy >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs proxy >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PROXY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -4346,7 +4603,7 @@ ts="$td/test$N.sh" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date)" da="$da$($ECHO '\r')" +da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" #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\"" #CMD="$SOCAT $opts - proxy:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT" @@ -4371,7 +4628,7 @@ else fi kill $pid 2>/dev/null wait -fi # feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -4381,6 +4638,7 @@ NAME=BUG-UNISTDIO case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: for bug with address options on both stdin/out in unidirectional mode" +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" ff="$td/file$N" @@ -4403,6 +4661,7 @@ else numCANT=$((numCANT+1)) fi fi +fi ;; # NUMCOND esac N=$((N+1)) @@ -4427,12 +4686,13 @@ NAME=SINGLEEXECOUTPTY case "$TESTS" in *%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: inheritance of stdout to single exec with pty" -if ! testaddrs pty >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testecho "$N" "$TEST" "exec:cat,pty,raw%-" "" "$opts" 1 -fi +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -4456,12 +4716,13 @@ NAME=SINGLEEXECINPTYDELAY case "$TESTS" in *%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: inheritance of stdin to single exec with pty, with delay" -if ! testaddrs pty >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testecho "$N" "$TEST" "-%exec:cat,pty,raw" "" "$opts" $MISCDELAY -fi +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -4469,12 +4730,13 @@ NAME=SINGLEEXECINPTY case "$TESTS" in *%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: inheritance of stdin to single exec with pty" -if ! testaddrs pty >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testecho "$N" "$TEST" "-%exec:cat,pty,raw" "" "$opts" -fi +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -4484,10 +4746,12 @@ NAME=READLINE case "$TESTS" in *%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: readline with password and sigint" -if ! feat=$(testaddrs readline pty); then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs readline pty); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else +SAVETERM="$TERM"; TERM= # 'cause konsole might print controls even in raw SAVEMICS=$MICROS #MICROS=2000000 ts="$td/test$N.sh" @@ -4497,9 +4761,9 @@ tpo="$td/test$N.outpipe" te="$td/test$N.stderr" tr="$td/test$N.ref" tdiff="$td/test$N.diff" -da="$(date)" da="$da$($ECHO '\r')" +da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # the feature that we really want to test is in the readline.sh script: -CMD="$SOCAT $opts open:$tpo%open:$tpi,nonblock exec:\"./readline.sh -nh ./readline-test.sh\",pty,ctty,setsid,raw,echo=0,isig" +CMD="$SOCAT $opts -t1 open:$tpo%open:$tpi,nonblock exec:\"./readline.sh -nh ./readline-test.sh\",pty,ctty,setsid,raw,echo=0,isig" #echo "$CMD" >"$ts" #chmod a+x "$ts" printf "test $F_n $TEST... " $N @@ -4532,18 +4796,6 @@ $ECHO "exit\n\c" usleep $MICROS ) >"$tpi" -#cat >$tr < prog> test 1 -#executing test 1 -#prog> ./readline-test.sh got SIGINT -# test 2 -#executing test 2 -#prog> prog> exit -#EOF cat >$tr </dev/null 2>&1; then #0 if ! sed 's/.*'"$($ECHO '\r\c')"'//dev/null 2>&1; then +wait if ! tr "$($ECHO '\r \c')" "% " <$tpo |sed 's/%$//g' |sed 's/.*%//g' |diff "$tr" - >"$tdiff" 2>&1; then $PRINTF "$FAILED: $SOCAT:\n" echo "$CMD" @@ -4570,9 +4823,11 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -#kill $pid 2>/dev/null +kill $pid 2>/dev/null # necc on OpenBSD +wait MICROS=$SAVEMICS -fi +TERM="$SAVETERM" +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -4582,10 +4837,11 @@ NAME=GENDERCHANGER case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: TCP4 \"gender changer\"" +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" # this is the server in the protected network that we want to reach CMD1="$SOCAT -lpserver $opts tcp4-l:$PORT,reuseaddr,bind=$LOCALHOST echo" # this is the double client in the protected network @@ -4621,6 +4877,7 @@ else fi kill $pid1 $pid2 $pid3 $pid4 2>/dev/null wait +fi ;; # NUMCOND esac PORT=$((PORT+3)) N=$((N+1)) @@ -4633,7 +4890,8 @@ NAME=OUTBOUNDIN case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: gender changer via SSL through HTTP proxy, oneshot" -if ! feat=$(testaddrs openssl proxy); then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs openssl proxy); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat |tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -4642,7 +4900,7 @@ gentestcert testcli tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" # this is the server in the protected network that we want to reach CMD1="$SOCAT $opts -lpserver tcp4-l:$PORT,reuseaddr,bind=$LOCALHOST echo" # this is the proxy in the protected network that provides a way out @@ -4700,20 +4958,27 @@ else fi kill $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null wait -fi # feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+5)) N=$((N+1)) -#! +# test the TCP gender changer with almost production requirements: a double +# client repeatedly tries to connect to a double server via SSL through an HTTP +# proxy. the double servers SSL port becomes active for one connection only +# after a (real) client has connected to its TCP port. when the double client +# succeeded to establish an SSL connection, it connects with its second client +# side to the specified (protected) server. all three consecutive connections +# must function for full success of this test. PORT=$((RANDOM+16184)) #! NAME=INTRANETRIPPER case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: gender changer via SSL through HTTP proxy, daemons" -if ! feat=$(testaddrs openssl proxy); then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs openssl proxy); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -4728,6 +4993,8 @@ da3="test$N.3 $(date) $RANDOM" # this is the server in the protected network that we want to reach CMD1="$SOCAT $opts -lpserver -t1 tcp4-l:$PORT,reuseaddr,bind=$LOCALHOST,fork echo" # this is the proxy in the protected network that provides a way out +# note: the proxy.sh script starts one or two more socat processes without +# setting the program name CMD2="$SOCAT $opts -lpproxy -t1 tcp4-l:$((PORT+1)),reuseaddr,bind=$LOCALHOST,fork exec:./proxy.sh" # this is our proxy connect wrapper in the protected network #CMD3="$SOCAT $opts -lpwrapper -t3 tcp4-l:$((PORT+2)),reuseaddr,bind=$LOCALHOST,fork proxy:$LOCALHOST:$LOCALHOST:$((PORT+3)),pf=ip4,proxyport=$((PORT+1)),resolve" @@ -4735,13 +5002,13 @@ CMD3="$SOCAT $opts -lu -lpwrapper -t3 tcp4-l:$((PORT+2)),reuseaddr,bind=$LOCALHO # 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 -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" +CMD4="$SOCAT $opts -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 #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" +CMD5="$SOCAT $opts -lp2server -t4 tcp4-l:$((PORT+4)),reuseaddr,bind=$LOCALHOST,backlog=3,fork ssl-l,$SOCAT_EGD,cert=testsrv.pem,cafile=testcli.crt\\|tcp4-l:$((PORT+3)),reuseaddr,bind=$LOCALHOST,retry=20,interval=0.5" # 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 -t6 - tcp4:$LOCALHOST:$((PORT+4)),retry=3" printf "test $F_n $TEST... " $N # start the intranet infrastructure eval "$CMD1 2>\"${te}1\" &" @@ -4773,6 +5040,8 @@ wait $pid6_1 $pid6_2 $pid6_3 (echo "$da2"; sleep 2) |diff - "${tf}_2" >"${tdiff}2" (echo "$da3"; sleep 2) |diff - "${tf}_3" >"${tdiff}3" if test -s "${tdiff}1" -o -s "${tdiff}2" -o -s "${tdiff}3"; then + # FAILED only when none of the three transfers succeeded + if test -s "${tdiff}1" -a -s "${tdiff}2" -a -s "${tdiff}3"; then $PRINTF "$FAILED: $SOCAT:\n" echo "$CMD1 &" cat "${te}1" @@ -4794,6 +5063,11 @@ if test -s "${tdiff}1" -o -s "${tdiff}2" -o -s "${tdiff}3"; then cat "${te}6_3" cat "${tdiff}3" numFAIL=$((numFAIL+1)) + else + $PRINTF "$OK ${YELLOW}(partial failure)${NORMAL}\n" + if [ -n "$debug" ]; then cat "${te}1" "${te}2" "${te}3" "${te}4" "${te}5" ${te}6*; fi + numOK=$((numOK+1)) + fi else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2" "${te}3" "${te}4" "${te}5" ${te}6*; fi @@ -4801,7 +5075,7 @@ else fi kill $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null wait -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+5)) N=$((N+1)) @@ -4813,7 +5087,7 @@ N=$((N+1)) # test the security features of a server address testserversec () { - local num="$1" + local N="$1" local title="$2" local opts="$3" local arg1="$4" # the server address @@ -4829,10 +5103,10 @@ testserversec () { local te="$td/test$N.stderr" local tdiff1="$td/test$N.diff1" local tdiff2="$td/test$N.diff2" - local da="$(date)" + local da="test$N.1 $(date) $RANDOM" local stat result - $PRINTF "test $F_n %s... " $num "$title" + $PRINTF "test $F_n %s... " $N "$title" #set -vx # first: without security # start server @@ -4902,6 +5176,7 @@ testserversec () { return fi # now use client + da="test$N.2 $(date) $RANDOM" (echo "$da"; sleep $T) |$SOCAT $opts - "$arg2" >"$tf" 2>"${te}4" stat=$? kill $spid 2>/dev/null @@ -4960,7 +5235,14 @@ NAME=TCP4RANGEBITS case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with RANGE option" +if ! eval $NUMCOND; then :; +elif [ -z "$SECONDADDR" ]; then + # we need access to a second addresses + $PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=$SECONDADDR/32" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0 +fi ;; # $SECONDADDR, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -4969,13 +5251,31 @@ NAME=TCP4RANGEMASK case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with RANGE option" -if [ "$UNAME" != Linux ]; then +if ! eval $NUMCOND; then :; +elif [ -z "$SECONDADDR" ]; then + # we need access to a second addresses + $PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=$SECONDADDR:255.255.255.255" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0 +fi ;; # $SECONDADDR, NUMCOND +esac +PORT=$((PORT+1)) +N=$((N+1)) + +# like TCP4RANGEMASK, but the "bad" address is within the same class A network +NAME=TCP4RANGEMASKHAIRY +case "$TESTS" in +*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) +TEST="$NAME: security of TCP4-L with RANGE option" +if ! eval $NUMCOND; then :; +elif [ "$UNAME" != Linux ]; then # we need access to more loopback addresses $PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N numCANT=$((numCANT+1)) else testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=127.0.0.0:255.255.0.0" "tcp4:127.1.0.0:$PORT" 4 tcp $PORT 0 -fi ;; # Linux +fi ;; # Linux, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -4985,7 +5285,9 @@ NAME=TCP4SOURCEPORT case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with SOURCEPORT option" +if ! eval $NUMCOND; then :; else testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "sp=$PORT" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0 +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -4994,7 +5296,9 @@ NAME=TCP4LOWPORT case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with LOWPORT option" +if ! eval $NUMCOND; then :; else testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "lowport" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0 +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -5003,7 +5307,8 @@ NAME=TCP4WRAPPERS_ADDR case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with TCPWRAP option" -if ! feat=$(testaddrs tcp ip4 libwrap) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip4 libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -5012,7 +5317,7 @@ hd="$td/hosts.deny" $ECHO "socat: $SECONDADDR" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "hosts-allow=$ha,hosts-deny=$hd" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0 -fi ;; # feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5021,7 +5326,8 @@ NAME=TCP4WRAPPERS_NAME case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with TCPWRAP option" -if ! feat=$(testaddrs tcp ip4 libwrap) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip4 libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -5030,7 +5336,7 @@ hd="$td/hosts.deny" $ECHO "socat: $LOCALHOST" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "hosts-allow=$ha,hosts-deny=$hd" "tcp4:$SECONDADDR:$PORT" 4 tcp $PORT 0 -fi ;; # feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5040,12 +5346,13 @@ NAME=TCP6RANGE case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%range%*|*%$NAME%*) TEST="$NAME: security of TCP6-L with RANGE option" -if ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testserversec "$N" "$TEST" "$opts -s" "tcp6-l:$PORT,reuseaddr,fork,retry=1" "" "range=[::2/128]" "tcp6:[::1]:$PORT" 6 tcp $PORT 0 -fi # feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5054,12 +5361,13 @@ NAME=TCP6SOURCEPORT case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of TCP6-L with SOURCEPORT option" -if ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testserversec "$N" "$TEST" "$opts -s" "tcp6-l:$PORT,reuseaddr,fork,retry=1" "" "sp=$PORT" "tcp6:[::1]:$PORT" 6 tcp $PORT 0 -fi # ! feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5068,12 +5376,13 @@ NAME=TCP6LOWPORT case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of TCP6-L with LOWPORT option" -if ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testserversec "$N" "$TEST" "$opts -s" "tcp6-l:$PORT,reuseaddr,fork,retry=1" "" "lowport" "tcp6:[::1]:$PORT" 6 tcp $PORT 0 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5082,7 +5391,8 @@ NAME=TCP6TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of TCP6-L with TCPWRAP option" -if ! feat=$(testaddrs tcp ip6 libwrap) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip6 libwrap) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -5091,8 +5401,7 @@ hd="$td/hosts.deny" $ECHO "socat: [::2]" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts -s" "tcp6-l:$PORT,reuseaddr,fork,retry=1" "" "hosts-allow=$ha,hosts-deny=$hd" "tcp6:[::1]:$PORT" 6 tcp $PORT 0 -fi # ! feat -;; +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5102,8 +5411,10 @@ NAME=UDP4RANGE case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP4-L with RANGE option" +if ! eval $NUMCOND; then :; else #testserversec "$N" "$TEST" "$opts -s" "udp4-l:$PORT,reuseaddr,fork" "" "range=$SECONDADDR/32" "udp4:127.0.0.1:$PORT" 4 udp $PORT 0 testserversec "$N" "$TEST" "$opts -s" "udp4-l:$PORT,reuseaddr" "" "range=$SECONDADDR/32" "udp4:127.0.0.1:$PORT" 4 udp $PORT 0 +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -5112,7 +5423,9 @@ NAME=UDP4SOURCEPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP4-L with SOURCEPORT option" +if ! eval $NUMCOND; then :; else testserversec "$N" "$TEST" "$opts -s" "udp4-l:$PORT,reuseaddr" "" "sp=$PORT" "udp4:127.0.0.1:$PORT" 4 udp $PORT 0 +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -5121,7 +5434,9 @@ NAME=UDP4LOWPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP4-L with LOWPORT option" +if ! eval $NUMCOND; then :; else testserversec "$N" "$TEST" "$opts -s" "udp4-l:$PORT,reuseaddr" "" "lowport" "udp4:127.0.0.1:$PORT" 4 udp $PORT 0 +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -5130,7 +5445,8 @@ NAME=UDP4TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP4-L with TCPWRAP option" -if ! feat=$(testaddrs udp ip4 libwrap) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip4 libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -5139,7 +5455,7 @@ hd="$td/hosts.deny" $ECHO "socat: $SECONDADDR" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts -s" "udp4-l:$PORT,reuseaddr,retry=1" "" "tcpwrap-etc=$td" "udp4:127.0.0.1:$PORT" 4 udp $PORT 0 -fi ;; # feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5149,13 +5465,14 @@ NAME=UDP6RANGE case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP6-L with RANGE option" -if ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else #testserversec "$N" "$TEST" "$opts -s" "udp6-l:$PORT,reuseaddr,fork" "" "range=[::2/128]" "udp6:[::1]:$PORT" 6 udp $PORT 0 testserversec "$N" "$TEST" "$opts -s" "udp6-l:$PORT,reuseaddr" "" "range=[::2/128]" "udp6:[::1]:$PORT" 6 udp $PORT 0 -fi # ! feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5164,12 +5481,13 @@ NAME=UDP6SOURCEPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP6-L with SOURCEPORT option" -if ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testserversec "$N" "$TEST" "$opts -s" "udp6-l:$PORT,reuseaddr" "" "sp=$PORT" "udp6:[::1]:$PORT" 6 udp $PORT 0 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5178,12 +5496,13 @@ NAME=UDP6LOWPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP6-L with LOWPORT option" -if ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testserversec "$N" "$TEST" "$opts -s" "udp6-l:$PORT,reuseaddr" "" "lowport" "udp6:[::1]:$PORT" 6 udp $PORT 0 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5192,7 +5511,8 @@ NAME=UDP6TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP6-L with TCPWRAP option" -if ! feat=$(testaddrs tcp ip6 libwrap) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip6 libwrap) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -5201,7 +5521,7 @@ hd="$td/hosts.deny" $ECHO "socat: [::2]" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts -s" "udp6-l:$PORT,reuseaddr" "" "lowport" "udp6:[::1]:$PORT" 6 udp $PORT 0 -fi ;; # feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5211,13 +5531,14 @@ NAME=OPENSSLTCP4_RANGE case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%range%*|*%$NAME%*) TEST="$NAME: security of SSL-L over TCP/IPv4 with RANGE option" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else gentestcert testsrv testserversec "$N" "$TEST" "$opts -s" "ssl-l:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "range=$SECONDADDR/32" "ssl:127.0.0.1:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5226,13 +5547,14 @@ NAME=OPENSSLTCP4_SOURCEPORT case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of SSL-L with SOURCEPORT option" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else gentestcert testsrv testserversec "$N" "$TEST" "$opts -s" "ssl-l:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "sp=$PORT" "ssl:127.0.0.1:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5241,13 +5563,14 @@ NAME=OPENSSLTCP4_LOWPORT case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of SSL-L with LOWPORT option" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else gentestcert testsrv testserversec "$N" "$TEST" "$opts -s" "ssl-l:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "lowport" "ssl:127.0.0.1:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5256,7 +5579,8 @@ NAME=OPENSSLTCP4_TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of SSL-L with TCPWRAP option" -if ! feat=$(testaddrs ip4 tcp libwrap openssl); then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 tcp libwrap openssl); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -5266,7 +5590,7 @@ hd="$td/hosts.deny" $ECHO "socat: $SECONDADDR" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts -s" "ssl-l:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "tcpwrap-etc=$td" "ssl:127.0.0.1:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1 -fi ;; # feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5275,14 +5599,15 @@ NAME=OPENSSLCERTSERVER case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*) TEST="$NAME: security of SSL-L with client certificate" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else gentestcert testsrv gentestcert testcli testserversec "$N" "$TEST" "$opts -s" "ssl-l:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify,cert=testsrv.crt,key=testsrv.key" "cafile=testcli.crt" "cafile=testsrv.crt" "ssl:127.0.0.1:$PORT,cafile=testsrv.crt,cert=testcli.pem,$SOCAT_EGD" 4 tcp $PORT -1 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5291,14 +5616,15 @@ NAME=OPENSSLCERTCLIENT case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*) TEST="$NAME: security of SSL with server certificate" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else gentestcert testsrv gentestcert testcli testserversec "$N" "$TEST" "$opts -s -lu -d" "ssl:$LOCALHOST:$PORT,pf=ip4,fork,retry=2,verify,cert=testcli.pem,$SOCAT_EGD" "cafile=testsrv.crt" "cafile=testcli.crt" "ssl-l:$PORT,pf=ip4,reuseaddr,$SOCAT_EGD,cafile=testcli.crt,cert=testsrv.crt,key=testsrv.key" 4 tcp "" -1 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5308,7 +5634,8 @@ NAME=OPENSSLTCP6_RANGE case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%range%*|*%$NAME%*) TEST="$NAME: security of SSL-L over TCP/IPv6 with RANGE option" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then @@ -5317,7 +5644,7 @@ elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then else gentestcert testsrv testserversec "$N" "$TEST" "$opts -s" "ssl-l:$PORT,pf=ip6,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "range=[::2/128]" "ssl:[::1]:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 6 tcp $PORT -1 -fi # ! feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5326,7 +5653,8 @@ NAME=OPENSSLTCP6_SOURCEPORT case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of SSL-L over TCP/IPv6 with SOURCEPORT option" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then @@ -5335,7 +5663,7 @@ elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then else gentestcert testsrv testserversec "$N" "$TEST" "$opts -s" "ssl-l:$PORT,pf=ip6,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "sp=$PORT" "ssl:[::1]:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 6 tcp $PORT -1 -fi # ! feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5344,7 +5672,8 @@ NAME=OPENSSLTCP6_LOWPORT case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of SSL-L over TCP/IPv6 with LOWPORT option" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then @@ -5353,7 +5682,7 @@ elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then else gentestcert testsrv testserversec "$N" "$TEST" "$opts -s" "ssl-l:$PORT,pf=ip6,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "lowport" "ssl:[::1]:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 6 tcp $PORT -1 -fi # ! feats +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5362,7 +5691,8 @@ NAME=OPENSSLTCP6_TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of SSL-L over TCP/IPv6 with TCPWRAP option" -if ! feat=$(testaddrs ip6 tcp libwrap openssl) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip6 tcp libwrap openssl) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -5372,7 +5702,7 @@ hd="$td/hosts.deny" $ECHO "socat: [::2]" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts -s" "ssl-l:$PORT,pf=ip6,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "tcpwrap-etc=$td" "ssl:[::1]:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 6 tcp $PORT -1 -fi # ! feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -5382,7 +5712,8 @@ NAME=OPENSSL_FIPS_SECURITY case "$TESTS" in *%functions%*|*%security%*|*%openssl%*|*%fips%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: OpenSSL restrictions by FIPS" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! testaddrs listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then @@ -5396,7 +5727,7 @@ gentestcert testsrv gentestcert testcli # openssl client accepts a "normal" certificate only when not in fips mode testserversec "$N" "$TEST" "$opts -s" "ssl:$LOCALHOST:$PORT,fork,retry=2,verify,cafile=testsrv.crt" "" "fips" "ssl-l:$PORT,pf=ip4,reuseaddr,cert=testsrv.crt,key=testsrv.key" 4 tcp "" -1 -fi ;; # testaddrs +fi ;; # testaddrs, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -5424,6 +5755,7 @@ NAME=FILANDIR case "$TESTS" in *%filan%*|*%$NAME%*) TEST="$NAME: check type printed for directories" +if ! eval $NUMCOND; then :; else te="$td/test$N.stderr" printf "test $F_n $TEST... " $N type=$($FILAN -f . 2>$te |tail -n 1 |awk '{print($2);}') @@ -5435,6 +5767,7 @@ else cat "$te" numFAIL=$((numFAIL+1)) fi +fi ;; # NUMCOND esac N=$((N+1)) @@ -5443,6 +5776,7 @@ NAME=FILANSOCKET case "$TESTS" in *%filan%*|*%$NAME%*) TEST="$NAME: capability to analyze named unix socket" +if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" te1="$td/test$N.stderr1" # socat te2="$td/test$N.stderr2" # filan @@ -5462,7 +5796,7 @@ else fi kill $spid 2>/dev/null wait -;; +fi ;; # NUMCOND esac N=$((N+1)) @@ -5473,15 +5807,15 @@ testptywaitslave () { local PTYTYPE="$3" # ptmx or openpty local opts="$4" -tp="$td/test$N.pty" -ts="$td/test$N.socket" -tf="$td/test$N.file" -tdiff="$td/test$N.diff" -te1="$td/test$N.stderr1" -te2="$td/test$N.stderr2" -te3="$td/test$N.stderr3" -te4="$td/test$N.stderr4" -da="test$N.1 $(date) $RANDOM" + local tp="$td/test$N.pty" + local ts="$td/test$N.socket" + local tf="$td/test$N.file" + local tdiff="$td/test$N.diff" + local te1="$td/test$N.stderr1" + local te2="$td/test$N.stderr2" + local te3="$td/test$N.stderr3" + local te4="$td/test$N.stderr4" + local da="test$N $(date) $RANDOM" printf "test $F_n $TEST... " $N # first generate a pty, then a socket ($SOCAT $opts -lpsocat1 pty,$PTYTYPE,pty-wait-slave,link="$tp" unix-listen:"$ts" 2>"$te1"; rm -f "$tp") 2>/dev/null & @@ -5518,6 +5852,7 @@ PTYTYPE=ptmx case "$TESTS" in *%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: test if master pty ($PTYTYPE) waits for slave connection" +if ! eval $NUMCOND; then :; else if ! feat=$(testaddrs pty); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) @@ -5527,6 +5862,7 @@ elif ! feat=$(testoptions "$PTYTYPE" pty-wait-slave); then else testptywaitslave "$N" "$TEST" "$PTYTYPE" "$opts" fi +fi ;; # NUMCOND esac N=$((N+1)) @@ -5535,7 +5871,8 @@ PTYTYPE=openpty case "$TESTS" in *%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: test if master pty ($PTYTYPE) waits for slave connection" -if ! feat=$(testaddrs pty); then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs pty); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testoptions "$PTYTYPE" pty-wait-slave); then @@ -5543,7 +5880,7 @@ elif ! feat=$(testoptions "$PTYTYPE" pty-wait-slave); then numCANT=$((numCANT+1)) else testptywaitslave "$N" "$TEST" "$PTYTYPE" "$opts" -fi +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -5552,7 +5889,8 @@ NAME=CONNECTTIMEOUT case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: test the connect-timeout option" -if ! feat=$(testaddrs tcp); then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testoptions connect-timeout); then @@ -5595,7 +5933,7 @@ else fi fi wait -fi ;; # testaddrs +fi ;; # testaddrs, NUMCOND esac N=$((N+1)) @@ -5604,7 +5942,8 @@ NAME=OPENSSLLISTENDSA case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: openssl listen with DSA certificate" -if ! testaddrs openssl >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -5613,7 +5952,7 @@ gentestdsacert $SRVCERT tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" #CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,reuseaddr,$SOCAT_EGD,cert=$SRVCERT.pem,key=$SRVCERT.key,verify=0 pipe" 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" @@ -5638,7 +5977,7 @@ else fi kill $pid 2>/dev/null wait -fi ;; # testaddrs +fi ;; # testaddrs, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -5647,9 +5986,9 @@ N=$((N+1)) # derive signal number from signal name # kill -l should provide the info signum () { - if [ ! "$BASH_VERSION" ]; then + if [ ! "$BASH_VERSION" -o -o posix ]; then # we expect: - for i in $(kill -l); do echo $i; done |grep -n -i $1 |cut -d: -f1 + for i in $(POSIXLY_CORRECT=1 kill -l); do echo $i; done |grep -n -i "^$1$" |cut -d: -f1 else # expect: # " 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL" @@ -5667,16 +6006,17 @@ NAME=EXITCODESIG$signam case "$TESTS" in *%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: exit status when dying on SIG$signam" -if ! feat=$(testaddrs pty); then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs pty); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat |tr a-z A-Z) not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else -SIG=$(signum $signam) +SIG="$(signum $signam)" te="$td/test$N.stderr" tpp="$td/test$N.ppid" tp="$td/test$N.pid" $PRINTF "test $F_n $TEST... " $N -(sleep 1; kill -$SIG $(cat "$tpp")) & +(sleep 1; kill -"$SIG" "$(cat "$tpp")") & # a simple "system:echo $PPID..." does not work on NetBSD, OpenBSD #$SOCAT $opts echo system:'exec /bin/bash -c "echo \$PPID '">$tpp"'; echo \$$ '">$tp; read x\"",nofork 2>"$te"; stat=$? tsh="$td/test$N.sh" @@ -5699,7 +6039,7 @@ else numFAIL=$((numFAIL+1)) fi wait -fi ;; # feat +fi ;; # NUMCOND, feats esac N=$((N+1)) done @@ -5710,7 +6050,8 @@ NAME=READBYTES case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: restrict reading from file with bytes option" -if false; then +if ! eval $NUMCOND; then :; +elif false; then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -5719,7 +6060,7 @@ ti="$td/test$N.in" to="$td/test$N.out" te="$td/test$N.err" tdiff="$td/test$N.diff" -da="$(date)" da="$da$($ECHO '\r')" +da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # the feature that we really want to test is in the readline.sh script: CMD="$SOCAT $opts -u open:$ti,readbytes=100 -" printf "test $F_n $TEST... " $N @@ -5742,7 +6083,7 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -5751,9 +6092,7 @@ NAME=UNIXLISTENFORK case "$TESTS" in *%functions%*|*%unix%*|*%listen%*|*%fork%*|*%$NAME%*) TEST="$NAME: UNIX socket keeps listening after child died" -if false; then - : -else +if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" @@ -5800,7 +6139,7 @@ else fi # !( $? -ne 0) fi # !(rc -ne 0) wait -fi # true +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -5809,9 +6148,7 @@ NAME=UNIXTOSTREAM case "$TESTS" in *%functions%*|*%unix%*|*%listen%*|*%$NAME%*) TEST="$NAME: generic UNIX client connects to stream socket" -if false; then - : -else +if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" @@ -5843,8 +6180,7 @@ else numOK=$((numOK+1)) fi # !(rc -ne 0) wait -fi # true -wait +fi ;; # NUMCOND esac N=$((N+1)) @@ -5853,9 +6189,7 @@ NAME=UNIXTODGRAM case "$TESTS" in *%functions%*|*%unix%*|*%recv%*|*%$NAME%*) TEST="$NAME: generic UNIX client connects to datagram socket" -if false; then - : -else +if ! eval $NUMCOND; then :; else ts1="$td/test$N.socket1" ts2="$td/test$N.socket2" tf="$td/test$N.stdout" @@ -5894,16 +6228,38 @@ else numOK=$((numOK+1)) fi # !(rc -ne 0) wait -fi # true +fi ;; # NUMCOND esac N=$((N+1)) +# there was an error in address EXEC with options pipes,stderr NAME=EXECPIPESSTDERR case "$TESTS" in *%functions%*|*%$NAME%*) TEST="$NAME: simple echo via exec of cat with pipes,stderr" +# this test is known to fail when logging is enabled with OPTS/opts env var. +SAVE_opts="$opts" +opts="$(echo "$opts" |sed 's/-d//g')" testecho "$N" "$TEST" "" "exec:$CAT,pipes,stderr" "$opts" +opts="$SAVE_opts" +esac +N=$((N+1)) + +# EXEC and SYSTEM with stderr injected socat messages into the data stream. +NAME=EXECSTDERRLOG +case "$TESTS" in +*%functions%*|*%$NAME%*) +TEST="$NAME: simple echo via exec of cat with pipes,stderr" +SAVE_opts="$opts" +# make sure at least two -d are there +case "$opts" in +*-d*-d*) ;; +*-d*) opts="$opts -d" ;; +*) opts="-d -d" ;; +esac +testecho "$N" "$TEST" "" "exec:$CAT,pipes,stderr" "$opts" +opts="$SAVE_opts" esac N=$((N+1)) @@ -5921,6 +6277,7 @@ NAME=FULLPARSE case "$TESTS" in *%functions%*|*%parse%*|*%$NAME%*) TEST="$NAME: correctly parse special chars" +if ! eval $NUMCOND; then :; else $PRINTF "test $F_n $TEST... " $N tf="$td/test$N.stdout" te="$td/test$N.stderr" @@ -5948,6 +6305,7 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi +fi ;; # NUMCOND esac N=$((N+1)) @@ -5972,7 +6330,8 @@ NAME=TCP6BYTCP4 case "$TESTS" in *%functions%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: TCP4 mapped into TCP6 address space" -if ! testaddrs tcp ip6 >/dev/null || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testaddrs tcp ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -5981,7 +6340,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts TCP6-listen:$tsl,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP6:$ts" printf "test $F_n $TEST... " $N @@ -6006,16 +6365,20 @@ else numOK=$((numOK+1)) fi kill $pid 2>/dev/null; wait -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) +# test the UDP4-SENDTO and UDP4-RECVFROM addresses together NAME=UDP4DGRAM case "$TESTS" in *%functions%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%$NAME%*) -TEST="$NAME: UDP/IPv4 datagram" +TEST="$NAME: UDP/IPv4 sendto and recvfrom" +# start a UDP4-RECVFROM process that echoes data, and send test data using +# UDP4-SENDTO. The sent data should be returned. +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" @@ -6024,7 +6387,7 @@ ts1a="127.0.0.1" ts1="$ts1a:$ts1p" ts2p=$PORT; PORT=$((PORT+1)) ts2="127.0.0.1:$ts2p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts UDP4-RECVFROM:$ts1p,reuseaddr,bind=$ts1a PIPE" CMD2="$SOCAT $opts - UDP4-SENDTO:$ts1,bind=$ts2" printf "test $F_n $TEST... " $N @@ -6037,23 +6400,25 @@ kill "$pid1" 2>/dev/null; wait; if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $SOCAT:\n" echo "$CMD1 &" - echo "$CMD2" cat "${te}1" + echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" echo "$CMD1 &" - echo "$CMD2" cat "${te}1" + echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) -fi ;; +fi +fi # NUMCOND + ;; esac PORT=$((PORT+1)) N=$((N+1)) @@ -6063,7 +6428,8 @@ NAME=UDP6DGRAM case "$TESTS" in *%functions%*|*%udp%*|*%udp6%*|*%ip6%*|*%dgram%*|*%$NAME%*) TEST="$NAME: UDP/IPv6 datagram" -if ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6075,7 +6441,7 @@ tsa="[::1]" ts1="$tsa:$ts1p" ts2p=$PORT; PORT=$((PORT+1)) ts2="$tsa:$ts2p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts UDP6-RECVFROM:$ts1p,reuseaddr,bind=$tsa PIPE" CMD2="$SOCAT $opts - UDP6-SENDTO:$ts1,bind=$ts2" printf "test $F_n $TEST... " $N @@ -6098,7 +6464,7 @@ else if [ -n "$debug" ]; then cat ${te}1 ${te}2; fi numOK=$((numOK+1)) fi -fi ;; # ! feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6108,7 +6474,8 @@ NAME=RAWIP4RECVFROM case "$TESTS" in *%functions%*|*%ip%*|*%ip4%*|*%rawip%*|*%rawip4%*|*%dgram%*|*%root%*|*%$NAME%*) TEST="$NAME: raw IPv4 datagram" -if [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then +if ! eval $NUMCOND; then :; +elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6120,7 +6487,7 @@ ts1a="127.0.0.1" ts1="$ts1a:$ts1p" ts2a="$SECONDADDR" ts2="$ts2a:$ts2p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts IP4-RECVFROM:$ts1p,reuseaddr,bind=$ts1a PIPE" CMD2="$SOCAT $opts - IP4-SENDTO:$ts1,bind=$ts2a" printf "test $F_n $TEST... " $N @@ -6146,9 +6513,8 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi # must be root;; +fi ;; # root, NUMCOND esac -PORT=$((PORT+1)) N=$((N+1)) @@ -6157,7 +6523,8 @@ NAME=RAWIP6RECVFROM case "$TESTS" in *%functions%*|*%ip%*|*%ip6%*|*%rawip%*|*%rawip6%*|*%dgram%*|*%root%*|*%$NAME%*) TEST="$NAME: raw IPv6 datagram by self addressing" -if ! feat=$(testaddrs ip6 rawip) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip6 rawip) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -6171,7 +6538,7 @@ ts1p=$PROTO; PROTO=$((PROTO+1)) tsa="[::1]" ts1="$tsa:$ts1p" ts2="$tsa" -da=$(date) +da="test$N $(date) $RANDOM" #CMD1="$SOCAT $opts IP6-RECVFROM:$ts1p,reuseaddr,bind=$tsa PIPE" CMD2="$SOCAT $opts - IP6-SENDTO:$ts1,bind=$ts2" printf "test $F_n $TEST... " $N @@ -6194,9 +6561,8 @@ else if [ -n "$debug" ]; then cat "$te"; fi numOK=$((numOK+1)) fi -fi # must be root ;; +fi ;; # root, NUMCOND esac -PORT=$((PORT+1)) N=$((N+1)) fi #false @@ -6205,12 +6571,13 @@ NAME=UNIXDGRAM case "$TESTS" in *%functions%*|*%unix%*|*%dgram%*|*%$NAME%*) TEST="$NAME: UNIX datagram" +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1="$td/test$N.socket1" ts2="$td/test$N.socket2" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts UNIX-RECVFROM:$ts1,reuseaddr PIPE" CMD2="$SOCAT $opts - UNIX-SENDTO:$ts1,bind=$ts2" printf "test $F_n $TEST... " $N @@ -6235,9 +6602,10 @@ else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) -fi ;; +fi +fi # NUMCOND + ;; esac -PORT=$((PORT+1)) N=$((N+1)) @@ -6245,13 +6613,14 @@ NAME=UDP4RECV case "$TESTS" in *%functions%*|*%ip4%*|*%dgram%*|*%udp%*|*%udp4%*|*%recv%*|*%$NAME%*) TEST="$NAME: UDP/IPv4 receive" +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) ts1a="127.0.0.1" ts1="$ts1a:$ts1p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -u UDP4-RECV:$ts1p,reuseaddr -" CMD2="$SOCAT $opts -u - UDP4-SENDTO:$ts1" printf "test $F_n $TEST... " $N @@ -6282,9 +6651,10 @@ else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) -fi ;; +fi +fi # NUMCOND + ;; esac -PORT=$((PORT+1)) N=$((N+1)) @@ -6292,7 +6662,8 @@ NAME=UDP6RECV case "$TESTS" in *%functions%*|*%ip6%*|*%dgram%*|*%udp%*|*%udp6%*|*%recv%*|*%$NAME%*) TEST="$NAME: UDP/IPv6 receive" -if ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6302,7 +6673,7 @@ tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) ts1a="[::1]" ts1="$ts1a:$ts1p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -u UDP6-RECV:$ts1p,reuseaddr -" CMD2="$SOCAT $opts -u - UDP6-SENDTO:$ts1" printf "test $F_n $TEST... " $N @@ -6330,9 +6701,8 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi ;; # ! feat +fi ;; # NUMCOND, feats esac -PORT=$((PORT+1)) N=$((N+1)) @@ -6340,7 +6710,8 @@ NAME=RAWIP4RECV case "$TESTS" in *%functions%*|*%ip4%*|*%dgram%*|*%rawip%*|*%rawip4%*|*%recv%*|*%root%*|*%$NAME%*) TEST="$NAME: raw IPv4 receive" -if [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then +if ! eval $NUMCOND; then :; +elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6350,7 +6721,7 @@ tdiff="$td/test$N.diff" ts1p=$PROTO; PROTO=$((PROTO+1)) ts1a="127.0.0.1" ts1="$ts1a:$ts1p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -u IP4-RECV:$ts1p,reuseaddr -" CMD2="$SOCAT $opts -u - IP4-SENDTO:$ts1" printf "test $F_n $TEST... " $N @@ -6378,9 +6749,8 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi # must be root ;; +fi ;; # NUMCOND, root esac -PORT=$((PORT+1)) N=$((N+1)) @@ -6388,7 +6758,8 @@ NAME=RAWIP6RECV case "$TESTS" in *%functions%*|*%ip6%*|*%dgram%*|*%rawip%*|*%rawip6%*|*%recv%*|*%root%*|*%$NAME%*) TEST="$NAME: raw IPv6 receive" -if ! feat=$(testaddrs ip6 rawip) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip6 rawip) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -6401,7 +6772,7 @@ tdiff="$td/test$N.diff" ts1p=$PROTO; PROTO=$((PROTO+1)) ts1a="[::1]" ts1="$ts1a:$ts1p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -u IP6-RECV:$ts1p,reuseaddr -" CMD2="$SOCAT $opts -u - IP6-SENDTO:$ts1" printf "test $F_n $TEST... " $N @@ -6428,9 +6799,8 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi # must be root ;; +fi ;; # NUMCOND, root esac -PORT=$((PORT+1)) N=$((N+1)) @@ -6438,12 +6808,13 @@ NAME=UNIXRECV case "$TESTS" in *%functions%*|*%unix%*|*%dgram%*|*%recv%*|*%$NAME%*) TEST="$NAME: UNIX receive" +if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1="$ts" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -u UNIX-RECV:$ts1,reuseaddr -" CMD2="$SOCAT $opts -u - UNIX-SENDTO:$ts1" printf "test $F_n $TEST... " $N @@ -6469,9 +6840,10 @@ else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) -fi ;; +fi +fi # NUMCOND + ;; esac -PORT=$((PORT+1)) N=$((N+1)) @@ -6479,12 +6851,13 @@ NAME=UDP4RECVFROM_SOURCEPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECVFROM with SOURCEPORT option" -if ! feat=$(testaddrs udp ip4) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testserversec "$N" "$TEST" "$opts -s" "udp4-recvfrom:$PORT,reuseaddr" "" "sp=$PORT" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6493,12 +6866,13 @@ NAME=UDP4RECVFROM_LOWPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECVFROM with LOWPORT option" -if ! feat=$(testaddrs udp ip4) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testserversec "$N" "$TEST" "$opts -s" "udp4-recvfrom:$PORT,reuseaddr" "" "lowport" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6508,7 +6882,9 @@ case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECVFROM with RANGE option" #testserversec "$N" "$TEST" "$opts -s" "udp4-recvfrom:$PORT,reuseaddr,fork" "" "range=$SECONDADDR/32" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 +if ! eval $NUMCOND; then :; else testserversec "$N" "$TEST" "$opts -s" "udp4-recvfrom:$PORT,reuseaddr" "" "range=$SECONDADDR/32" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -6517,7 +6893,8 @@ NAME=UDP4RECVFROM_TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECVFROM with TCPWRAP option" -if ! feat=$(testaddrs ip4 udp libwrap) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 udp libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6527,7 +6904,7 @@ $ECHO "socat: $SECONDADDR" >"$ha" $ECHO "ALL: ALL" >"$hd" #testserversec "$N" "$TEST" "$opts -s" "udp4-recvfrom:$PORT,reuseaddr,fork" "" "tcpwrap=$d" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 testserversec "$N" "$TEST" "$opts -s" "udp4-recvfrom:$PORT,reuseaddr" "" "tcpwrap-etc=$td" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 -fi ;; # feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6537,7 +6914,8 @@ NAME=UDP4RECV_SOURCEPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECV with SOURCEPORT option" -if ! feat=$(testaddrs udp ip4) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6547,7 +6925,7 @@ PORT3=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -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 ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6556,7 +6934,8 @@ NAME=UDP4RECV_LOWPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECV with LOWPORT option" -if ! feat=$(testaddrs udp ip4) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6565,7 +6944,7 @@ PORT2=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -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 ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6574,7 +6953,8 @@ NAME=UDP4RECV_RANGE case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECV with RANGE option" -if ! feat=$(testaddrs udp ip4) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6583,7 +6963,7 @@ PORT2=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -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 ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6592,7 +6972,8 @@ NAME=UDP4RECV_TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECV with TCPWRAP option" -if ! feat=$(testaddrs udp ip4 libwrap) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip4 libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6605,7 +6986,7 @@ $ECHO "ALL: ALL" >"$hd" # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -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 ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6615,12 +6996,13 @@ NAME=UDP6RECVFROM_SOURCEPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECVFROM with SOURCEPORT option" -if ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testserversec "$N" "$TEST" "$opts -s" "udp6-recvfrom:$PORT,reuseaddr" "" "sp=$PORT" "udp6-sendto:[::1]:$PORT" 6 udp $PORT 0 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6629,12 +7011,13 @@ NAME=UDP6RECVFROM_LOWPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECVFROM with LOWPORT option" -if ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testserversec "$N" "$TEST" "$opts -s" "udp6-recvfrom:$PORT,reuseaddr" "" "lowport" "udp6-sendto:[::1]:$PORT" 6 udp $PORT 0 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6643,13 +7026,14 @@ NAME=UDP6RECVFROM_RANGE case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECVFROM with RANGE option" -if ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else #testserversec "$N" "$TEST" "$opts -s" "udp6-recvfrom:$PORT,reuseaddr,fork" "" "range=[::2/128]" "udp6-sendto:[::1]:$PORT" 6 udp $PORT 0 testserversec "$N" "$TEST" "$opts -s" "udp6-recvfrom:$PORT,reuseaddr" "" "range=[::2/128]" "udp6-sendto:[::1]:$PORT" 6 udp $PORT 0 -fi # ! feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6658,7 +7042,8 @@ NAME=UDP6RECVFROM_TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECVFROM with TCPWRAP option" -if ! feat=$(testaddrs udp ip6 libwrap) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip6 libwrap) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6667,7 +7052,7 @@ hd="$td/hosts.deny" $ECHO "socat: [::2]" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts -s" "udp6-recvfrom:$PORT,reuseaddr" "" "tcpwrap-etc=$td" "udp6-sendto:[::1]:$PORT" 6 udp $PORT 0 -fi ;; # feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6677,7 +7062,8 @@ NAME=UDP6RECV_SOURCEPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECV with SOURCEPORT option" -if ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6687,7 +7073,7 @@ PORT3=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -s" "udp6-sendto:[::1]:$PORT2%udp6-recv:$PORT1,reuseaddr" "" "sp=$PORT3" "udp6-sendto:[::1]:$PORT1%udp6-recv:$PORT2" 6 udp $PORT1 0 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6696,7 +7082,8 @@ NAME=UDP6RECV_LOWPORT case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECV with LOWPORT option" -if ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6705,7 +7092,7 @@ PORT2=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -s" "udp6-sendto:[::1]:$PORT2%udp6-recv:$PORT1,reuseaddr" "" "lowport" "udp6-sendto:[::1]:$PORT1%udp6-recv:$PORT2" 6 udp $PORT1 0 -fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6714,7 +7101,8 @@ NAME=UDP6RECV_RANGE case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECV with RANGE option" -if ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6723,7 +7111,7 @@ PORT2=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -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 ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6732,7 +7120,8 @@ NAME=UDP6RECV_TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECV with TCPWRAP option" -if ! feat=$(testaddrs udp ip6 libwrap) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip6 libwrap) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -6745,7 +7134,7 @@ PORT2=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -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 ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -6755,7 +7144,8 @@ NAME=IP4RECVFROM_RANGE case "$TESTS" in *%functions%*|*%security%*|*%ip%*|*%ip4%*|*%range%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP4-RECVFROM with RANGE option" -if ! feat=$(testaddrs ip4 rawip) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 rawip) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -6764,7 +7154,7 @@ elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then 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" "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 ;; # NUMCOND, feats, root esac PROTO=$((PROTO+1)) PORT=$((PORT+1)) @@ -6774,7 +7164,8 @@ NAME=IP4RECVFROM_TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%ip%*|*%ip4%*|*%tcpwrap%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP4-RECVFROM with TCPWRAP option" -if ! feat=$(testaddrs ip4 rawip libwrap) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 rawip libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -6787,7 +7178,8 @@ $ECHO "socat: $SECONDADDR" >"$ha" $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" "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 # NUMCOND, feats, root + ;; esac PROTO=$((PROTO+1)) PORT=$((PORT+1)) @@ -6798,7 +7190,8 @@ NAME=IP4RECV_RANGE case "$TESTS" in *%functions%*|*%security%*|*%ip%*|*%ip4%*|*%range%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP4-RECV with RANGE option" -if ! feat=$(testaddrs ip4 rawip) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 rawip) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -6810,18 +7203,18 @@ PROTO2=$PROTO # we use the forward channel (PROTO1) for testing, and have a backward channel # (PROTO2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -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 ;; # NUMCOND, feats, root esac PROTO=$((PROTO+1)) N=$((N+1)) - NAME=IP4RECV_TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%ip%*|*%ip4%*|*%tcpwrap%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP4-RECV with TCPWRAP option" -if ! feat=$(testaddrs ip4 rawip libwrap) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 rawip libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -6837,7 +7230,7 @@ $ECHO "ALL: ALL" >"$hd" # we use the forward channel (PROTO1) for testing, and have a backward channel # (PROTO2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -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 ;; # NUMCOND, feats, root esac PROTO=$((PROTO+1)) N=$((N+1)) @@ -6847,7 +7240,8 @@ NAME=IP6RECVFROM_RANGE case "$TESTS" in *%functions%*|*%security%*|*%ip%*|*%ip6%*|*%range%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP6-RECVFROM with RANGE option" -if ! feat=$(testaddrs ip6 rawip) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip6 rawip) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -6856,7 +7250,7 @@ elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then 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" "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 ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) PORT=$((PORT+1)) @@ -6866,7 +7260,8 @@ NAME=IP6RECVFROM_TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%ip%*|*%ip6%*|*%tcpwrap%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP6-RECVFROM with TCPWRAP option" -if ! feat=$(testaddrs ip6 rawip libwrap) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip6 rawip libwrap) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -6879,7 +7274,7 @@ $ECHO "socat: [::2]" >"$ha" $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" "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 ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) PORT=$((PORT+1)) @@ -6890,7 +7285,8 @@ NAME=IP6RECV_RANGE case "$TESTS" in *%functions%*|*%security%*|*%ip%*|*%ip6%*|*%range%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP6-RECV with RANGE option" -if ! feat=$(testaddrs ip6 rawip) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip6 rawip) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}raw IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -6902,7 +7298,7 @@ PROTO2=$PROTO # we use the forward channel (PROTO1) for testing, and have a backward channel # (PROTO2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -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 ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) N=$((N+1)) @@ -6911,7 +7307,8 @@ NAME=IP6RECV_TCPWRAP case "$TESTS" in *%functions%*|*%security%*|*%ip%*|*%ip6%*|*%tcpwrap%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP6-RECV with TCPWRAP option" -if ! feat=$(testaddrs ip6 rawip libwrap) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip6 rawip libwrap) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -6927,7 +7324,7 @@ $ECHO "ALL: ALL" >"$hd" # we use the forward channel (PROTO1) for testing, and have a backward channel # (PROTO2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts -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 ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) N=$((N+1)) @@ -6941,14 +7338,15 @@ TEST="$NAME: option O_NOATIME on file" # without this option (using touch); one second later read from the first file. # Then we check which file has the later ATIME stamp. For this check we use # "ls -ltu" because it is more portable than "test ... -nt ..." -if ! testoptions o-noatime >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testoptions o-noatime >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}o-noatime not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else tf="$td/test$N.file" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" $PRINTF "test $F_n $TEST... " $N CMD="$SOCAT $opts -u open:\"${tf}1\",o-noatime /dev/null" # generate a file @@ -6978,7 +7376,7 @@ else numOK=$((numOK+1)) fi # wrong time stamps fi # command ok -fi ;; # not feats +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -6990,14 +7388,15 @@ TEST="$NAME: option O_NOATIME on file descriptor" # without this option (using touch); one second later read from the first file. # Then we check which file has the later ATIME stamp. For this check we use # "ls -ltu" because it is more portable than "test ... -nt ..." -if ! testoptions o-noatime >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testoptions o-noatime >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}o-noatime not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else tf="$td/test$N.file" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da=$(date) +da="test$N $(date) $RANDOM" $PRINTF "test $F_n $TEST... " $N touch ${tf}1 CMD="$SOCAT $opts -u -,o-noatime /dev/null <${tf}1" @@ -7028,7 +7427,7 @@ else numOK=$((numOK+1)) fi # wrong time stamps fi # command ok -fi ;; # not feats +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -7040,7 +7439,8 @@ TEST="$NAME: extended file system options using ext2fs noatime option" # without this option (using touch); one second later read from the first file. # Then we check which file has the later ATIME stamp. For this check we use # "ls -ltu" because it is more portable than "test ... -nt ..." -if ! testoptions ext2-noatime >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testoptions ext2-noatime >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}ext2-noatime not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -7049,7 +7449,7 @@ tf="$td/test$N.file" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1="$ts" -da=$(date) +da="test$N $(date) $RANDOM" $PRINTF "test $F_n $TEST... " $N CMD0="$SOCAT $opts -u /dev/null create:\"${tf}1\"" CMD="$SOCAT $opts -u /dev/null create:\"${tf}1\",ext2-noatime" @@ -7088,7 +7488,7 @@ else fi fi # not impotent fi # can test -fi ;; # not feats +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -7097,7 +7497,8 @@ NAME=COOLWRITE case "$TESTS" in *%functions%*|*%timeout%*|*%ignoreeof%*|*%coolwrite%*|*%$NAME%*) TEST="$NAME: option cool-write" -if ! testoptions cool-write >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testoptions cool-write >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}option cool-write not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -7106,7 +7507,7 @@ ti="$td/test$N.pipe" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date) $RANDOM" +da="test$N $(date) $RANDOM" # a reader that will terminate after 1 byte CMD1="$SOCAT $opts -u pipe:\"$ti\",readbytes=1 /dev/null" CMD="$SOCAT $opts -u - file:\"$ti\",cool-write" @@ -7127,7 +7528,7 @@ else if [ -n "$debug" ]; then cat "$te"; fi numOK=$((numOK+1)) fi -fi # testoptions +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -7144,7 +7545,8 @@ TEST="$NAME: option cool-write on bidirectional stdio" # byte. The last write will fail with "broken pipe"; if option coolwrite # has been applied successfully, socat will terminate with 0 (OK), # otherwise with error. -if ! testoptions cool-write >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! testoptions cool-write >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}option cool-write not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -7153,7 +7555,7 @@ ti="$td/test$N.pipe" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date) $RANDOM" +da="test$N $(date) $RANDOM" # a reader that will terminate after 1 byte CMD1="$SOCAT $opts -u pipe:\"$ti\",readbytes=1 /dev/null" CMD="$SOCAT $opts -,cool-write pipe >\"$ti\"" @@ -7174,7 +7576,7 @@ else if [ -n "$debug" ]; then cat "$te"; fi numOK=$((numOK+1)) fi -fi # testoptions +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -7200,6 +7602,7 @@ TEST="$NAME: shut-none keeps TCP V4 socket open" # 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. +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" @@ -7228,7 +7631,7 @@ if [ $? -ne 0 ]; then echo "$CMD2" cat "${te}1a" "${te}1b" "${te}2" "${te}3" numFAIL=$((numFAIL+1)) -elif ! echo -e "$da1a\n$da1b" |diff - "$tf" >"$tdiff"; then +elif ! $ECHO "$da1a\n$da1b" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" cat "${te}1a" "${te}1b" "${te}2" "${te}3" @@ -7237,7 +7640,8 @@ else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1a" "${te}1b" "${te}2" "${te}3"; fi numOK=$((numOK+1)) -fi ;; +fi +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -7247,7 +7651,7 @@ N=$((N+1)) NAME=EXECENDCLOSE case "$TESTS" in *%functions%*|*%exec%*|*%$NAME%*) -TEST="$NAME: shut-none keeps EXEC child running" +TEST="$NAME: end-close 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 @@ -7257,6 +7661,7 @@ TEST="$NAME: shut-none keeps EXEC child running" # 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. +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" ts="$td/test$N.sock" @@ -7270,9 +7675,9 @@ $CMD 2>"${te}2" & pid2=$! waitfile $ts 1 echo "$da1a" |$CMD1 2>>"${te}1a" >"$tf" -usleep 100000 +usleep $MICROS echo "$da1b" |$CMD1 2>>"${te}1b" >>"$tf" -usleep 100000 +#usleep $MICROS kill "$pid2" 2>/dev/null wait if [ $? -ne 0 ]; then @@ -7281,7 +7686,7 @@ if [ $? -ne 0 ]; then echo "$CMD" cat "${te}1a" "${te}1b" "${te}2" numFAIL=$((numFAIL+1)) -elif ! echo -e "$da1a\n$da1b" |diff - "$tf" >"$tdiff"; then +elif ! $ECHO "$da1a\n$da1b" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" echo "$CMD1 &" echo "$CMD" @@ -7292,34 +7697,20 @@ else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1a" "${te}1b" "${te}2"; fi numOK=$((numOK+1)) -fi ;; +fi +fi ;; # NUMCOND esac -PORT=$((PORT+1)) -N=$((N+1)) - - -NAME=TCP4RANGEMASK -case "$TESTS" in -*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) -TEST="$NAME: security of TCP4-L with RANGE option" -if [ "$UNAME" != Linux ]; then - $PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N - numCANT=$((numCANT+1)) -else -testserversec "$N" "$TEST" "$opts -s" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=127.0.0.0:255.255.0.0" "tcp4:127.1.0.0:$PORT" 4 tcp $PORT 0 -fi ;; # Linux -esac -PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6LISTENBIND # this tests for a bug in (up to) 1.5.0.0: -# with upd*-listen, the bind option supported only IPv4 +# with udp*-listen, the bind option supported only IPv4 case "$TESTS" in *%functions%*|*%bugs%*|*%ip6%*|*%ipapp%*|*%udp%*|*%$NAME%*) TEST="$NAME: UDP6-LISTEN with bind" -if ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -7328,7 +7719,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="$LOCALHOST6:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts UDP6-LISTEN:$tsl,reuseaddr,bind=$LOCALHOST6 PIPE" CMD2="$SOCAT $opts - UDP6:$ts" printf "test $F_n $TEST... " $N @@ -7353,7 +7744,7 @@ else if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi -fi ;; # ! testaddrs +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -7365,17 +7756,18 @@ NAME=TCPWRAPPERS_MULTIOPTS case "$TESTS" in *%functions%*|*%bugs%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: use of multiple tcpwrapper enabling options" -if ! feat=$(testaddrs tcp ip4 libwrap) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip4 libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date) $RANDOM" +da="test$N $(date) $RANDOM" ha="$td/hosts.allow" $ECHO "test : ALL : allow" >"$ha" -CMD1="$SOCAT $opts TCP4-LISTEN:$PORT,reuseaddr,hosts-allow=$a,tcpwrap=test pipe" +CMD1="$SOCAT $opts TCP4-LISTEN:$PORT,reuseaddr,hosts-allow=$ha,tcpwrap=test pipe" CMD2="$SOCAT $opts - TCP:$LOCALHOST:$PORT" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & @@ -7397,7 +7789,7 @@ else if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi -fi ;; # feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -7409,14 +7801,15 @@ NAME=TCPWRAPPERS_TCP6ADDR case "$TESTS" in *%functions%*|*%bugs%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: specification of TCP6 address in hosts.allow" -if ! feat=$(testaddrs tcp ip6 libwrap) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs tcp ip6 libwrap) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" -da="$(date) $RANDOM" +da="test$N $(date) $RANDOM" ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat : [::1] : allow" >"$ha" @@ -7445,7 +7838,7 @@ else if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi -fi ;; # feat +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -7455,8 +7848,10 @@ NAME=UDP4BROADCAST case "$TESTS" in *%functions%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%broadcast%*|*%$NAME%*) TEST="$NAME: UDP/IPv4 broadcast" -if [ -z "$BCADDR" ]; then +if ! eval $NUMCOND; then :; +elif [ -z "$BCADDR" ]; then $PRINTF "test $F_n $TEST... ${YELLOW}dont know a broadcast address${NORMAL}\n" $N + numCANT=$((numCANT+1)) else tf="$td/test$N.stdout" te="$td/test$N.stderr" @@ -7466,7 +7861,7 @@ ts1p=$PORT; PORT=$((PORT+1)) ts1="$BCADDR:$ts1p" ts2p=$PORT; PORT=$((PORT+1)) ts2="$BCIFADDR:$ts2p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts UDP4-RECVFROM:$ts1p,reuseaddr,broadcast PIPE" #CMD2="$SOCAT $opts - UDP4-BROADCAST:$ts1" CMD2="$SOCAT $opts - UDP4-DATAGRAM:$ts1,broadcast" @@ -7497,9 +7892,8 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi ;; # feats +fi ;; # NUMCOND, feats esac -PORT=$((PORT+1)) N=$((N+1)) @@ -7510,7 +7904,8 @@ NAME=IP4BROADCAST case "$TESTS" in *%functions%*|*%rawip%*|*%rawip4%*|*%ip4%*|*%dgram%*|*%broadcast%*|*%root%*|*%$NAME%*) TEST="$NAME: raw IPv4 broadcast" -if ! feat=$(testaddrs ip4 rawip) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 rawip) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}raw IP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -7527,7 +7922,7 @@ ts1p=$PROTO ts1="$BCADDR:$ts1p" ts2p=$ts1p ts2="$BCIFADDR" -da="$(date) $RANDOM XXXX" +da="test$N $(date) $RANDOM XXXX" sh="$td/test$N-sed.sh" echo 'sed s/XXXX/YYYY/' >"$sh" chmod a+x "$sh" @@ -7557,7 +7952,7 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi ;; # not feats, not root +fi ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) N=$((N+1)) @@ -7567,11 +7962,12 @@ N=$((N+1)) #case "$TESTS" in #*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%broadcast%*|*%range%*|*%$NAME%*) #TEST="$NAME: security of UDP4-BROADCAST with RANGE option" -#if [ -z "$BCADDR" ]; then +#if ! eval $NUMCOND; then :; +#elif [ -z "$BCADDR" ]; then # $PRINTF "test $F_n $TEST... ${YELLOW}dont know a broadcast address${NORMAL}\n" $N #else #testserversec "$N" "$TEST" "$opts -s" "UDP4-BROADCAST:$BCADDR/8:$PORT" "" "range=127.1.0.0:255.255.0.0" "udp4:127.1.0.0:$PORT" 4 udp $PORT 0 -#fi ;; # feats +#fi ;; # NUMCOND, feats #esac #PORT=$((PORT+1)) #N=$((N+1)) @@ -7581,7 +7977,8 @@ NAME=UDP4MULTICAST_UNIDIR case "$TESTS" in *%functions%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%multicast%*|*%$NAME%*) TEST="$NAME: UDP/IPv4 multicast, send only" -if ! feat=$(testaddrs ip4 udp) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 udp) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -7591,7 +7988,7 @@ tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) ts1a="$SECONDADDR" ts1="$ts1a:$ts1p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT -u $opts UDP4-RECV:$ts1p,reuseaddr,ip-add-membership=224.255.255.254:$ts1a -" CMD2="$SOCAT -u $opts - UDP4-SENDTO:224.255.255.254:$ts1p,bind=$ts1a" printf "test $F_n $TEST... " $N @@ -7618,16 +8015,16 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi ;; # not feats +fi ;; # NUMCOND, feats esac -PORT=$((PORT+1)) N=$((N+1)) NAME=IP4MULTICAST_UNIDIR case "$TESTS" in *%functions%*|*%rawip%*|*%ip4%*|*%dgram%*|*%multicast%*|*%root%*|*%$NAME%*) TEST="$NAME: IPv4 multicast" -if ! feat=$(testaddrs ip4 rawip) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 rawip) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -7640,7 +8037,7 @@ tdiff="$td/test$N.diff" ts1p=$PROTO ts1a="$SECONDADDR" ts1="$ts1a:$ts1p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT -u $opts IP4-RECV:$ts1p,reuseaddr,ip-add-membership=224.255.255.254:$ts1a -" CMD2="$SOCAT -u $opts - IP4-SENDTO:224.255.255.254:$ts1p,bind=$ts1a" printf "test $F_n $TEST... " $N @@ -7668,7 +8065,7 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi ;; # not feats, not root +fi ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) N=$((N+1)) @@ -7678,7 +8075,8 @@ NAME=UDP6MULTICAST_UNIDIR case "$TESTS" in *%functions%*|*%udp%*|*%udp6%*|*%ip6%*|*%dgram%*|*%multicast%*|*%$NAME%*) TEST="$NAME: UDP/IPv6 multicast" -if ! feat=$(testaddrs ip6 udp) || ! runsip6 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip6 udp) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -7688,7 +8086,7 @@ tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) if1="$MCINTERFACE" ts1a="[::1]" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT -u $opts UDP6-RECV:$ts1p,reuseaddr,ipv6-join-group=[ff02::2]:$if1 -" CMD2="$SOCAT -u $opts - UDP6-SENDTO:[ff02::2]:$ts1p,bind=$ts1a" printf "test $F_n $TEST... " $N @@ -7715,9 +8113,8 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi ;; # not feats +fi ;; # NUMCOND, feats esac -PORT=$((PORT+1)) N=$((N+1)) fi # false @@ -7725,6 +8122,7 @@ NAME=UDP4MULTICAST_BIDIR case "$TESTS" in *%functions%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%multicast%*|*%$NAME%*) TEST="$NAME: UDP/IPv4 multicast, with reply" +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" @@ -7733,7 +8131,7 @@ ts1a="$SECONDADDR" ts1="$ts1a:$ts1p" ts2p=$PORT; PORT=$((PORT+1)) ts2="$BCIFADDR:$ts2p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts UDP4-RECVFROM:$ts1p,reuseaddr,ip-add-membership=224.255.255.254:$ts1a PIPE" #CMD2="$SOCAT $opts - UDP4-MULTICAST:224.255.255.254:$ts1p,bind=$ts1a" CMD2="$SOCAT $opts - UDP4-DATAGRAM:224.255.255.254:$ts1p,bind=$ts1a" @@ -7763,16 +8161,17 @@ else fi if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) -fi ;; +fi +fi ;; # NUMCOND esac -PORT=$((PORT+1)) N=$((N+1)) NAME=IP4MULTICAST_BIDIR case "$TESTS" in *%functions%*|*%rawip%*|*%ip4%*|*%dgram%*|*%multicast%*|*%root%*|*%$NAME%*) TEST="$NAME: IPv4 multicast, with reply" -if ! feat=$(testaddrs ip4 rawip) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 rawip) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -7785,7 +8184,7 @@ tdiff="$td/test$N.diff" ts1p=$PROTO ts1a="$SECONDADDR" ts1="$ts1a:$ts1p" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts IP4-RECVFROM:$ts1p,reuseaddr,ip-add-membership=224.255.255.254:$ts1a PIPE" #CMD2="$SOCAT $opts - IP4-MULTICAST:224.255.255.254:$ts1p,bind=$ts1a" CMD2="$SOCAT $opts - IP4-DATAGRAM:224.255.255.254:$ts1p,bind=$ts1a" @@ -7793,6 +8192,7 @@ printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid1="$!" waitip4port $ts1p 1 +usleep 100000 # give process a chance to add multicast membership echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2="$?" kill "$pid1" 2>/dev/null; wait; @@ -7816,7 +8216,7 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi ;; # not feats, not root +fi ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) N=$((N+1)) @@ -7829,7 +8229,8 @@ TEST="$NAME: reading data sent through tun interface" #idea: create a TUN interface and send a datagram to one of the addresses of # its virtual network. On the tunnel side, read the packet and compare its last # bytes with the datagram payload -if ! feat=$(testaddrs ip4 tun) || ! runsip4 >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 tun) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then @@ -7840,7 +8241,7 @@ tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tl="$td/test$N.lock" -da="$(date) $RANDOM" +da="test$N $(date) $RANDOM" dalen=$((${#da}+1)) TUNNET=10.255.255 CMD1="$SOCAT $opts -u - UDP4-SENDTO:$TUNNET.2:$PORT" @@ -7869,7 +8270,63 @@ else if [ -n "$debug" ]; then cat "${te}" "${te}1"; fi numOK=$((numOK+1)) fi -fi ;; # not feats, not root +fi ;; # NUMCOND, feats +esac +PORT=$((PORT+1)) +N=$((N+1)) + + +# use the INTERFACE address on a tun/tap device and transfer data fully +# transparent +NAME=TUNINTERFACE +case "$TESTS" in +*%functions%*|*%tun%*|*%interface%*|*%root%*|*%$NAME%*) +TEST="$NAME: pass data through tun interface using INTERFACE" +#idea: create a TUN interface and send a raw packet on the interface side. +# It should arrive unmodified on the tunnel side. +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs ip4 tun interface) || ! runsip4 >/dev/null; then + $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N + numCANT=$((numCANT+1)) +elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then + $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +tl="$td/test$N.lock" +da="$(date) $RANDOM" +dalen=$((${#da}+1)) +TUNNET=10.255.255 +TUNNAME=tun9 +CMD1="$SOCAT $opts -L $tl TUN:$TUNNET.1/24,iff-up=1,tun-type=tun,tun-name=$TUNNAME echo" +CMD="$SOCAT $opts - INTERFACE:$TUNNAME" +printf "test $F_n $TEST... " $N +$CMD1 2>"${te}1" & +pid1="$!" +#waitinterface "$TUNNAME" +sleep 1 +echo "$da" |$CMD 2>"${te}1" >"$tf" 2>"${te}" +kill $pid1 2>/dev/null +wait +if [ $? -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD &" + echo "$CMD1" + cat "${te}" "${te}1" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + cat "${te}" "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat "${te}" "${te}1"; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) @@ -7879,7 +8336,8 @@ NAME=ABSTRACTSTREAM case "$TESTS" in *%functions%*|*%unix%*|*%abstract%*|*%connect%*|*%listen%*|*%$NAME%*) TEST="$NAME: abstract UNIX stream socket, listen and connect" -if ! feat=$(testaddrs abstract-unixsocket); then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs abstract-unixsocket); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -7922,7 +8380,7 @@ else numOK=$((numOK+1)) fi # !(rc -ne 0) wait -fi ;; # not feats +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -7931,7 +8389,8 @@ NAME=ABSTRACTDGRAM case "$TESTS" in *%functions%*|*%unix%*|*%abstract%*|*%dgram%*|*%$NAME%*) TEST="$NAME: abstract UNIX datagram" -if ! feat=$(testaddrs abstract-unixsocket); then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs abstract-unixsocket); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -7940,7 +8399,7 @@ te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1="$td/test$N.socket1" ts2="$td/test$N.socket2" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts ABSTRACT-RECVFROM:$ts1,reuseaddr PIPE" #CMD2="$SOCAT $opts - ABSTRACT-SENDTO:$ts1,bind=$ts2" CMD2="$SOCAT $opts - ABSTRACT-SENDTO:$ts1,bind=$ts2" @@ -7968,9 +8427,8 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi ;; # not feats +fi ;; # NUMCOND, feats esac -PORT=$((PORT+1)) N=$((N+1)) @@ -7978,7 +8436,8 @@ NAME=ABSTRACTRECV case "$TESTS" in *%functions%*|*%unix%*|*%abstract%*|*%dgram%*|*%recv%*|*%$NAME%*) TEST="$NAME: abstract UNIX datagram receive" -if ! feat=$(testaddrs abstract-unixsocket); then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs abstract-unixsocket); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -7987,7 +8446,7 @@ tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1="$ts" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -u ABSTRACT-RECV:$ts1,reuseaddr -" CMD2="$SOCAT $opts -u - ABSTRACT-SENDTO:$ts1" printf "test $F_n $TEST... " $N @@ -8016,9 +8475,8 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi ;; # not feats +fi ;; # NUMCOND, feats esac -PORT=$((PORT+1)) N=$((N+1)) @@ -8038,14 +8496,15 @@ TEST="$NAME: socat handles data buffered by openssl" # socat transfer block size; keep the socket connection open and kill the # server process after a short time; if not the whole data block has been # transferred, the test has failed. -if ! feat=$(testaddrs openssl) >/dev/null; then +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs openssl) >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else tf="$td/test$N.out" te="$td/test$N.err" tdiff="$td/test$N.diff" -da="$(date) $RANDOM" +da="test$N $(date) $RANDOM" SRVCERT=testsrv gentestcert "$SRVCERT" CMD1="$SOCAT $opts -u -T 1 -b $($ECHO "$da\c" |wc -c) OPENSSL-LISTEN:$PORT,reuseaddr,cert=$SRVCERT.pem,verify=0 -" @@ -8070,8 +8529,9 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi -wait ;; +wait +fi # NUMCOND, featsesac + ;; esac N=$((N+1)) @@ -8088,7 +8548,8 @@ TEST="$NAME: trigger EOF after that many bytes, even when socket idle" #idea: we deliver that many bytes to socat; the process should terminate then. # we try to transfer data in the other direction then; if transfer succeeds, # the process did not terminate and the bug is still there. -if false; then +if ! eval $NUMCOND; then :; +elif false; then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else @@ -8097,10 +8558,10 @@ ti="$td/test$N.in" to="$td/test$N.out" te="$td/test$N.err" tdiff="$td/test$N.diff" -da="$(date)" da="$da$($ECHO '\r')" -CMD="$SOCAT $opts -%system:\"echo A; sleep 2\",readbytes=2 /dev/null%-" +da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" +CMD="$SOCAT $opts -%system:\"echo A; sleep $((2*SECONDs))\",readbytes=2 /dev/null%-" printf "test $F_n $TEST... " $N -(sleep 1; echo) |eval "$CMD" >"$to" 2>"$te" +(usleep $((2*MICROS)); echo) |eval "$CMD" >"$to" 2>"$te" if test -s "$to"; then $PRINTF "$FAILED: $SOCAT:\n" echo "$CMD" @@ -8110,7 +8571,7 @@ else if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi -fi +fi ;; # NUMCOND, feats esac N=$((N+1)) @@ -8121,10 +8582,11 @@ NAME=EXECPTYKILL case "$TESTS" in *%functions%*|*%bugs%*|*%exec%*|*%$NAME%*) TEST="$NAME: exec:...,pty explicitely kills sub process" -# we want to check if the exec'd sub process is kill in time +# we want to check if the exec'd sub process is killed in time # for this we have a shell script that generates a file after two seconds; # it should be killed after one second, so if the file was generated the test # has failed +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" ts="$td/test$N.sock" @@ -8132,18 +8594,18 @@ tda="$td/test$N.data" tsh="$td/test$N.sh" tdiff="$td/test$N.diff" cat >"$tsh" <"${te}2" & pid1=$! -sleep 1 -waitfile $ts 1 +sleep $SECONDs +waitfile $ts $SECONDs $CMD 2>>"${te}1" >>"$tf" -usleep 2500000 +sleep $((2*SECONDs)) kill "$pid1" 2>/dev/null wait if [ $? -ne 0 ]; then @@ -8160,7 +8622,8 @@ else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) -fi ;; +fi +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) @@ -8174,16 +8637,18 @@ TEST="$NAME: echo via connection to TCP V4 socket" # select a tcp entry from /etc/services, have a server listen on the port # number and connect using the service name; with the bug, connection will to a # wrong port +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" # find a service entry we do not need root for (>=1024; here >=1100 for ease) SERVENT="$(grep '^[a-z][a-z]*[^!-~][^!-~]*[1-9][1-9][0-9][0-9]/tcp' /etc/services |head -n 1)" SERVICE="$(echo $SERVENT |cut -d' ' -f1)" +_PORT="$PORT" PORT="$(echo $SERVENT |sed 's/.* \([1-9][0-9]*\).*/\1/')" tsl="$PORT" ts="127.0.0.1:$SERVICE" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts TCP4-LISTEN:$tsl,reuseaddr PIPE" CMD2="$SOCAT $opts stdout%stdin TCP4:$ts" printf "test $F_n $TEST... " $N @@ -8208,9 +8673,10 @@ else numOK=$((numOK+1)) fi kill $pid1 2>/dev/null -wait ;; +wait +PORT="$_PORT" +fi ;; # NUMCOND esac -#PORT=$((PORT+1)) N=$((N+1)) @@ -8234,6 +8700,7 @@ case "$TESTS" in TEST="$NAME: more than FOPEN_MAX FDs in use" # this test opens a number of FDs before socat is invoked. socat will have to # allocate higher FD numbers and thus hang if it cannot handle them. +if ! eval $NUMCOND; then :; else REDIR= #set -vx FOPEN_MAX=$($PROCAN -c 2>/dev/null |grep '^#define[ ][ ]*FOPEN_MAX' |awk '{print($3);}') @@ -8249,9 +8716,10 @@ done #echo "$REDIR" #testecho "$N" "$TEST" "" "pipe" "$opts -T 3" "" 1 #set -vx -eval testecho "\"$N\"" "\"$TEST\"" "\"\"" "pipe" "\"$opts -T 1\"" 1 $REDIR +eval testecho "\"$N\"" "\"$TEST\"" "\"\"" "pipe" "\"$opts -T $((2*SECONDs))\"" 1 $REDIR #set +vx fi # could determine FOPEN_MAX +fi ;; # NUMCOND esac N=$((N+1)) @@ -8266,12 +8734,13 @@ TEST="$NAME: test if UDP4-LISTEN child becomes zombie" # process is forked off. Make some transfer and wait until the -T timeout is # over. Now check for the child process: if it is zombie the test failed. # Correct is that child process terminated +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="$LOCALHOST:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -T 0.5 UDP4-LISTEN:$tsl,reuseaddr,fork PIPE" CMD2="$SOCAT $opts - UDP4:$ts" printf "test $F_n $TEST... " $N @@ -8285,10 +8754,10 @@ sleep 1 l="$(childprocess $pid1)" kill $pid1 2>/dev/null; wait if [ $rc2 -ne 0 ]; then - $PRINTF "$NO_RESULT\n" # already handled in test UDP4STREAM + $PRINTF "$NO_RESULT (client failed)\n" # already handled in test UDP4STREAM numCANT=$((numCANT+1)) elif ! echo "$da" |diff - "$tf" >"$tdiff"; then - $PRINTF "$NO_RESULT\n" # already handled in test UDP4STREAM + $PRINTF "$NO_RESULT (diff failed)\n" # already handled in test UDP4STREAM numCANT=$((numCANT+1)) elif $(isdefunct "$l"); then $PRINTF "$FAILED: $SOCAT:\n" @@ -8300,11 +8769,12 @@ else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) -fi ;; +fi +fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) - +set +vx # there was a bug with udp-recvfrom and fork: terminating sub processes became # zombies because the master process caught SIGCHLD but did not wait() @@ -8312,16 +8782,17 @@ NAME=UDP4RECVFROM_SIGCHLD case "$TESTS" in *%functions%*|*%ip4%*|*%udp%*|*%dgram%*|*%zombie%*|*%$NAME%*) TEST="$NAME: test if UDP4-RECVFROM child becomes zombie" -# idea: run a udp-recvfrom process with fork and -T. Sent it one packet, so a +# idea: run a udp-recvfrom process with fork and -T. Send it one packet, so a # sub process is forked off. Make some transfer and wait until the -T timeout # is over. Now check for the child process: if it is zombie the test failed. # Correct is that child process terminated +if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="$LOCALHOST:$tsl" -da=$(date) +da="test$N $(date) $RANDOM" CMD1="$SOCAT $opts -T 0.5 UDP4-RECVFROM:$tsl,reuseaddr,fork PIPE" CMD2="$SOCAT $opts - UDP4-SENDTO:$ts" printf "test $F_n $TEST... " $N @@ -8338,7 +8809,7 @@ if [ $rc2 -ne 0 ]; then $PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM numCANT=$((numCANT+1)) elif ! echo "$da" |diff - "$tf" >"$tdiff"; then - $PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAMM + $PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM numCANT=$((numCANT+1)) elif $(isdefunct "$l"); then $PRINTF "$FAILED: $SOCAT:\n" @@ -8350,7 +8821,1319 @@ else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) -fi ;; +fi +fi ;; # NUMCOND +esac +PORT=$((PORT+1)) +N=$((N+1)) + + +# test: there was a bug with ip*-recv and bind option: it would not bind, and +# with the first received packet an error: +# socket_init(): unknown address family 0 +# occurred +NAME=RAWIP4RECVBIND +case "$TESTS" in +*%functions%*|*%ip4%*|*%dgram%*|*%rawip%*|*%rawip4%*|*%recv%*|*%root%*|*%$NAME%*) +TEST="$NAME: raw IPv4 receive with bind" +# idea: start a socat process with ip4-recv:...,bind=... and send it a packet +# if the packet passes the test succeeded +if ! eval $NUMCOND; then :; +elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then + $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +ts1p=$PROTO; PROTO=$((PROTO+1)) +ts1a="127.0.0.1" +ts1="$ts1a:$ts1p" +da="test$N $(date) $RANDOM" +CMD1="$SOCAT $opts -u IP4-RECV:$ts1p,bind=$ts1a,reuseaddr -" +CMD2="$SOCAT $opts -u - IP4-SENDTO:$ts1" +printf "test $F_n $TEST... " $N +$CMD1 >"$tf" 2>"${te}1" & +pid1="$!" +waitip4proto $ts1p 1 +echo "$da" |$CMD2 2>>"${te}2" +rc2="$?" +#ls -l $tf +i=0; while [ ! -s "$tf" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done +kill "$pid1" 2>/dev/null; wait +if [ "$rc2" -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD1 &" + echo "$CMD2" + cat "${te}1" + cat "${te}2" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND, root +esac +PROTO=$((PROTO+1)) +N=$((N+1)) + + +# there was a bug in *-recvfrom with fork: due to an error in the appropriate +# signal handler the master process would hang after forking off the first +# child process. +NAME=UDP4RECVFROM_FORK +case "$TESTS" in +*%functions%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*) +TEST="$NAME: test if UDP4-RECVFROM handles more than one packet" +# idea: run a UDP4-RECVFROM process with fork and -T. Send it one packet; +# send it a second packet and check if this is processed properly. If yes, the +# test succeeded. +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +tsp=$PORT +ts="$LOCALHOST:$tsp" +da="test$N $(date) $RANDOM" +CMD1="$SOCAT $opts -T 2 UDP4-RECVFROM:$tsp,reuseaddr,fork PIPE" +CMD2="$SOCAT $opts -T 1 - UDP4-SENDTO:$ts" +printf "test $F_n $TEST... " $N +$CMD1 >/dev/null 2>"${te}1" & +pid1=$! +waitudp4port $tsp 1 +echo "$da" |$CMD2 >/dev/null 2>>"${te}2" # this should always work +rc2a=$? +sleep 1 +echo "$da" |$CMD2 >"$tf" 2>>"${te}3" # this would fail when bug +rc2b=$? +kill $pid1 2>/dev/null; wait +if [ $rc2b -ne 0 ]; then + $PRINTF "$NO_RESULT\n" + numCANT=$((numCANT+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD1 &" + echo "$CMD2" + cat "${te}1" "${te}2" "${te}3" + cat "$tdiff" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat "${te}1" "${te}2" "${te}3"; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +PORT=$((PORT+1)) +N=$((N+1)) + + +# there was a bug in parsing the arguments of exec: consecutive spaces resulted +# in additional empty arguments +NAME=EXECSPACES +case "$TESTS" in +*%functions%*|*%exec%*|*%parse%*|*%$NAME%*) +TEST="$NAME: correctly parse exec with consecutive spaces" +if ! eval $NUMCOND; then :; else +$PRINTF "test $F_n $TEST... " $N +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +da="test$N $(date) $RANDOM" # with a double space +tdiff="$td/test$N.diff" +# put the test data as first argument after two spaces. expect the data in the +# first argument of the exec'd command. +$SOCAT $opts -u "exec:\"bash -c \\\"echo \\\\\\\"\$1\\\\\\\"\\\" \\\"\\\" \\\"$da\\\"\"" - >"$tf" 2>"$te" +rc=$? +echo "$da" |diff - "$tf" >"$tdiff" +if [ "$rc" -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + cat "$te" + numFAIL=$((numFAIL+1)) +elif [ -s "$tdiff" ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo diff: + cat "$tdiff" + if [ -n "$debug" ]; then cat $te; fi + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +N=$((N+1)) + + +# a bug was found in the way UDP-LISTEN handles the listening socket: +# when UDP-LISTEN continued to listen after a packet had been dropped by, e.g., +# range option, the old listen socket would not be closed but a new one created. +NAME=UDP4LISTENCONT +case "$TESTS" in +*%functions%*|*%bugs%*|*%ip4%*|*%udp%*|*%$NAME%*) +TEST="$NAME: let range drop a packet and see if old socket is closed" +# idea: run a UDP4-LISTEN process with range option. Send it one packet from an +# address outside range and check if two listening sockets are open then +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +while [ "$(netstat -an |grep "^udp.*127.0.0.1:$PORT" |wc -l)" -ne 0 ]; do + PORT=$((PORT+1)) +done +tp=$PORT +da1="test$N $(date) $RANDOM" +a1="$LOCALHOST" +a2="$SECONDADDR" +#CMD0="$SOCAT $opts UDP4-LISTEN:$tp,bind=$a1,range=$a2/32 PIPE" +CMD0="$SOCAT $opts UDP4-LISTEN:$tp,range=$a2/32 PIPE" +CMD1="$SOCAT $opts - UDP-CONNECT:$a1:$tp" +printf "test $F_n $TEST... " $N +$CMD0 >/dev/null 2>"${te}0" & +pid1=$! +waitudp4port $tp 1 +echo "$da1" |$CMD1 >"${tf}1" 2>"${te}1" # this should fail +rc1=$? +waitudp4port $tp 1 +nsocks="$(netstat -an |grep "^udp.*[:.]$PORT" |wc -l)" +kill $pid1 2>/dev/null; wait +if [ $rc1 -ne 0 ]; then + $PRINTF "$NO_RESULT\n" + numCANT=$((numCANT+1)) +elif [ $nsocks -eq 0 ]; then + $PRINTF "$NO_RESULT\n" + numCANT=$((numCANT+1)) +elif [ $nsocks -ne 1 ]; then + $PRINTF "$FAILED ($nsocks listening sockets)\n" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2"; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +PORT=$((PORT+1)) +N=$((N+1)) + + +# during wait for next poll time option ignoreeof blocked the data transfer in +# the reverse direction +NAME=IGNOREEOFNOBLOCK +case "$TESTS" in +*%functions%*|*%socket%*|*%ignoreeof%*|*%$NAME%*) +TEST="$NAME: ignoreeof does not block other direction" +# have socat poll in ignoreeof mode. while it waits one second for next check, +# we send data in the reverse direction and then the total timeout fires. +# it the data has passed, the test succeeded. +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts -%/dev/null,ignoreeof /dev/null%-" +printf "test $F_n $TEST... " $N +(usleep 333333; echo "$da") |$CMD0 >"$tf" 2>"${te}0" +rc0=$? +if [ $rc0 != 0 ]; then + $PRINTF "$FAILED\n" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" + cat "${te}1" + numFAIL=$((numFAIL+1)) +elif echo "$da" |diff - "$tf" >/dev/null; then + $PRINTF "$OK\n" + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" + numFAIL=$((numFAIL+1)) +fi +fi ;; # NUMCOND +esac +N=$((N+1)) + + +# test the escape option +NAME=ESCAPE +case "$TESTS" in +*%functions%*|*%escape%*|*%$NAME%*) +TEST="$NAME: escape character triggers EOF" +# idea: start socat just echoing input, but apply escape option. send a string +# containing the escape character and check if the output is truncated +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +CMD="$SOCAT $opts -,escape=26 pipe" +printf "test $F_n $TEST... " $N +$ECHO "$da\n\x1aXYZ" |$CMD >"$tf" 2>"$te" +if [ $? -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD" + cat "$te" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED: diff:\n" + cat "$tdiff" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +N=$((N+1)) + +# test the escape option combined with ignoreeof +NAME=ESCAPE_IGNOREEOF +case "$TESTS" in +*%functions%*|*%ignoreeof%*|*%escape%*|*%$NAME%*) +TEST="$NAME: escape character triggers EOF" +# idea: start socat just echoing input, but apply escape option. send a string +# containing the escape character and check if the output is truncated +if ! eval $NUMCOND; then :; else +ti="$td/test$N.file" +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +CMD="$SOCAT -T 5 $opts -%file:$ti,ignoreeof,escape=26 pipe" +printf "test $F_n $TEST... " $N +>"$ti" +$CMD >"$tf" 2>"$te" & +$ECHO "$da\n\x1aXYZ" >>"$ti" +sleep 1 +if ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED: diff:\n" + cat "$tdiff" + cat "$te" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +N=$((N+1)) + + +# test: logging of ancillary message +while read PF KEYW ADDR IPPORT SCM_ENABLE SCM_RECV SCM_TYPE SCM_NAME ROOT SCM_VALUE +do +if [ -z "$PF" ] || [[ "$PF" == \#* ]]; then continue; fi +# +pf="$(echo $PF |tr A-Z a-z)" +proto="$(echo $KEYW |tr A-Z a-z)" +NAME=${KEYW}SCM_$SCM_TYPE +case "$TESTS" in +*%functions%*|*%$pf%*|*%dgram%*|*%udp%*|*%$proto%*|*%recv%*|*%ancillary%*|*%$ROOT%*|*%$NAME%*) +TEST="$NAME: $KEYW log ancillary message $SCM_TYPE $SCM_NAME" +# idea: start a socat process with *-RECV:..,... , ev. with ancillary message +# enabling option and send it a packet, ev. with some option. check the info log +# for the appropriate output. +if ! eval $NUMCOND; then :; +#elif [[ "$PF" == "#*" ]]; then : +elif [ "$ROOT" = root -a $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then + $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +case "X$IPPORT" in + "XPORT") + tra="$PORT" # test recv address + tsa="$ADDR:$PORT" # test sendto address + PORT=$((PORT+1)) ;; + "XPROTO") + tra="$PROTO" # test recv address + tsa="$ADDR:$PROTO" # test sendto address + PROTO=$((PROTO+1)) ;; + *) + tra="$(eval echo "$ADDR")" # resolve $N + tsa="$tra" +esac +CMD0="$SOCAT $opts -d -d -d -u $KEYW-RECV:$tra,reuseaddr,$SCM_RECV -" +CMD1="$SOCAT $opts -u - $KEYW-SENDTO:$tsa,$SCM_ENABLE" +printf "test $F_n $TEST... " $N +# is this option supported? +if $SOCAT -hhh |grep "[[:space:]]$SCM_RECV[[:space:]]" >/dev/null; then +$CMD0 >"$tf" 2>"${te}0" & +pid0="$!" +wait${proto}port $tra 1 +echo "XYZ" |$CMD1 2>"${te}1" +rc1="$?" +sleep 1 +i=0; while [ ! -s "${te}0" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done +kill "$pid0" 2>/dev/null; wait +# do not show more messages than requested +case "$opts" in +*-d*-d*-d*-d*) LEVELS="[EWNID]" ;; +*-d*-d*-d*) LEVELS="[EWNI]" ;; +*-d*-d*) LEVELS="[EWN]" ;; +*-d*) LEVELS="[EW]" ;; +*) LEVELS="[E]" ;; +esac +if [ "$rc1" -ne 0 ]; then + $PRINTF "$NO_RESULT: $SOCAT:\n" + echo "$CMD0 &" + echo "$CMD1" + grep " $LEVELS " "${te}0" + grep " $LEVELS " "${te}1" + numCANT=$((numCANT+1)) +elif ! grep "ancillary message: $SCM_TYPE: $SCM_NAME=$SCM_VALUE" ${te}0 >/dev/null; then + $PRINTF "$FAILED\n" + echo "$CMD0 &" + echo "$CMD1" + grep " $LEVELS " "${te}0" + grep " $LEVELS " "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then + grep " $LEVELS " "${te}0"; echo; grep " $LEVELS " "${te}1"; + fi + numOK=$((numOK+1)) +fi +set +vx +else # option is not supported + $PRINTF "${YELLOW}$SCM_RECV not available${NORMAL}\n" + numCANT=$((numCANT+1)) +fi # option is not supported +fi # NUMCOND, root, feats + ;; +esac +N=$((N+1)) +# +done <<<" +IP4 UDP4 127.0.0.1 PORT ip-options=x01000000 ip-recvopts IP_OPTIONS options user x01000000 +IP4 UDP4 127.0.0.1 PORT , so-timestamp SCM_TIMESTAMP timestamp user $(date '+%a %b %e %H:%M:.. %Y') +IP4 UDP4 127.0.0.1 PORT ip-ttl=53 ip-recvttl IP_TTL ttl user 53 +IP4 UDP4 127.0.0.1 PORT ip-tos=7 ip-recvtos IP_TOS tos user 7 +IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_PKTINFO locaddr user 127.0.0.1 +IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_PKTINFO dstaddr user 127.0.0.1 +IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_PKTINFO if user lo +IP4 UDP4 127.0.0.1 PORT , ip-recvif IP_RECVIF if user lo0 +IP4 UDP4 127.0.0.1 PORT , ip-recvdstaddr IP_RECVDSTADDR dstaddr user 127.0.0.1 +IP4 IP4 127.0.0.1 PROTO ip-options=x01000000 ip-recvopts IP_OPTIONS options root x01000000 +IP4 IP4 127.0.0.1 PROTO , so-timestamp SCM_TIMESTAMP timestamp root $(date '+%a %b %e %H:%M:.. %Y') +IP4 IP4 127.0.0.1 PROTO ip-ttl=53 ip-recvttl IP_TTL ttl root 53 +IP4 IP4 127.0.0.1 PROTO ip-tos=7 ip-recvtos IP_TOS tos root 7 +IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_PKTINFO locaddr root 127.0.0.1 +IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_PKTINFO dstaddr root 127.0.0.1 +IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_PKTINFO if root lo +IP4 IP4 127.0.0.1 PROTO , ip-recvif IP_RECVIF if root lo0 +IP4 IP4 127.0.0.1 PROTO , ip-recvdstaddr IP_RECVDSTADDR dstaddr root 127.0.0.1 +IP6 UDP6 [::1] PORT , so-timestamp SCM_TIMESTAMP timestamp user $(date '+%a %b %e %H:%M:.. %Y') +IP6 UDP6 [::1] PORT , ipv6-recvpktinfo IPV6_PKTINFO dstaddr user [[]0000:0000:0000:0000:0000:0000:0000:0001[]] +IP6 UDP6 [::1] PORT ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT hoplimit user 35 +IP6 UDP6 [::1] PORT ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS tclass user xaa000000 +IP6 IP6 [::1] PROTO , so-timestamp SCM_TIMESTAMP timestamp root $(date '+%a %b %e %H:%M:.. %Y') +IP6 IP6 [::1] PROTO , ipv6-recvpktinfo IPV6_PKTINFO dstaddr root [[]0000:0000:0000:0000:0000:0000:0000:0001[]] +IP6 IP6 [::1] PROTO ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT hoplimit root 35 +IP6 IP6 [::1] PROTO ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS tclass root xaa000000 +#UNIX UNIX $td/test\$N.server - , so-timestamp SCM_TIMESTAMP timestamp user $(date '+%a %b %e %H:%M:.. %Y') +" +# this one fails, appearently due to a Linux weakness: +# UNIX so-timestamp + + +# test: setting of environment variables that describe a stream socket +# connection: SOCAT_SOCKADDR, SOCAT_PEERADDR; and SOCAT_SOCKPORT, +# SOCAT_PEERPORT when applicable +while read KEYW FEAT TEST_SOCKADDR TEST_PEERADDR TEST_SOCKPORT TEST_PEERPORT; do +if [ -z "$KEYW" ] || [[ "$KEYW" == \#* ]]; then continue; fi +# +test_proto="$(echo $KEYW |tr A-Z a-z)" +NAME=${KEYW}LISTENENV +case "$TESTS" in +*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$test_proto%*|*%envvar%*|*%$NAME%*) +TEST="$NAME: $KEYW-LISTEN fills environment variables with socket addresses" +# have a server accepting a connection and invoking some shell code. The shell +# code extracts and prints the SOCAT related environment vars. +# outside code then checks if the environment contains the variables correctly +# describing the peer and local sockets. +if ! eval $NUMCOND; then :; +elif ! feat=$(testaddrs $FEAT); then + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat |tr a-z A-Z) not available${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +TEST_SOCKADDR="$(echo $TEST_SOCKADDR |sed "s/\$N/$N/g")" # actual vars +tsa="$TEST_SOCKADDR" # test server address +tsp="$TEST_SOCKPORT" # test server port +if [ "$tsp" != ',' ]; then + tsa1="$tsp"; tsa2="$tsa"; tsa="$tsa:$tsp" # tsa2 used for server bind= +else + tsa1="$tsa"; tsa2= # tsa1 used for addr parameter +fi +TEST_PEERADDR="$(echo $TEST_PEERADDR |sed "s/\$N/$N/g")" # actual vars +tca="$TEST_PEERADDR" # test client address +tcp="$TEST_PEERPORT" # test client port +if [ "$tcp" != ',' ]; then + tca="$tca:$tcp" +fi +#CMD0="$SOCAT $opts -u $KEYW-LISTEN:$tsa1 system:\"export -p\"" +CMD0="$SOCAT $opts -u $KEYW-LISTEN:$tsa1 system:\"echo SOCAT_SOCKADDR=\\\$SOCAT_SOCKADDR; echo SOCAT_PEERADDR=\\\$SOCAT_PEERADDR; echo SOCAT_SOCKPORT=\\\$SOCAT_SOCKPORT; echo SOCAT_PEERPORT=\\\$SOCAT_PEERPORT; sleep 1\"" +CMD1="$SOCAT $opts -u - $KEYW-CONNECT:$tsa,bind=$tca" +printf "test $F_n $TEST... " $N +eval "$CMD0 2>\"${te}0\" >\"$tf\" &" +pid0=$! +wait${test_proto}port $tsa1 1 +echo |$CMD1 2>"${te}1" +rc1=$? +waitfile "$tf" 2 +kill $pid0 2>/dev/null; wait +#set -vx +if [ $rc1 != 0 ]; then + $PRINTF "$NO_RESULT (client failed):\n" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numCANT=$((numCANT+1)) +elif [ "$(grep SOCAT_SOCKADDR "${tf}" |sed -e 's/^[^=]*=//' |sed -e "s/[\"']//g")" = "$TEST_SOCKADDR" -a \ + "$(grep SOCAT_PEERADDR "${tf}" |sed -e 's/^[^=]*=//' -e "s/[\"']//g")" = "$TEST_PEERADDR" -a \ + \( "$TEST_SOCKPORT" = ',' -o "$(grep SOCAT_SOCKPORT "${tf}" |sed -e 's/^[^=]*=//' |sed -e 's/"//g')" = "$tsp" \) -a \ + \( "$TEST_PEERPORT" = ',' -o "$(grep SOCAT_PEERPORT "${tf}" |sed -e 's/^[^=]*=//' |sed -e 's/"//g')" = "$tcp" \) \ + ]; then + $PRINTF "$OK\n" + if [ "$debug" ]; then + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + fi + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +fi +set +xv +fi # NUMCOND, feats + ;; +esac +N=$((N+1)) +# +done <<<" +TCP4 TCP $LOCALHOST $SECONDADDR $PORT $((PORT+1)) +TCP6 IP6 [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] $((PORT+2)) $((PORT+3)) +UDP6 IP6 [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] $((PORT+6)) $((PORT+7)) +SCTP4 SCTP $LOCALHOST $SECONDADDR $((PORT+8)) $((PORT+9)) +SCTP6 SCTP [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] $((PORT+10)) $((PORT+11)) +UNIX UNIX $td/test\$N.server $td/test\$N.client , , +" +# this one fails due to weakness in socats UDP4-LISTEN implementation: +#UDP4 $LOCALHOST $SECONDADDR $((PORT+4)) $((PORT+5)) + + +# test: environment variables from ancillary message +while read PF KEYW ADDR IPPORT SCM_ENABLE SCM_RECV SCM_ENVNAME ROOT SCM_VALUE +do +if [ -z "$PF" ] || [[ "$PF" == \#* ]]; then continue; fi +# +pf="$(echo $PF |tr A-Z a-z)" +proto="$(echo $KEYW |tr A-Z a-z)" +NAME=${KEYW}ENV_$SCM_ENVNAME +case "$TESTS" in +*%functions%*|*%$pf%*|*%dgram%*|*%udp%*|*%$proto%*|*%recv%*|*%ancillary%*|*%envvar%*|*%$ROOT%*|*%$NAME%*) +#set -vx +TEST="$NAME: $KEYW ancillary message brings $SCM_ENVNAME into environment" +# idea: start a socat process with *-RECVFROM:..,... , ev. with ancillary +# message enabling option and send it a packet, ev. with some option. write +# the resulting environment to a file and check its contents for the +# appropriate variable. +if ! eval $NUMCOND; then :; +elif [ "$ROOT" = root -a $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then + $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +case "X$IPPORT" in + "XPORT") + tra="$PORT" # test recv address + tsa="$ADDR:$PORT" # test sendto address + PORT=$((PORT+1)) ;; + "XPROTO") + tra="$PROTO" # test recv address + tsa="$ADDR:$PROTO" # test sendto address + PROTO=$((PROTO+1)) ;; + *) + tra="$(eval echo "$ADDR")" # resolve $N + tsa="$tra" +esac +#CMD0="$SOCAT $opts -u $KEYW-RECVFROM:$tra,reuseaddr,$SCM_RECV system:\"export -p\"" +CMD0="$SOCAT $opts -u $KEYW-RECVFROM:$tra,reuseaddr,$SCM_RECV system:\"echo \\\$SOCAT_$SCM_ENVNAME\"" +CMD1="$SOCAT $opts -u - $KEYW-SENDTO:$tsa,$SCM_ENABLE" +printf "test $F_n $TEST... " $N +# is this option supported? +if $SOCAT -hhh |grep "[[:space:]]$SCM_RECV[[:space:]]" >/dev/null; then +eval "$CMD0 >\"$tf\" 2>\"${te}0\" &" +pid0="$!" +wait${proto}port $tra 1 +echo "XYZ" |$CMD1 2>"${te}1" +rc1="$?" +waitfile "$tf" 2 +#i=0; while [ ! -s "${te}0" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done +kill "$pid0" 2>/dev/null; wait +# do not show more messages than requested +#set -vx +if [ "$rc1" -ne 0 ]; then + $PRINTF "$NO_RESULT: $SOCAT:\n" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" + cat "${te}1" + numCANT=$((numCANT+1)) +#elif ! egrep "^export SOCAT_$SCM_ENVNAME=[\"']?$SCM_VALUE[\"']?\$" ${tf} >/dev/null; then +#elif ! eval echo "$SOCAT_\$SCM_VALUE" |diff - "${tf}" >/dev/null; then +elif ! expr "$(cat "$tf")" : "$(eval echo "\$SCM_VALUE")" >/dev/null; then + $PRINTF "$FAILED\n" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" + cat "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then + cat "${te}0"; echo; cat "${te}1"; + fi + numOK=$((numOK+1)) +fi +set +vx +else # option is not supported + $PRINTF "${YELLOW}$SCM_RECV not available${NORMAL}\n" + numCANT=$((numCANT+1)) +fi # option is not supported +fi ;; # NUMCOND, feats +esac +N=$((N+1)) +# +done <<<" +IP4 UDP4 127.0.0.1 PORT ip-options=x01000000 ip-recvopts IP_OPTIONS user x01000000 +IP4 UDP4 127.0.0.1 PORT , so-timestamp TIMESTAMP user $(date '+%a %b %e %H:%M:.. %Y'), ...... usecs +IP4 UDP4 127.0.0.1 PORT ip-ttl=53 ip-recvttl IP_TTL user 53 +IP4 UDP4 127.0.0.1 PORT ip-tos=7 ip-recvtos IP_TOS user 7 +IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_LOCADDR user 127.0.0.1 +IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_DSTADDR user 127.0.0.1 +IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_IF user lo +IP4 UDP4 127.0.0.1 PORT , ip-recvif IP_IF user lo0 +IP4 UDP4 127.0.0.1 PORT , ip-recvdstaddr IP_DSTADDR user 127.0.0.1 +IP4 IP4 127.0.0.1 PROTO ip-options=x01000000 ip-recvopts IP_OPTIONS root x01000000 +IP4 IP4 127.0.0.1 PROTO , so-timestamp TIMESTAMP root $(date '+%a %b %e %H:%M:.. %Y'), ...... usecs +IP4 IP4 127.0.0.1 PROTO ip-ttl=53 ip-recvttl IP_TTL root 53 +IP4 IP4 127.0.0.1 PROTO ip-tos=7 ip-recvtos IP_TOS root 7 +IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_LOCADDR root 127.0.0.1 +IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_DSTADDR root 127.0.0.1 +IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_IF root lo +IP4 IP4 127.0.0.1 PROTO , ip-recvif IP_IF root lo0 +IP4 IP4 127.0.0.1 PROTO , ip-recvdstaddr IP_DSTADDR root 127.0.0.1 +IP6 UDP6 [::1] PORT , ipv6-recvpktinfo IPV6_DSTADDR user [[]0000:0000:0000:0000:0000:0000:0000:0001[]] +IP6 UDP6 [::1] PORT ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT user 35 +IP6 UDP6 [::1] PORT ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS user xaa000000 +IP6 IP6 [::1] PROTO , ipv6-recvpktinfo IPV6_DSTADDR root [[]0000:0000:0000:0000:0000:0000:0000:0001[]] +IP6 IP6 [::1] PROTO ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT root 35 +IP6 IP6 [::1] PROTO ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS root xaa000000 +#UNIX UNIX $td/test\$N.server - , so-timestamp TIMESTAMP user $(date '+%a %b %e %H:%M:.. %Y') +" + + +# test the SOCKET-CONNECT address (against TCP4-LISTEN) +NAME=SOCKET_CONNECT_TCP4 +case "$TESTS" in +*%functions%*|*%generic%*|*%socket%*|*%$NAME%*) +TEST="$NAME: socket connect with TCP/IPv4" +# start a TCP4-LISTEN process that echoes data, and send test data using +# SOCKET-CONNECT, selecting TCP/IPv4. The sent data should be returned. +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +ts0p=$PORT; PORT=$((PORT+1)) +ts0a="127.0.0.1" +ts1p=$(printf "%04x" $ts0p); +ts1a="7f000001" # "127.0.0.1" +ts1="x${ts1p}${ts1a}x0000000000000000" +ts1b=$(printf "%04x" $PORT); PORT=$((PORT+1)) +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts TCP4-LISTEN:$ts0p,reuseaddr,bind=$ts0a PIPE" +CMD1="$SOCAT $opts - SOCKET-CONNECT:2:6:$ts1,bind=x${ts1b}00000000x0000000000000000" +printf "test $F_n $TEST... " $N +$CMD0 2>"${te}0" & +pid0="$!" +waittcp4port $ts0p 1 +echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" +rc1="$?" +kill "$pid0" 2>/dev/null; wait; +if [ "$rc1" -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi # NUMCOND + ;; +esac +PORT=$((PORT+1)) +N=$((N+1)) + +PF_INET6="$($PROCAN -c |grep "^#define[[:space:]]*PF_INET6[[:space:]]" |cut -d' ' -f3)" + +# test the SOCKET-CONNECT address (against TCP6-LISTEN) +NAME=SOCKET_CONNECT_TCP6 +case "$TESTS" in +*%functions%*|*%generic%*|*%tcp6%*|*%socket%*|*%$NAME%*) +TEST="$NAME: socket connect with TCP/IPv6" +if ! eval $NUMCOND; then :; else +# start a TCP6-LISTEN process that echoes data, and send test data using +# SOCKET-CONNECT, selecting TCP/IPv6. The sent data should be returned. +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +ts0p=$PORT; PORT=$((PORT+1)) +ts0a="[::1]" +ts1p=$(printf "%04x" $ts0p); +ts1a="00000000000000000000000000000001" # "[::1]" +ts1="x${ts1p}x00000000x${ts1a}x00000000" +ts1b=$(printf "%04x" $PORT); PORT=$((PORT+1)) +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts TCP6-LISTEN:$ts0p,reuseaddr,bind=$ts0a PIPE" +CMD1="$SOCAT $opts - SOCKET-CONNECT:$PF_INET6:6:$ts1,bind=x${ts1b}x00000000x00000000000000000000000000000000x00000000" +printf "test $F_n $TEST... " $N +$CMD0 2>"${te}0" & +pid0="$!" +waittcp6port $ts0p 1 +echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" +rc1="$?" +kill "$pid0" 2>/dev/null; wait; +if [ "$rc1" -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +PORT=$((PORT+1)) +N=$((N+1)) + +# test the SOCKET-CONNECT address (against UNIX-LISTEN) +NAME=SOCKET_CONNECT_UNIX +case "$TESTS" in +*%functions%*|*%generic%*|*%unix%*|*%socket%*|*%$NAME%*) +TEST="$NAME: socket connect with UNIX domain" +# start a UNIX-LISTEN process that echoes data, and send test data using +# SOCKET-CONNECT, selecting UNIX socket. The sent data should be returned. +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +ts0="$td/test$N.server" +ts1="$td/test$N.client" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts UNIX-LISTEN:$ts0,reuseaddr PIPE" +CMD1="$SOCAT $opts - SOCKET-CONNECT:1:0:\\\"$ts0\\\0\\\",bind=\\\"$ts1\\\0\\\"" +printf "test $F_n $TEST... " $N +$CMD0 2>"${te}0" & +pid0="$!" +waitfile $ts0 1 +echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" +rc1="$?" +kill "$pid0" 2>/dev/null; wait; +if [ "$rc1" -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +N=$((N+1)) + +# test the SOCKET-LISTEN address (with TCP4-CONNECT) +NAME=SOCKET_LISTEN +case "$TESTS" in +*%functions%*|*%generic%*|*%socket%*|*%$NAME%*) +TEST="$NAME: socket recvfrom with TCP/IPv4" +# start a SOCKET-LISTEN process that uses TCP/IPv4 and echoes data, and +# send test data using TCP4-CONNECT. The sent data should be returned. +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +ts1p=$PORT; PORT=$((PORT+1)) +ts1a="127.0.0.1" +ts0p=$(printf "%04x" $ts1p); +ts0a="7f000001" # "127.0.0.1" +ts0="x${ts0p}${ts0a}x0000000000000000" +ts1b=$PORT; PORT=$((PORT+1)) +ts1="$ts1a:$ts1p" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts SOCKET-LISTEN:2:6:$ts0,reuseaddr PIPE" +CMD1="$SOCAT $opts - TCP4-CONNECT:$ts1,bind=:$ts1b" +printf "test $F_n $TEST... " $N +$CMD0 2>"${te}0" & +pid0="$!" +#sleep 1 +waittcp4port $ts1p 1 +echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" +rc1="$?" +kill "$pid0" 2>/dev/null; wait; +if [ "$rc1" -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +PORT=$((PORT+1)) +N=$((N+1)) + +SOCK_DGRAM="$($PROCAN -c |grep "^#define[[:space:]]*SOCK_DGRAM[[:space:]]" |cut -d' ' -f3)" + +# test the SOCKET-SENDTO address (against UDP4-RECVFROM) +NAME=SOCKET_SENDTO +case "$TESTS" in +*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*) +TEST="$NAME: socket sendto with UDP/IPv4" +# start a UDP4-RECVFROM process that echoes data, and send test data using +# SOCKET-SENDTO, selecting UDP/IPv4. The sent data should be returned. +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +ts0p=$PORT; PORT=$((PORT+1)) +ts0a="127.0.0.1" +ts1p=$(printf "%04x" $ts0p); +ts1a="7f000001" # "127.0.0.1" +ts1="x${ts1p}${ts1a}x0000000000000000" +ts1b=$(printf "%04x" $PORT); PORT=$((PORT+1)) +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts UDP4-RECVFROM:$ts0p,reuseaddr,bind=$ts0a PIPE" +CMD1="$SOCAT $opts - SOCKET-SENDTO:2:$SOCK_DGRAM:17:$ts1,bind=x${ts1b}x00000000x0000000000000000" +printf "test $F_n $TEST... " $N +$CMD0 2>"${te}0" & +pid0="$!" +waitudp4port $ts0p 1 +echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" +rc1="$?" +kill "$pid0" 2>/dev/null; wait; +if [ "$rc1" -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +PORT=$((PORT+1)) +N=$((N+1)) + +# test the SOCKET-RECVFROM address (with UDP4-SENDTO) +NAME=SOCKET_RECVFROM +case "$TESTS" in +*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*) +TEST="$NAME: socket recvfrom with UDP/IPv4" +# start a SOCKET-RECVFROM process that uses UDP/IPv4 and echoes data, and +# send test data using UDP4-SENDTO. The sent data should be returned. +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +ts1p=$PORT; PORT=$((PORT+1)) +ts1a="127.0.0.1" +ts0p=$(printf "%04x" $ts1p); +ts0a="7f000001" # "127.0.0.1" +ts0="x${ts0p}${ts0a}x0000000000000000" +ts1b=$PORT; PORT=$((PORT+1)) +ts1="$ts1a:$ts1p" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts SOCKET-RECVFROM:2:$SOCK_DGRAM:17:$ts0,reuseaddr PIPE" +CMD1="$SOCAT $opts - UDP4-SENDTO:$ts1,bind=:$ts1b" +printf "test $F_n $TEST... " $N +$CMD0 2>"${te}0" & +pid0="$!" +sleep 1 # waitudp4port $ts1p 1 +echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" +rc1="$?" +kill "$pid0" 2>/dev/null; wait; +if [ "$rc1" -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +PORT=$((PORT+1)) +N=$((N+1)) + + +# test the SOCKET-RECV address (with UDP4-SENDTO) +NAME=SOCKET_RECV +case "$TESTS" in +*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*) +TEST="$NAME: socket recv with UDP/IPv4" +# start a SOCKET-RECV process that uses UPD/IPv4 and writes received data to file, and +# send test data using UDP4-SENDTO. +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +ts1p=$PORT; PORT=$((PORT+1)) +ts1a="127.0.0.1" +ts0p=$(printf "%04x" $ts1p); +ts0a="7f000001" # "127.0.0.1" +ts0="x${ts0p}${ts0a}x0000000000000000" +ts1b=$PORT; PORT=$((PORT+1)) +ts1="$ts1a:$ts1p" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts -u SOCKET-RECV:2:$SOCK_DGRAM:17:$ts0,reuseaddr -" +CMD1="$SOCAT $opts -u - UDP4-SENDTO:$ts1,bind=:$ts1b" +printf "test $F_n $TEST... " $N +$CMD0 2>"${te}0" >"$tf" & +pid0="$!" +sleep 1 # waitudp4port $ts1p 1 +echo "$da" |$CMD1 2>>"${te}1" +rc1="$?" +sleep 1 +kill "$pid0" 2>/dev/null; wait; +if [ "$rc1" -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +PORT=$((PORT+1)) +N=$((N+1)) + +# test SOCKET-DATAGRAM (with UDP4-DATAGRAM) +NAME=SOCKET_DATAGRAM +case "$TESTS" in +*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*) +TEST="$NAME: socket datagram via UDP/IPv4" +# start a UDP4-DATAGRAM process that echoes data, and send test data using +# SOCKET-DATAGRAM, selecting UDP/IPv4. The sent data should be returned. +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +ts0p=$PORT; PORT=$((PORT+1)) +ts1p=$PORT; PORT=$((PORT+1)) +ts0a="127.0.0.1" +ts1b=$(printf "%04x" $ts0p); +ts1a="7f000001" # "127.0.0.1" +ts0b=$(printf "%04x" $ts0p) +ts1b=$(printf "%04x" $ts1p) +ts1="x${ts0b}${ts1a}x0000000000000000" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts UDP4-DATAGRAM:$ts0a:$ts1p,bind=:$ts0p,reuseaddr PIPE" +CMD1="$SOCAT $opts - SOCKET-DATAGRAM:2:$SOCK_DGRAM:17:$ts1,bind=x${ts1b}x00000000x0000000000000000" +printf "test $F_n $TEST... " $N +$CMD0 2>"${te}0" & +pid0="$!" +waitudp4port $ts0p 1 +echo "$da" |$CMD1 2>>"${te}1" >"$tf" +rc1="$?" +kill "$pid0" 2>/dev/null; wait; +if [ "$rc1" -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + echo "$CMD0 &" + cat "${te}0" + echo "$CMD1" + cat "${te}1" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat $te; fi + numOK=$((numOK+1)) +fi +fi ;; # NUMCOND +esac +PORT=$((PORT+1)) +N=$((N+1)) + +NAME=SOCKETRANGEMASK +case "$TESTS" in +*%functions%*|*%security%*|*%generic%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%socket%*|*%range%*|*%$NAME%*) +TEST="$NAME: security of generic socket-listen with RANGE option" +if ! eval $NUMCOND; then :; +elif [ -z "$SECONDADDR" ]; then + # we need access to more loopback addresses + $PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +ts1p=$(printf "%04x" $PORT); +testserversec "$N" "$TEST" "$opts -s" "SOCKET-LISTEN:2:6:x${ts1p}x00000000x0000000000000000,reuseaddr,fork,retry=1" "" "range=x0000x7f000000:x0000xffffffff" "SOCKET-CONNECT:2:6:x${ts1p}x${SECONDADDRHEX}x0000000000000000" 4 tcp $PORT 0 +fi ;; # NUMCOND, $SECONDADDR +esac +PORT=$((PORT+1)) +N=$((N+1)) + + +TIOCEXCL="$($PROCAN -c |grep "^#define[[:space:]]*TIOCEXCL[[:space:]]" |cut -d' ' -f3)" + +# test the generic ioctl-void option +NAME=IOCTL_VOID +case "$TESTS" in +*%functions%*|*%pty%*|*%generic%*|*%$NAME%*) +TEST="$NAME: test the ioctl-void option" +# there are not many ioctls that apply to non global resources and do not +# require root. TIOCEXCL seems to fit: +# process 0 provides a pty; +# process 1 opens it with the TIOCEXCL ioctl; +# process 2 opens it too and fails with "device or resource busy" only when the +# previous ioctl was successful +if ! eval $NUMCOND; then :; +elif [ -z "$TIOCEXCL" ]; then + # we use the numeric value of TIOCEXL which is system dependent + $PRINTF "test $F_n $TEST... ${YELLOW}no value of TIOCEXCL${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +tp="$td/test$N.pty" +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts PTY,LINK=$tp pipe" +CMD1="$SOCAT $opts - file:$tp,ioctl-void=$TIOCEXCL,raw,echo=0" +CMD2="$SOCAT $opts - file:$tp,raw,echo=0" +printf "test $F_n $TEST... " $N +$CMD0 >/dev/null 2>"${te}0" & +pid0=$! +waitfile $tp 1 +(echo "$da"; sleep 2) |$CMD1 >"$tf" 2>"${te}1" & # this should always work +pid1=$! +usleep 1000000 +$CMD2 >/dev/null 2>"${te}2" /dev/null; wait +if ! echo "$da" |diff - "$tf" >/dev/null; then + $PRINTF "${YELLOW}phase 1 failed${NORMAL}\n" + echo "$CMD0 &" + echo "$CMD1" + echo "$da" |diff - "$tf" + numCANT=$((numCANT+1)) +elif [ $rc2 -eq 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD0 &" + echo "$CMD1" + echo "$CMD2" + cat "${te}0" "${te}1" "${te}2" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2"; fi + numOK=$((numOK+1)) +fi +fi # NUMCOND, TIOCEXCL +;; +esac +N=$((N+1)) + + +SOL_SOCKET="$($PROCAN -c |grep "^#define[[:space:]]*SOL_SOCKET[[:space:]]" |cut -d' ' -f3)" +SO_REUSEADDR="$($PROCAN -c |grep "^#define[[:space:]]*SO_REUSEADDR[[:space:]]" |cut -d' ' -f3)" + +# test the generic setsockopt-int option +NAME=SETSOCKOPT_INT +case "$TESTS" in +*%functions%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*) +TEST="$NAME: test the setsockopt-int option" +# there are not many socket options that apply to non global resources, do not +# require root, do not require a network connection, and can easily be +# tested. SO_REUSEADDR seems to fit: +# process 0 provides a tcp listening socket with reuseaddr; +# process 1 connects to this port; thus the port is connected but no longer +# listening +# process 2 tries to listen on this port with SO_REUSEADDR, will fail if the +# (generically specified) SO_REUSEADDR socket options did not work +# process 3 connects to this port; only if it is successful the test is ok +if ! eval $NUMCOND; then :; +elif [ -z "SO_REUSEADDR" ]; then + # we use the numeric value of SO_REUSEADDR which might be system dependent + $PRINTF "test $F_n $TEST... ${YELLOW}value of SO_REUSEADDR not known${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +tp="$PORT" +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts TCP4-L:$tp,setsockopt-int=$SOL_SOCKET:$SO_REUSEADDR:1 PIPE" +CMD1="$SOCAT $opts - TCP:localhost:$tp" +CMD2="$CMD0" +CMD3="$CMD1" +printf "test $F_n $TEST... " $N +$CMD0 >/dev/null 2>"${te}0" & +pid0=$! +waittcp4port $tp 1 +(echo "$da"; sleep 3) |$CMD1 >"$tf" 2>"${te}1" & # this should always work +pid1=$! +usleep 1000000 +$CMD2 >/dev/null 2>"${te}2" & +pid2=$! +waittcp4port $tp 1 +(echo "$da") |$CMD3 >"${tf}3" 2>"${te}3" +rc3=$? +kill $pid0 $pid1 $pid2 2>/dev/null; wait +if ! echo "$da" |diff - "$tf"; then + $PRINTF "${YELLOW}phase 1 failed${NORMAL}\n" + echo "$CMD0 &" + echo "$CMD1" + numCANT=$((numCANT+1)) +elif [ $rc3 -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD2 &" + echo "$CMD3" + cat "${te}2" "${te}3" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "${tf}3"; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD2 &" + echo "$CMD3" + echo "$da" |diff - "${tf}3" + numCANT=$((numCANT+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2" "${te}3"; fi + numOK=$((numOK+1)) +fi +fi # NUMCOND, SO_REUSEADDR + ;; +esac +PORT=$((PORT+1)) +N=$((N+1)) + + +NAME=SCTP4STREAM +case "$TESTS" in +*%functions%*|*%ip4%*|*%ipapp%*|*%sctp%*|*%$NAME%*) +TEST="$NAME: echo via connection to SCTP V4 socket" +PORT="$((PORT+1))" +if ! eval $NUMCOND; then :; +elif ! testaddrs sctp ip4 >/dev/null || ! runsip4 >/dev/null || ! runssctp4 "$((PORT-1))" >/dev/null; then + $PRINTF "test $F_n $TEST... ${YELLOW}SCTP4 not available${NORMAL}\n" $N + numCANT=$((numCANT+1)) +elif [ "$UNAME" = Linux ] && ! grep ^sctp /proc/modules >/dev/null; then + # RHEL5 based systems became unusable when an sctp socket was created but + # module sctp not loaded + $PRINTF "test $F_n $TEST...${YELLOW}load sctp module!${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +tsl=$PORT +ts="127.0.0.1:$tsl" +da=$(date) +CMD1="$SOCAT $opts SCTP4-LISTEN:$tsl,reuseaddr PIPE" +CMD2="$SOCAT $opts stdout%stdin SCTP4:$ts" +printf "test $F_n $TEST... " $N +$CMD1 >"$tf" 2>"${te}1" & +pid1=$! +waitsctp4port $tsl 1 +# SCTP does not seem to support half close, so we let it 1s to finish +(echo "$da"; sleep 1) |$CMD2 >>"$tf" 2>>"${te}2" +if [ $? -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD1 &" + cat "${te}1" + echo "$CMD2" + cat "${te}2" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi + numOK=$((numOK+1)) +fi +kill $pid1 2>/dev/null +wait +fi # NUMCOND, feats + ;; +esac +PORT=$((PORT+1)) +N=$((N+1)) + +NAME=SCTP6STREAM +case "$TESTS" in +*%functions%*|*%ip6%*|*%ipapp%*|*%sctp%*|*%$NAME%*) +TEST="$NAME: echo via connection to SCTP V6 socket" +PORT="$((PORT+1))" +if ! eval $NUMCOND; then :; +elif ! testaddrs sctp ip6 >/dev/null || ! runsip6 >/dev/null || ! runssctp6 "$((PORT-1))" >/dev/null; then + $PRINTF "test $F_n $TEST... ${YELLOW}SCTP6 not available${NORMAL}\n" $N + numCANT=$((numCANT+1)) +elif [ "$UNAME" = Linux ] && ! grep ^sctp /proc/modules >/dev/null; then + $PRINTF "test $F_n $TEST...${YELLOW}load sctp module!${NORMAL}\n" $N + numCANT=$((numCANT+1)) +else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +tsl=$PORT +ts="[::1]:$tsl" +da=$(date) +CMD1="$SOCAT $opts SCTP6-listen:$tsl,reuseaddr PIPE" +CMD2="$SOCAT $opts stdout%stdin SCTP6:$ts" +printf "test $F_n $TEST... " $N +$CMD1 >"$tf" 2>"${te}1" & +pid=$! # background process id +waitsctp6port $tsl 1 +# SCTP does not seem to support half close, so we let it 1s to finish +(echo "$da"; sleep 1) |$CMD2 >>"$tf" 2>>"${te}2" +if [ $? -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD1 &" + echo "$CMD2" + cat "$te" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED: diff:\n" + cat "$tdiff" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi + numOK=$((numOK+1)) +fi +kill $pid 2>/dev/null +fi # NUMCOND, feats + ;; esac PORT=$((PORT+1)) N=$((N+1)) @@ -8378,32 +10161,40 @@ wait exit -# template -NAME=!!! +# test template + +# give a description of what is tested (a bugfix, a new feature...) +NAME=SHORT_UNIQUE_TESTNAME case "$TESTS" in -*%functions%*|*%$NAME%*) -TEST="$NAME: !!!" +*%functions%*|*%bugs%*|*%socket%*|*%$NAME%*) +TEST="$NAME: give a one line description of test" +# describe how the test is performed, and what's the success criteria +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts server-address PIPE" +CMD1="$SOCAT - client-address" printf "test $F_n $TEST... " $N -!!! +$CMD0 >/dev/null 2>"${te}0" & +pid0=$! +waitport $xy 1 +echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" +rc1=$? +kill $pid0 2>/dev/null; wait if [ !!! ]; then $PRINTF "$OK\n" + numOK=$((numOK+1)) else $PRINTF "$FAILED\n" - cat "$te" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" + cat "${te}1" + numFAIL=$((numFAIL+1)) fi +fi # NUMCOND + ;; esac N=$((N+1)) - - -TEST="$NAME: transferring from one file to another with echo" -tf1="$td/file$N.input" -tf2="$td/file$N.output" -testecho "$N" "$TEST" "" "echo" "$opts" - - -# MANUAL TESTS - -# ZOMBIES -# have httpd on PORT/tcp -# nice -20 $SOCAT -d tcp-l:24080,fork tcp:$LOCALHOST:PORT -# i=0; while [ $i -lt 100 ]; do $ECHO 'GET / HTTP/1.0\n' |$SOCAT -t -,ignoreeof tcp:$LOCALHOST:24080 >/dev/null& i=$((i+1)); done diff --git a/utils.c b/utils.c index eeca60c..57904d9 100644 --- a/utils.c +++ b/utils.c @@ -1,5 +1,5 @@ /* source: utils.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* useful additions to C library */ @@ -145,3 +145,17 @@ char *sanitize_string(const char *data, /* input data */ } return coded; } + +/* copies a substring out of a given buff + returns scratch, \0 terminated; scratch must provide len+1 bytes +*/ +char *xiosubstr(char *scratch, const char *str, size_t from, size_t len) { + char *scratch0 = scratch; + str += from; + while (len--) { + *scratch++ = *str++; + } + *scratch = '\0'; + return scratch0; +} + diff --git a/utils.h b/utils.h index 4488358..f942db1 100644 --- a/utils.h +++ b/utils.h @@ -1,5 +1,5 @@ /* source: utils.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __utils_h_included @@ -63,6 +63,7 @@ char *sanitize_string(const char *data, /* input data */ size_t bytes, /* length of input data, >=0 */ char *coded, /* output buffer, must be long enough */ int style); +extern +char *xiosubstr(char *scratch, const char *str, size_t from, size_t len); #endif /* !defined(__utils_h_included) */ - diff --git a/xio-ascii.c b/xio-ascii.c index 88909dc..7cd8103 100644 --- a/xio-ascii.c +++ b/xio-ascii.c @@ -1,5 +1,5 @@ /* source: xio-ascii.c */ -/* Copyright Gerhard Rieger 2002-2006 */ +/* Copyright Gerhard Rieger 2002-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains functions for text encoding, decoding, and conversions */ @@ -105,3 +105,52 @@ char * } return coded; } + +/* write the binary data to output buffer codbuff in human readable form. + bytes gives the length of the data, codlen the available space in codbuff. + coding specifies how the data is to be presented. Not much to select now. + returns a pointer to the first char in codbuff that has not been overwritten; + it might also point to the first char after the buffer! +*/ +static char * +_xiodump(const unsigned char *data, size_t bytes, char *codbuff, size_t codlen, + int coding) { + int start = 1; + int space = coding & 0xff; + + if (bytes <= 0) { codbuff[0] = '\0'; return codbuff; } + if (space == 0) space = -1; + if (0) { + ; /* for canonical reasons */ + } else if (1) { + /* simple hexadecimal output */ + if (bytes > 2*codlen+1) { + bytes = (codlen-1)/2; + } + *codbuff++ = 'x'; --codlen; + while (bytes-- > 0) { + if (start == 0 && space == 0) { + *codbuff++ = ' '; + space = (coding & 0xff); + } + codbuff += sprintf(codbuff, "%02x", *data++); + start = 0; + } + } + return codbuff; +} + +/* write the binary data to codbuff in human readable form. + bytes gives the length of the data, codlen the available space in codbuff. + coding specifies how the data is to be presented. Not much to select now. + null terminates the output. returns a pointer to the output string. +*/ +char * +xiodump(const unsigned char *data, size_t bytes, char *codbuff, size_t codlen, + int coding) { + char *result; + + result = _xiodump(data, bytes, codbuff, codlen-1, coding); + *result = '\0'; + return codbuff; +} diff --git a/xio-ascii.h b/xio-ascii.h index 875623d..bcb760f 100644 --- a/xio-ascii.h +++ b/xio-ascii.h @@ -1,5 +1,5 @@ /* source: xio-ascii.h */ -/* Copyright Gerhard Rieger 2002-2006 */ +/* Copyright Gerhard Rieger 2002-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_ascii_h_included @@ -17,4 +17,8 @@ extern char *xiosanitize(const char *data, /* input data */ extern char * xiohexdump(const unsigned char *data, size_t bytes, char *coded); +extern char * +xiodump(const unsigned char *data, size_t bytes, char *coded, size_t codlen, + int coding); + #endif /* !defined(__xio_ascii_h_included) */ diff --git a/xio-exec.c b/xio-exec.c index 2fb3d83..03f7abe 100644 --- a/xio-exec.c +++ b/xio-exec.c @@ -1,5 +1,5 @@ /* source: xio-exec.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for opening addresses of exec type */ @@ -42,6 +42,7 @@ static int xioopen_exec1end(int argc, const char *argv[], struct opt *opts, ) { int status; bool dash = false; + int duptostderr; if (argc != 2) { Error3("\"%s:%s\": wrong number of parameters (%d instead of 1)", argv[0], argv[1], argc-1); @@ -49,7 +50,7 @@ static int xioopen_exec1end(int argc, const char *argv[], struct opt *opts, retropt_bool(opts, OPT_DASH, &dash); - status = _xioopen_foxec_end(xioflags, &fd->stream, groups, &opts); + status = _xioopen_foxec_end(xioflags, &fd->stream, groups, &opts, &duptostderr); if (status < 0) return status; if (status == 0) { /* child */ const char *ends[] = { " ", NULL }; @@ -92,11 +93,11 @@ static int xioopen_exec1end(int argc, const char *argv[], struct opt *opts, if (pargv[0] == NULL) pargv[0] = token; else ++pargv[0]; pargc = 1; while (*strp == ' ') { + while (*++strp == ' ') ; if ((pargc & 0x07) == 0) { pargv = Realloc(pargv, (pargc+8)*sizeof(char *)); if (pargv == NULL) return STAT_RETRYLATER; } - ++strp; pargv[pargc++] = tokp; if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests, false, true, true, false) < 0) { @@ -128,6 +129,11 @@ static int xioopen_exec1end(int argc, const char *argv[], struct opt *opts, return STAT_NORETRY; } + /* only now redirect stderr */ + if (duptostderr >= 0) { + diag_dup(); + Dup2(duptostderr, 2); + } Notice1("execvp'ing \"%s\"", token); result = Execvp(token, pargv); /* here we come only if execvp() failed */ diff --git a/xio-fd.c b/xio-fd.c index af12446..2fa96cb 100644 --- a/xio-fd.c +++ b/xio-fd.c @@ -1,5 +1,5 @@ /* source: xio-fd.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains common file descriptor related option definitions */ @@ -74,5 +74,17 @@ 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 }; /* control closing of connections */ -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_end_close = { "end-close", "close", 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 }; + +/****** generic ioctl() options ******/ +const struct optdesc opt_ioctl_void = { "ioctl-void", "ioctl", OPT_IOCTL_VOID, GROUP_FD, PH_FD, TYPE_INT, OFUNC_IOCTL_GENERIC, 0, 0, 0 }; +const struct optdesc opt_ioctl_int = { "ioctl-int", NULL, OPT_IOCTL_INT, GROUP_FD, PH_FD, TYPE_INT_INT, OFUNC_IOCTL_GENERIC, 0, 0, 0 }; +const struct optdesc opt_ioctl_intp = { "ioctl-intp", NULL, OPT_IOCTL_INTP, GROUP_FD, PH_FD, TYPE_INT_INTP, OFUNC_IOCTL_GENERIC, 0, 0, 0 }; +const struct optdesc opt_ioctl_bin = { "ioctl-bin", NULL, OPT_IOCTL_BIN, GROUP_FD, PH_FD, TYPE_INT_BIN, OFUNC_IOCTL_GENERIC, 0, 0, 0 }; +const struct optdesc opt_ioctl_string = { "ioctl-string",NULL, OPT_IOCTL_STRING,GROUP_FD, PH_FD, TYPE_INT_STRING,OFUNC_IOCTL_GENERIC, 0, 0, 0 }; + +/* POSIX STREAMS */ +#define ENABLE_OPTIONS +#include "xio-streams.c" +#undef ENABLE_OPTIONS diff --git a/xio-fd.h b/xio-fd.h index b08bd5e..7d06ac7 100644 --- a/xio-fd.h +++ b/xio-fd.h @@ -1,10 +1,15 @@ /* source: xio-fd.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_fd_h_included #define __xio_fd_h_included 1 +extern const struct optdesc opt_ioctl_void; +extern const struct optdesc opt_ioctl_int; +extern const struct optdesc opt_ioctl_intp; +extern const struct optdesc opt_ioctl_bin; +extern const struct optdesc opt_ioctl_string; extern const struct optdesc opt_append; extern const struct optdesc opt_nonblock; extern const struct optdesc opt_o_ndelay; @@ -38,5 +43,6 @@ extern const struct optdesc opt_f_setlkw_wr; extern const struct optdesc opt_cool_write; extern const struct optdesc opt_end_close; extern const struct optdesc opt_shut_none; +extern const struct optdesc opt_streams_i_push; #endif /* !defined(__xio_fd_h_included) */ diff --git a/xio-gopen.c b/xio-gopen.c index 6557019..65bd75a 100644 --- a/xio-gopen.c +++ b/xio-gopen.c @@ -1,5 +1,5 @@ /* source: xio-gopen.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for opening addresses of generic open type */ @@ -17,7 +17,7 @@ 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 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(":") }; +const struct xioaddr_endpoint_desc xioaddr_gopen1 = { XIOADDR_SYS, "gopen", 1, XIOBIT_ALL, GROUP_FD|GROUP_FIFO|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(":") }; const union xioaddr_desc *xioaddrs_gopen[] = { (union xioaddr_desc *)&xioaddr_gopen1, @@ -50,120 +50,19 @@ static int xioopen_gopen1(int argc, const char *argv[], struct opt *opts, int xi /* note: when S_ISSOCK was undefined, it always gives 0 */ if (exists && S_ISSOCK(st_mode)) { #if WITH_UNIX - int socktype = SOCK_STREAM; - int optsotype = -1; - struct sockaddr_un sa, us; - socklen_t salen, uslen = sizeof(us); - bool needbind = false; + union sockaddr_union us; + socklen_t uslen; char infobuff[256]; - struct opt *opts2; - - socket_un_init(&sa); - socket_un_init(&us); Info1("\"%s\" is a socket, connecting to it", filename); - if (retropt_int(opts, OPT_SO_TYPE, &optsotype) == 0) { - socktype = optsotype; + + fd->stream.howtoshut = XIOSHUT_DOWN; + fd->stream.howtoclose = XIOCLOSE_CLOSE; + result = + _xioopen_unix_client(&fd->stream, xioflags, groups, 0, opts, filename); + if (result < 0) { + return result; } - - if (retropt_bind(opts, AF_UNIX, socktype, 0, (struct sockaddr *)&us, &uslen, 0, 0, 0) != STAT_NOACTION) { - needbind = true; - } - - retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); - if (opt_unlink_close) { - if ((fd->stream.unlink_close = strdup(filename)) == NULL) { - Error1("strdup(\"%s\"): out of memory", filename); - } - fd->stream.opt_unlink_close = true; - } - - /* save options, because we might have to start again with Socket() */ - opts2 = copyopts(opts, GROUP_ALL); - - if ((fd->stream.fd1 = Socket(PF_UNIX, socktype, 0)) < 0) { - Error2("socket(PF_UNIX, %d, 0): %s", socktype, strerror(errno)); - return STAT_RETRYLATER; - } - fd->stream.fd2 = fd->stream.fd1; - fd->stream.fdtype = FDTYPE_SINGLE; - 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.fd1, opts); - - sa.sun_family = AF_UNIX; - salen = xiosetunix(&sa, filename, false, false); - -#if 0 - applyopts(fd->stream.fd1, opts, PH_PREBIND); - applyopts(fd->stream.fd1, opts, PH_BIND); - if (us) { - if (Bind(fd->stream.fd1, us, uslen) < 0) { - Error4("bind(%d, {%s}, "F_Zd"): %s", - fd->fd, sockaddr_info(us, infobuff, sizeof(infobuff)), - uslen, strerror(errno)); - if (fd->forever || --fd->retry) { - Nanosleep(&fd->intervall, NULL); - continue; - } else - return STAT_RETRYLATER; - } - } - applyopts(fd->stream.fd1, opts, PH_PASTBIND); -#endif /* 0 */ - - applyopts(fd->stream.fd1, opts, PH_CONNECT); - if ((result = Connect(fd->stream.fd1, (struct sockaddr *)&sa, salen)) < 0) { - if (errno == EINPROGRESS) { - Warn4("connect(%d, %s, "F_Zd"): %s", - fd->stream.fd1, sockaddr_unix_info(&sa, salen, infobuff, sizeof(infobuff)), - sizeof(sa), strerror(errno)); - } else if (errno == EPROTOTYPE && optsotype != SOCK_STREAM) { - Warn4("connect(%d, %s, "F_Zd"): %s", - fd->stream.fd1, sockaddr_unix_info(&sa, salen, infobuff, sizeof(infobuff)), - sizeof(sa), strerror(errno)); - Info("assuming datagram socket"); - Close(fd->stream.fd1); - - opts = opts2; - if ((fd->stream.fd1 = Socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) { - Error1("socket(PF_UNIX, SOCK_DGRAM, 0): %s", strerror(errno)); - return STAT_RETRYLATER; - } - /*0 Info1("socket(PF_UNIX, SOCK_DGRAM, 0) -> %d", fd->stream.fd1);*/ - - applyopts(fd->stream.fd1, opts, PH_PASTSOCKET); - applyopts(fd->stream.fd1, opts, PH_FD); - - applyopts_cloexec(fd->stream.fd1, opts); - - sa.sun_family = AF_UNIX; - strncpy(sa.sun_path, filename, sizeof(sa.sun_path)); - - fd->stream.dtype = XIODATA_RECVFROM; - fd->stream.salen = sizeof(sa); - memcpy(&fd->stream.peersa.soa, &sa, fd->stream.salen); - } else { - Error4("connect(%d, %s, "F_Zd"): %s", - fd->stream.fd1, sockaddr_unix_info(&sa, fd->stream.salen, infobuff, sizeof(infobuff)), - sizeof(sa), strerror(errno)); - return STAT_RETRYLATER; - } - } - if (fd->stream.howtoshut == XIOSHUT_UNSPEC) - fd->stream.howtoshut = XIOSHUT_CLOSE; - if (fd->stream.howtoclose == XIOCLOSE_UNSPEC) - fd->stream.howtoclose = XIOCLOSE_CLOSE; - - applyopts_fchown(fd->stream.fd1, opts); - applyopts(fd->stream.fd1, opts, PH_CONNECTED); - applyopts(fd->stream.fd1, opts, PH_LATE); applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */ if (Getsockname(fd->stream.fd1, (struct sockaddr *)&us, &uslen) < 0) { @@ -171,7 +70,8 @@ static int xioopen_gopen1(int argc, const char *argv[], struct opt *opts, int xi fd->stream.fd1, &us, uslen, strerror(errno)); } else { Notice1("successfully connected via %s", - sockaddr_unix_info(&us, uslen, infobuff, sizeof(infobuff))); + sockaddr_unix_info(&us.un, uslen, + infobuff, sizeof(infobuff))); } #else Error("\"%s\" is a socket, but UNIX socket support is not compiled in"); @@ -190,6 +90,10 @@ static int xioopen_gopen1(int argc, const char *argv[], struct opt *opts, int xi } fd->stream.opt_unlink_close = true; } + if (fd->stream.howtoshut == XIOSHUT_UNSPEC) + fd->stream.howtoshut = XIOSHUT_NONE; + if (fd->stream.howtoclose == XIOCLOSE_UNSPEC) + fd->stream.howtoclose = XIOCLOSE_CLOSE; Notice3("opening %s \"%s\" for %s", filetypenames[(st_mode&S_IFMT)>>12], filename, ddirection[(xioflags&XIO_ACCMODE)]); @@ -202,10 +106,6 @@ static int xioopen_gopen1(int argc, const char *argv[], struct opt *opts, int xi Ioctl(result, I_PUSH, "ttcompat"); } #endif - 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 diff --git a/xio-interface.c b/xio-interface.c new file mode 100644 index 0000000..587ea5d --- /dev/null +++ b/xio-interface.c @@ -0,0 +1,105 @@ +/* source: xio-interface.c */ +/* Copyright Gerhard Rieger 2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +/* this file contains the source for opening addresses of raw socket type */ + +#include "xiosysincludes.h" + +#if WITH_INTERFACE + +#include "xioopen.h" +#include "xio-socket.h" + +#include "xio-interface.h" + + +static +int xioopen_interface(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xfd, unsigned groups, int dummy, + int dummy2, int dummy3); + +const struct xioaddr_endpoint_desc xioaddr_interface1 = { XIOADDR_SYS, "interface", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_interface, 0, 0, 0 HELP(":") }; +const union xioaddr_desc *xioaddrs_interface[] = { + (union xioaddr_desc *)&xioaddr_interface1, + NULL +}; + +static +int _xioopen_interface(const char *ifname, + struct opt *opts, int xioflags, xiofile_t *xxfd, + unsigned groups) { + xiosingle_t *xfd = &xxfd->stream; + int pf = PF_PACKET; + union sockaddr_union us = {{0}}; + socklen_t uslen; + int socktype = SOCK_RAW; + unsigned int ifidx; + bool needbind = false; + char *bindstring = NULL; + struct sockaddr_ll sall = { 0 }; + + if (ifindex(ifname, &ifidx, -1) < 0) { + Error1("unknown interface \"%s\"", ifname); + ifidx = 0; /* desparate attempt to continue */ + } + + retropt_int(opts, OPT_SO_TYPE, &socktype); + + retropt_socket_pf(opts, &pf); + + /* ...res_opts[] */ + if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + applyopts(-1, opts, PH_INIT); + + xfd->salen = sizeof(xfd->peersa); + if (pf == PF_UNSPEC) { + pf = xfd->peersa.soa.sa_family; + } + + xfd->dtype = XIODATA_RECVFROM_SKIPIP; + + if (retropt_string(opts, OPT_BIND, &bindstring)) { + needbind = true; + } + /*!!! parse by ':' */ + ((struct sockaddr_ll *)&us)->sll_family = pf; + ((struct sockaddr_ll *)&us)->sll_protocol = htons(ETH_P_ALL); + ((struct sockaddr_ll *)&us)->sll_ifindex = ifidx; + uslen = sizeof(sall); + needbind = true; + xfd->peersa = (union sockaddr_union)us; + + return + _xioopen_dgram_sendto(needbind?&us:NULL, uslen, + opts, xioflags, xfd, groups, pf, socktype, 0); +} + +static +int xioopen_interface(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xxfd, unsigned groups, + int summy, int dummy2, int dummy3) { + xiosingle_t *xfd = &xxfd->stream; + int result; + + if (argc != 2) { + Error2("%s: wrong number of parameters (%d instead of 1)", + argv[0], argc-1); + return STAT_NORETRY; + } + + if ((result = + _xioopen_interface(argv[1], opts, xioflags, xxfd, groups)) + != STAT_OK) { + return result; + } + + xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO; + + xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family; + + _xio_openlate(xfd, opts); + return STAT_OK; +} + +#endif /* WITH_INTERFACE */ diff --git a/xio-interface.h b/xio-interface.h new file mode 100644 index 0000000..69cc6f1 --- /dev/null +++ b/xio-interface.h @@ -0,0 +1,10 @@ +/* source: xio-interface.h */ +/* Copyright Gerhard Rieger 2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +#ifndef __xio_interface_h_included +#define __xio_interface_h_included 1 + +extern const union xioaddr_desc *xioaddrs_interface[]; + +#endif /* !defined(__xio_interface_h_included) */ diff --git a/xio-ip.c b/xio-ip.c index df5a5b6..365f066 100644 --- a/xio-ip.c +++ b/xio-ip.c @@ -9,6 +9,8 @@ #if _WITH_IP4 || _WITH_IP6 #include "xioopen.h" + +#include "xio-ascii.h" #include "xio-socket.h" #include "xio-ip.h" #include "xio-ip6.h" @@ -25,7 +27,7 @@ const struct optdesc opt_ip_pktinfo = { "ip-pktinfo", "pktinfo", OPT_IP_PKTINF #ifdef IP_RECVTOS const struct optdesc opt_ip_recvtos = { "ip-recvtos", "recvtos", OPT_IP_RECVTOS, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_RECVTOS }; #endif -#ifdef IP_RECVTTL +#ifdef IP_RECVTTL /* -Cygwin */ const struct optdesc opt_ip_recvttl = { "ip-recvttl", "recvttl", OPT_IP_RECVTTL, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_RECVTTL }; #endif #ifdef IP_RECVOPTS @@ -56,7 +58,8 @@ const struct optdesc opt_ip_router_alert={"ip-router-alert","routeralert",OPT_IP #endif /* following: Linux allows int but OpenBSD reqs char/byte */ const struct optdesc opt_ip_multicast_ttl={"ip-multicast-ttl","multicastttl",OPT_IP_MULTICAST_TTL,GROUP_SOCK_IP,PH_PASTSOCKET,TYPE_BYTE,OFUNC_SOCKOPT,SOL_IP,IP_MULTICAST_TTL}; -const struct optdesc opt_ip_multicast_loop={"ip-multicast-loop","multicastloop",OPT_IP_MULTICAST_LOOP,GROUP_SOCK_IP,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_IP,IP_MULTICAST_LOOP}; +/* following: Linux allows int but OpenBSD reqs char/byte */ +const struct optdesc opt_ip_multicast_loop={"ip-multicast-loop","multicastloop",OPT_IP_MULTICAST_LOOP,GROUP_SOCK_IP,PH_PASTSOCKET,TYPE_BYTE,OFUNC_SOCKOPT,SOL_IP,IP_MULTICAST_LOOP}; const struct optdesc opt_ip_multicast_if ={"ip-multicast-if", "multicast-if", OPT_IP_MULTICAST_IF, GROUP_SOCK_IP,PH_PASTSOCKET,TYPE_IP4NAME,OFUNC_SOCKOPT,SOL_IP,IP_MULTICAST_IF}; #ifdef IP_PKTOPTIONS const struct optdesc opt_ip_pktoptions = { "ip-pktoptions", "pktopts", OPT_IP_PKTOPTIONS, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_PKTOPTIONS }; @@ -64,6 +67,12 @@ const struct optdesc opt_ip_pktoptions = { "ip-pktoptions", "pktopts", OPT_IP_PK #ifdef IP_ADD_MEMBERSHIP const struct optdesc opt_ip_add_membership = { "ip-add-membership", "membership",OPT_IP_ADD_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IP, IP_ADD_MEMBERSHIP }; #endif +#ifdef IP_RECVDSTADDR +const struct optdesc opt_ip_recvdstaddr = { "ip-recvdstaddr", "recvdstaddr",OPT_IP_RECVDSTADDR, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_RECVDSTADDR }; +#endif +#ifdef IP_RECVIF +const struct optdesc opt_ip_recvif = { "ip-recvif", "recvdstaddrif",OPT_IP_RECVIF, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_RECVIF }; +#endif #if HAVE_RESOLV_H const struct optdesc opt_res_debug = { "res-debug", NULL, OPT_RES_DEBUG, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, (size_t)&((xiosingle_t *)0)->para.socket.ip.res_opts, sizeof(unsigned long), RES_DEBUG }; @@ -204,6 +213,18 @@ int xiogetaddrinfo(const char *node, const char *service, if (node != NULL || service != NULL) { struct addrinfo *record; + if (socktype != SOCK_STREAM && socktype != SOCK_DGRAM) { + /* actual socket type value is not supported - fallback to a good one */ + socktype = SOCK_DGRAM; + } + if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) { + /* actual protocol value is not supported - fallback to a good one */ + if (socktype == SOCK_DGRAM) { + protocol = IPPROTO_UDP; + } else { + protocol = IPPROTO_TCP; + } + } hints.ai_flags |= AI_PASSIVE; hints.ai_family = family; hints.ai_socktype = socktype; @@ -423,89 +444,121 @@ int xiogetaddrinfo(const char *node, const char *service, } -int xioparsenetwork(const char *rangename, int pf, union xiorange_union *range) { -#if WITH_IP4 - struct in_addr *netaddr_in = &range->ip4.netaddr; - struct in_addr *netmask_in = &range->ip4.netmask; -#endif /* WITH_IP4 */ - struct hostent *maskaddr; - char *delimpos; /* absolute address of delimiter */ - int bits; +#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA) +/* these are valid for IPv4 and IPv6 */ +int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num, + char *typbuff, int typlen, + char *nambuff, int namlen, + char *envbuff, int envlen, + char *valbuff, int vallen) { + const char *cmsgtype, *cmsgname = NULL, *cmsgenvn = NULL, *cmsgfmt = NULL; + size_t msglen; + char scratch1[16]; /* can hold an IPv4 address in ASCII */ + char scratch2[16]; + char scratch3[16]; - switch (pf) { -#if WITH_IP4 - char *rangename1; /* a copy of rangename with writing allowed */ - case PF_INET: - if ((rangename1 = strdup(rangename)) == NULL) { - Error1("strdup(\"%s\"): out of memory", rangename); - return STAT_RETRYLATER; - } - - if (delimpos = strchr(rangename1, '/')) { - bits = strtoul(delimpos+1, NULL, 10); - netmask_in->s_addr = htonl((0xffffffff << (32-bits))); - } else if (delimpos = strchr(rangename1, ':')) { - if ((maskaddr = Gethostbyname(delimpos+1)) == NULL) { - Error2("gethostbyname(\"%s\"): %s", delimpos+1, - h_errno == NETDB_INTERNAL ? strerror(errno) : - hstrerror(h_errno)); - return STAT_NORETRY; - } - netmask_in->s_addr = *(uint32_t *)maskaddr->h_addr_list[0]; - } else { - Error1("xioparsenetwork(\"%s\",,): missing netmask delimiter", rangename); - free(rangename1); - return STAT_NORETRY; - } - { - struct hostent *nameaddr; - *delimpos = 0; - if ((nameaddr = Gethostbyname(rangename1)) == NULL) { - Error2("gethostbyname(\"%s\"): %s", rangename1, - h_errno == NETDB_INTERNAL ? strerror(errno) : - hstrerror(h_errno)); - free(rangename1); - return STAT_NORETRY; - } - netaddr_in->s_addr = *(unsigned long *)nameaddr->h_addr_list[0]; - } - free(rangename1); - break; -#endif /* WITH_IP4 */ -#if WITH_IP6 - case PF_INET6: - return xioparsenetwork_ip6(rangename, &range->ip6); - break; -#endif /* WITH_IP6 */ - default: - Error1("range option not supported with address family %d", pf); - return STAT_NORETRY; - } - return STAT_OK; -} - -/* parses a string of form address/bits or address:mask, and fills the fields - of the range union. The addr component is masked with mask. */ -int parserange(const char *rangename, int pf, union xiorange_union *range) { - if (xioparsenetwork(rangename, pf, range) < 0) { - return -1; - } - switch (pf) { -#if WITH_IP4 - case PF_INET: - range->ip4.netaddr.s_addr &= range->ip4.netmask.s_addr; - break; -#endif /* WITH_IP4 */ -#if WITH_IP6 - case PF_INET6: - return xiorange_ip6andmask(&range->ip6); - break; -#endif /* WITH_IP6 */ + msglen = cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg); + envbuff[0] = '\0'; + switch (cmsg->cmsg_type) { default: - Error1("range option not supported with address family %d", pf); - return STAT_NORETRY; + *num = 1; + strncpy(typbuff, "IP", typlen); + snprintf(nambuff, namlen, "type_%u", cmsg->cmsg_type); + xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0); + return STAT_OK; +#if WITH_IP4 +#if defined(IP_PKTINFO) && HAVE_STRUCT_IN_PKTINFO + case IP_PKTINFO: { + struct in_pktinfo *pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); + *num = 3; + strncpy(typbuff, "IP_PKTINFO", typlen); + snprintf(nambuff, namlen, "%s%c%s%c%s", "if", '\0', "locaddr", '\0', "dstaddr"); + snprintf(envbuff, envlen, "%s%c%s%c%s", "IP_IF", '\0', + "IP_LOCADDR", '\0', "IP_DSTADDR"); + snprintf(valbuff, vallen, "%s%c%s%c%s", + xiogetifname(pktinfo->ipi_ifindex, scratch1, -1), '\0', + inet4addr_info(ntohl(pktinfo->ipi_spec_dst.s_addr), scratch2, sizeof(scratch2)), '\0', + inet4addr_info(ntohl(pktinfo->ipi_addr.s_addr), scratch3, sizeof(scratch3))); } - return 0; + return STAT_OK; +#endif /* defined(IP_PKTINFO) && HAVE_STRUCT_IN_PKTINFO */ +#endif /* WITH_IP4 */ +#ifdef IP_RECVERR + case IP_RECVERR: { + struct sock_extended_err *err = + (struct sock_extended_err *)CMSG_DATA(cmsg); + *num = 6; + strncpy(typbuff, "IP_RECVERR", typlen); + snprintf(nambuff, namlen, "%s%c%s%c%s%c%s%c%s%c%s", + "errno", '\0', "origin", '\0', "type", '\0', + "code", '\0', "info", '\0', "data"); + snprintf(envbuff, envlen, "%s%c%s%c%s%c%s%c%s%c%s", + "IP_RECVERR_ERRNO", '\0', "IP_RECVERR_ORIGIN", '\0', + "IP_RECVERR_TYPE", '\0', "IP_RECVERR_CODE", '\0', + "IP_RECVERR_INFO", '\0', "IP_RECVERR_DATA"); + snprintf(valbuff, vallen, "%u%c%u%c%u%c%u%c%u%c%u", + err->ee_errno, '\0', err->ee_origin, '\0', err->ee_type, '\0', + err->ee_code, '\0', err->ee_info, '\0', err->ee_data); + return STAT_OK; + } +#endif /* IP_RECVERR */ +#ifdef IP_RECVIF + case IP_RECVIF: { + /* spec in FreeBSD: /usr/include/net/if_dl.h */ + struct sockaddr_dl *sadl = (struct sockaddr_dl *)CMSG_DATA(cmsg); + *num = 1; + strncpy(typbuff, "IP_RECVIF", typlen); + strncpy(nambuff, "if", namlen); + strncpy(envbuff, "IP_IF", envlen); + strncpy(valbuff, + xiosubstr(scratch1, sadl->sdl_data, 0, sadl->sdl_nlen), vallen); + return STAT_OK; + } +#endif /* defined(IP_RECVIF) */ +#if WITH_IP4 +#ifdef IP_RECVDSTADDR + case IP_RECVDSTADDR: + *num = 1; + strncpy(typbuff, "IP_RECVDSTADDR", typlen); + strncpy(nambuff, "dstaddr", namlen); + strncpy(envbuff, "IP_DSTADDR", envlen); + inet4addr_info(ntohl(*(uint32_t *)CMSG_DATA(cmsg)), valbuff, vallen); + return STAT_OK; +#endif +#endif /* WITH_IP4 */ + case IP_OPTIONS: +#ifdef IP_RECVOPTS + case IP_RECVOPTS: +#endif + cmsgtype = "IP_OPTIONS"; cmsgname = "options"; cmsgfmt = NULL; break; + case IP_TOS: + cmsgtype = "IP_TOS"; cmsgname = "tos"; cmsgfmt = "%u"; break; + case IP_TTL: /* Linux */ +#ifdef IP_RECVTTL + case IP_RECVTTL: /* FreeBSD */ +#endif + cmsgtype = "IP_TTL"; cmsgname = "ttl"; cmsgfmt = "%u"; break; + } + /* when we come here we provide a single parameter + with type in cmsgtype, name in cmsgname, printf format in cmsgfmt */ + *num = 1; + if (strlen(cmsgtype) >= typlen) Fatal("buff too short"); + strncpy(typbuff, cmsgtype, typlen); + if (strlen(cmsgname) >= namlen) Fatal("buff too short"); + strncpy(nambuff, cmsgname, namlen); + if (cmsgenvn) { + if (strlen(cmsgenvn) >= envlen) Fatal("buff too short"); + strncpy(envbuff, cmsgenvn, envlen); + } else { + envbuff[0] = '\0'; + } + if (cmsgfmt != NULL) { + snprintf(valbuff, vallen, cmsgfmt, *(unsigned char *)CMSG_DATA(cmsg)); + } else { + xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0); + } + return STAT_OK; } +#endif /* defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA) */ #endif /* _WITH_IP4 || _WITH_IP6 */ diff --git a/xio-ip.h b/xio-ip.h index 4d68012..5ec9ff6 100644 --- a/xio-ip.h +++ b/xio-ip.h @@ -1,5 +1,5 @@ /* source: xio-ip.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_ip_h_included @@ -24,6 +24,8 @@ extern const struct optdesc opt_ip_multicast_loop; extern const struct optdesc opt_ip_multicast_if; extern const struct optdesc opt_ip_pktoptions; extern const struct optdesc opt_ip_add_membership; +extern const struct optdesc opt_ip_recvdstaddr; +extern const struct optdesc opt_ip_recvif; extern const struct optdesc opt_res_debug; extern const struct optdesc opt_res_aaonly; @@ -40,9 +42,10 @@ extern int xiogetaddrinfo(const char *node, const char *service, union sockaddr_union *sa, socklen_t *socklen, unsigned long res_opts0, unsigned long res_opts1); extern -int xioparsenetwork(const char *rangename, int pf, - union xiorange_union *range); -extern -int parserange(const char *rangename, int pf, union xiorange_union *range); +int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num, + char *typbuff, int typlen, + char *nambuff, int namlen, + char *envbuff, int envlen, + char *valbuff, int vallen); #endif /* !defined(__xio_ip_h_included) */ diff --git a/xio-ip4.c b/xio-ip4.c index 6e8ff23..076ce1f 100644 --- a/xio-ip4.c +++ b/xio-ip4.c @@ -1,5 +1,5 @@ /* source: xio-ip4.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for IP4 related functions */ @@ -13,11 +13,59 @@ #include "xio-ip.h" #include "xio-ip4.h" + +int xioparsenetwork_ip4(const char *rangename, struct xiorange *range) { + struct hostent *maskaddr; + struct in_addr *netaddr_in = &range->netaddr.ip4.sin_addr; + struct in_addr *netmask_in = &range->netmask.ip4.sin_addr; + char *rangename1; /* a copy of rangename with writing allowed */ + char *delimpos; /* absolute address of delimiter */ + int bits; + + if ((rangename1 = strdup(rangename)) == NULL) { + Error1("strdup(\"%s\"): out of memory", rangename); + return STAT_RETRYLATER; + } + + if (delimpos = strchr(rangename1, '/')) { + bits = strtoul(delimpos+1, NULL, 10); + netmask_in->s_addr = htonl((0xffffffff << (32-bits))); + } else if (delimpos = strchr(rangename1, ':')) { + if ((maskaddr = Gethostbyname(delimpos+1)) == NULL) { + /* note: cast is req on AIX: */ + Error2("gethostbyname(\"%s\"): %s", delimpos+1, + h_errno == NETDB_INTERNAL ? strerror(errno) : + (char *)hstrerror(h_errno)); + return STAT_NORETRY; + } + netmask_in->s_addr = *(uint32_t *)maskaddr->h_addr_list[0]; + } else { + Error1("xioparsenetwork_ip4(\"%s\",,): missing netmask delimiter", rangename); + free(rangename1); + return STAT_NORETRY; + } + { + struct hostent *nameaddr; + *delimpos = 0; + if ((nameaddr = Gethostbyname(rangename1)) == NULL) { + /* note: cast is req on AIX: */ + Error2("gethostbyname(\"%s\"): %s", rangename1, + h_errno == NETDB_INTERNAL ? strerror(errno) : + (char *)hstrerror(h_errno)); + free(rangename1); + return STAT_NORETRY; + } + netaddr_in->s_addr = *(unsigned long *)nameaddr->h_addr_list[0]; + } + free(rangename1); + return STAT_OK; +} + /* check if peer address is within permitted range. return >= 0 if so. */ -int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange_ip4 *range) { - struct in_addr *netaddr_in = &range->netaddr; - struct in_addr *netmask_in = &range->netmask; +int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange *range) { + struct in_addr *netaddr_in = &range->netaddr.ip4.sin_addr; + struct in_addr *netmask_in = &range->netmask.ip4.sin_addr; char addrbuf[256], maskbuf[256]; char peername[256]; @@ -43,4 +91,41 @@ int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange_ip4 *range) { return 0; } +/* returns information that can be used for constructing an environment + variable describing the socket address. + if idx is 0, this function writes "ADDR" into namebuff and the IP address + into valuebuff, and returns 1 (which means that one more info is there). + if idx is 1, it writes "PORT" into namebuff and the port number into + valuebuff, and returns 0 (no more info) + namelen and valuelen contain the max. allowed length of output chars in the + respective buffer. + on error this function returns -1. +*/ +int +xiosetsockaddrenv_ip4(int idx, char *namebuff, size_t namelen, + char *valuebuff, size_t valuelen, + struct sockaddr_in *sa, int ipproto) { + switch (idx) { + case 0: + strcpy(namebuff, "ADDR"); + strcpy(valuebuff, + inet4addr_info(ntohl(sa->sin_addr.s_addr), valuebuff, valuelen)); + switch (ipproto) { + case IPPROTO_TCP: + case IPPROTO_UDP: +#ifdef IPPROTO_SCTP + case IPPROTO_SCTP: +#endif + return 1; /* there is port information to also be retrieved */ + default: + return 0; /* no port info coming */ + } + case 1: + strcpy(namebuff, "PORT"); + snprintf(valuebuff, valuelen, "%u", ntohs(sa->sin_port)); + return 0; + } + return -1; +} + #endif /* WITH_IP4 */ diff --git a/xio-ip4.h b/xio-ip4.h index 9357dcc..2bd11ce 100644 --- a/xio-ip4.h +++ b/xio-ip4.h @@ -1,5 +1,5 @@ /* source: xio-ip4.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_ip4_h_included @@ -7,7 +7,12 @@ extern const struct optdesc opt_ip4_add_membership; +int xioparsenetwork_ip4(const char *rangename, struct xiorange *range); extern -int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange_ip4 *range); +int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange *range); +extern int +xiosetsockaddrenv_ip4(int idx, char *namebuff, size_t namelen, + char *valuebuff, size_t valuelen, + struct sockaddr_in *sa, int ipproto); #endif /* !defined(__xio_ip4_h_included) */ diff --git a/xio-ip6.c b/xio-ip6.c index 0bf8577..9a729f6 100644 --- a/xio-ip6.c +++ b/xio-ip6.c @@ -1,5 +1,5 @@ /* source: xio-ip6.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for IP6 related functions */ @@ -9,27 +9,71 @@ #if WITH_IP6 #include "xioopen.h" +#include "xio-ascii.h" #include "xio-socket.h" #include "xio-ip.h" /* xiogetaddrinfo() */ #include "xio-ip6.h" + +static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen); + + #ifdef IPV6_V6ONLY const struct optdesc opt_ipv6_v6only = { "ipv6-v6only", "ipv6only", OPT_IPV6_V6ONLY, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_V6ONLY }; #endif #ifdef IPV6_JOIN_GROUP const struct optdesc opt_ipv6_join_group = { "ipv6-join-group", "join-group", OPT_IPV6_JOIN_GROUP, GROUP_SOCK_IP6, PH_PASTBIND, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IPV6, IPV6_JOIN_GROUP }; #endif +const struct optdesc opt_ipv6_pktinfo = { "ipv6-pktinfo", "pktinfo", OPT_IPV6_PKTINFO, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_PKTINFO }; +#ifdef IPV6_RECVPKTINFO +const struct optdesc opt_ipv6_recvpktinfo = { "ipv6-recvpktinfo", "recvpktinfo", OPT_IPV6_RECVPKTINFO, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVPKTINFO }; +#endif +const struct optdesc opt_ipv6_rthdr = { "ipv6-rthdr", "rthdr", OPT_IPV6_RTHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RTHDR }; +#ifdef IPV6_RECVRTHDR +const struct optdesc opt_ipv6_recvrthdr = { "ipv6-recvrthdr", "recvrthdr", OPT_IPV6_RECVRTHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVRTHDR }; +#endif +#ifdef IPV6_AUTHHDR +const struct optdesc opt_ipv6_authhdr = { "ipv6-authhdr", "authhdr", OPT_IPV6_AUTHHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_AUTHHDR }; +#endif +const struct optdesc opt_ipv6_dstopts = { "ipv6-dstopts", "dstopts", OPT_IPV6_DSTOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_DSTOPTS }; +#ifdef IPV6_RECVDSTOPTS +const struct optdesc opt_ipv6_recvdstopts = { "ipv6-recvdstopts", "recvdstopts", OPT_IPV6_RECVDSTOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVDSTOPTS }; +#endif +const struct optdesc opt_ipv6_hopopts = { "ipv6-hopopts", "hopopts", OPT_IPV6_HOPOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_HOPOPTS }; +#ifdef IPV6_RECVHOPOPTS +const struct optdesc opt_ipv6_recvhopopts = { "ipv6-recvhopopts", "recvhopopts", OPT_IPV6_RECVHOPOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVHOPOPTS }; +#endif +#ifdef IPV6_FLOWINFO /* is in linux/in6.h */ +const struct optdesc opt_ipv6_flowinfo= { "ipv6-flowinfo","flowinfo",OPT_IPV6_FLOWINFO,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_FLOWINFO }; +#endif +const struct optdesc opt_ipv6_hoplimit= { "ipv6-hoplimit","hoplimit",OPT_IPV6_HOPLIMIT,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_HOPLIMIT }; +const struct optdesc opt_ipv6_unicast_hops= { "ipv6-unicast-hops","unicast-hops",OPT_IPV6_UNICAST_HOPS,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_UNICAST_HOPS }; +#ifdef IPV6_RECVHOPLIMIT +const struct optdesc opt_ipv6_recvhoplimit= { "ipv6-recvhoplimit","recvhoplimit",OPT_IPV6_RECVHOPLIMIT,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVHOPLIMIT }; +#endif +#ifdef IPV6_RECVERR +const struct optdesc opt_ipv6_recverr = { "ipv6-recverr", "recverr", OPT_IPV6_RECVERR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVERR }; +#endif +#ifdef IPV6_TCLASS +const struct optdesc opt_ipv6_tclass = { "ipv6-tclass", "tclass", OPT_IPV6_TCLASS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_TCLASS }; +#endif +#ifdef IPV6_RECVTCLASS +const struct optdesc opt_ipv6_recvtclass = { "ipv6-recvtclass", "recvtclass", OPT_IPV6_RECVTCLASS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVTCLASS }; +#endif +#ifdef IPV6_RECVPATHMTU +const struct optdesc opt_ipv6_recvpathmtu = { "ipv6-recvpathmtu", "recvpathmtu", OPT_IPV6_RECVPATHMTU, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVPATHMTU }; +#endif -int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *range) { +int xioparsenetwork_ip6(const char *rangename, struct xiorange *range) { char *delimpos; /* absolute address of delimiter */ size_t delimind; /* index of delimiter in string */ int bits; char *baseaddr; union sockaddr_union sockaddr; socklen_t sockaddrlen = sizeof(sockaddr); - union xioin6_u *rangeaddr = (union xioin6_u *)&range->addr; - union xioin6_u *rangemask = (union xioin6_u *)&range->mask; + union xioin6_u *rangeaddr = (union xioin6_u *)&range->netaddr.ip6.sin6_addr; + union xioin6_u *rangemask = (union xioin6_u *)&range->netmask.ip6.sin6_addr; union xioin6_u *nameaddr = (union xioin6_u *)&sockaddr.ip6.sin6_addr; if (rangename[0] != '[' || rangename[strlen(rangename)-1] != ']') { @@ -87,7 +131,7 @@ int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *range) { return 0; } -int xiorange_ip6andmask(struct xiorange_ip6 *range) { +int xiorange_ip6andmask(struct xiorange *range) { int i; #if 0 range->addr.s6_addr32[0] &= range->mask.s6_addr32[0]; @@ -96,7 +140,8 @@ int xiorange_ip6andmask(struct xiorange_ip6 *range) { range->addr.s6_addr32[3] &= range->mask.s6_addr32[3]; #else for (i = 0; i < 16; ++i) { - range->addr.s6_addr[i] &= range->mask.s6_addr[i]; + range->netaddr.ip6.sin6_addr.s6_addr[i] &= + range->netmask.ip6.sin6_addr.s6_addr[i]; } #endif return 0; @@ -104,12 +149,12 @@ int xiorange_ip6andmask(struct xiorange_ip6 *range) { /* check if peer address is within permitted range. return >= 0 if so. */ -int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange_ip6 *range) { +int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range) { union xioin6_u masked; int i; char peername[256]; - union xioin6_u *rangeaddr = (union xioin6_u *)&range->addr; - union xioin6_u *rangemask = (union xioin6_u *)&range->mask; + union xioin6_u *rangeaddr = (union xioin6_u *)&range->netaddr.ip6.sin6_addr; + union xioin6_u *rangemask = (union xioin6_u *)&range->netmask.ip6; Debug16("permitted client subnet: [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]", htons(rangeaddr->u6_addr16[0]), htons(rangeaddr->u6_addr16[1]), @@ -142,4 +187,202 @@ int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange_ip6 *range) { return 0; } + +#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA) +/* provides info about the ancillary message */ +int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num, + char *typbuff, int typlen, + char *nambuff, int namlen, + char *envbuff, int envlen, + char *valbuff, int vallen) { + char scratch1[42]; /* can hold an IPv6 address in ASCII */ + char scratch2[32]; + size_t msglen; + + *num = 1; /* good for most message types */ + msglen = cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg); + envbuff[0] = '\0'; + switch (cmsg->cmsg_type) { + case IPV6_PKTINFO: { + struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg); + *num = 2; + strncpy(typbuff, "IPV6_PKTINFO", typlen); + snprintf(nambuff, namlen, "%s%c%s", "dstaddr", '\0', "if"); + snprintf(envbuff, envlen, "%s%c%s", "IPV6_DSTADDR", '\0', "IPV6_IF"); + snprintf(valbuff, vallen, "%s%c%s", + inet6addr_info(&pktinfo->ipi6_addr, scratch1, sizeof(scratch1)), + '\0', xiogetifname(pktinfo->ipi6_ifindex, scratch2, -1)); + } + return STAT_OK; + case IPV6_HOPLIMIT: + strncpy(typbuff, "IPV6_HOPLIMIT", typlen); + strncpy(nambuff, "hoplimit", namlen); + snprintf(valbuff, vallen, "%d", *(int *)CMSG_DATA(cmsg)); + return STAT_OK; + case IPV6_RTHDR: + strncpy(typbuff, "IPV6_RTHDR", typlen); + strncpy(nambuff, "rthdr", namlen); + xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0); + return STAT_OK; +#ifdef IPV6_AUTHHDR + case IPV6_AUTHHDR: + strncpy(typbuff, "IPV6_AUTHHDR", typlen); + strncpy(nambuff, "authhdr", namlen); + xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0); + return STAT_OK; +#endif + case IPV6_DSTOPTS: + strncpy(typbuff, "IPV6_DSTOPTS", typlen); + strncpy(nambuff, "dstopts", namlen); + xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0); + return STAT_OK; + case IPV6_HOPOPTS: + strncpy(typbuff, "IPV6_HOPOPTS", typlen); + strncpy(nambuff, "hopopts", namlen); + xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0); + return STAT_OK; +#ifdef IPV6_FLOWINFO + case IPV6_FLOWINFO: + strncpy(typbuff, "IPV6_FLOWINFO", typlen); + strncpy(nambuff, "flowinfo", namlen); + xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0); + return STAT_OK; +#endif +#ifdef IPV6_TCLASS + case IPV6_TCLASS: + strncpy(typbuff, "IPV6_TCLASS", typlen); + strncpy(nambuff, "tclass", namlen); + xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0); + return STAT_OK; +#endif + default: + snprintf(typbuff, typlen, "IPV6.%u", cmsg->cmsg_type); + strncpy(nambuff, "data", namlen); + xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0); + return STAT_OK; + } + return STAT_OK; +} +#endif /* defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA) */ + + +/* convert the IP6 socket address to human readable form. buff should be at + least 50 chars long. output includes the port number */ +static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen) { + if (snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]", +#if HAVE_IP6_SOCKADDR==0 + (sa->s6_addr[0]<<8)+sa->s6_addr[1], + (sa->s6_addr[2]<<8)+sa->s6_addr[3], + (sa->s6_addr[4]<<8)+sa->s6_addr[5], + (sa->s6_addr[6]<<8)+sa->s6_addr[7], + (sa->s6_addr[8]<<8)+sa->s6_addr[9], + (sa->s6_addr[10]<<8)+sa->s6_addr[11], + (sa->s6_addr[12]<<8)+sa->s6_addr[13], + (sa->s6_addr[14]<<8)+sa->s6_addr[15] +#elif HAVE_IP6_SOCKADDR==1 + ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[0]), + ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[1]), + ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[2]), + ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[3]), + ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[4]), + ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[5]), + ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[6]), + ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[7]) +#elif HAVE_IP6_SOCKADDR==2 + ntohs(((unsigned short *)&sa->u6_addr16)[0]), + ntohs(((unsigned short *)&sa->u6_addr16)[1]), + ntohs(((unsigned short *)&sa->u6_addr16)[2]), + ntohs(((unsigned short *)&sa->u6_addr16)[3]), + ntohs(((unsigned short *)&sa->u6_addr16)[4]), + ntohs(((unsigned short *)&sa->u6_addr16)[5]), + ntohs(((unsigned short *)&sa->u6_addr16)[6]), + ntohs(((unsigned short *)&sa->u6_addr16)[7]) +#elif HAVE_IP6_SOCKADDR==3 + ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[0]), + ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[1]), + ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[2]), + ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[3]), + ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[4]), + ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[5]), + ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[6]), + ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[7]) +#elif HAVE_IP6_SOCKADDR==4 + (sa->_S6_un._S6_u8[0]<<8)|(sa->_S6_un._S6_u8[1]&0xff), + (sa->_S6_un._S6_u8[2]<<8)|(sa->_S6_un._S6_u8[3]&0xff), + (sa->_S6_un._S6_u8[4]<<8)|(sa->_S6_un._S6_u8[5]&0xff), + (sa->_S6_un._S6_u8[6]<<8)|(sa->_S6_un._S6_u8[7]&0xff), + (sa->_S6_un._S6_u8[8]<<8)|(sa->_S6_un._S6_u8[9]&0xff), + (sa->_S6_un._S6_u8[10]<<8)|(sa->_S6_un._S6_u8[11]&0xff), + (sa->_S6_un._S6_u8[12]<<8)|(sa->_S6_un._S6_u8[13]&0xff), + (sa->_S6_un._S6_u8[14]<<8)|(sa->_S6_un._S6_u8[15]&0xff) +#elif HAVE_IP6_SOCKADDR==5 + ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[0]), + ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[1]), + ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[2]), + ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[3]), + ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[4]), + ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[5]), + ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[6]), + ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[7]) +#endif + ) < 0) { + Warn("sockaddr_inet6_info(): buffer too short"); + buff[blen-1] = '\0'; + } + return buff; +} + + +/* returns information that can be used for constructing an environment + variable describing the socket address. + if idx is 0, this function writes "ADDR" into namebuff and the IP address + into valuebuff, and returns 1 (which means that one more info is there). + if idx is 1, it writes "PORT" into namebuff and the port number into + valuebuff, and returns 0 (no more info) + namelen and valuelen contain the max. allowed length of output chars in the + respective buffer. + on error this function returns -1. +*/ +int +xiosetsockaddrenv_ip6(int idx, char *namebuff, size_t namelen, + char *valuebuff, size_t valuelen, + struct sockaddr_in6 *sa, int ipproto) { + switch (idx) { + case 0: + strcpy(namebuff, "ADDR"); + snprintf(valuebuff, valuelen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]", + (sa->sin6_addr.s6_addr[0]<<8)+ + sa->sin6_addr.s6_addr[1], + (sa->sin6_addr.s6_addr[2]<<8)+ + sa->sin6_addr.s6_addr[3], + (sa->sin6_addr.s6_addr[4]<<8)+ + sa->sin6_addr.s6_addr[5], + (sa->sin6_addr.s6_addr[6]<<8)+ + sa->sin6_addr.s6_addr[7], + (sa->sin6_addr.s6_addr[8]<<8)+ + sa->sin6_addr.s6_addr[9], + (sa->sin6_addr.s6_addr[10]<<8)+ + sa->sin6_addr.s6_addr[11], + (sa->sin6_addr.s6_addr[12]<<8)+ + sa->sin6_addr.s6_addr[13], + (sa->sin6_addr.s6_addr[14]<<8)+ + sa->sin6_addr.s6_addr[15]); + switch (ipproto) { + case IPPROTO_TCP: + case IPPROTO_UDP: +#ifdef IPPROTO_SCTP + case IPPROTO_SCTP: +#endif + return 1; /* there is port information to also be retrieved */ + default: + return 0; /* no port info coming */ + } + case 1: + strcpy(namebuff, "PORT"); + snprintf(valuebuff, valuelen, "%u", ntohs(sa->sin6_port)); + return 0; + } + return -1; +} + #endif /* WITH_IP6 */ diff --git a/xio-ip6.h b/xio-ip6.h index 431d4d1..c0203ff 100644 --- a/xio-ip6.h +++ b/xio-ip6.h @@ -1,5 +1,5 @@ /* source: xio-ip6.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_ip6_h_included @@ -9,13 +9,40 @@ extern const struct optdesc opt_ipv6_v6only; extern const struct optdesc opt_ipv6_join_group; +extern const struct optdesc opt_ipv6_pktinfo; +extern const struct optdesc opt_ipv6_recvpktinfo; +extern const struct optdesc opt_ipv6_rthdr; +extern const struct optdesc opt_ipv6_recvrthdr; +extern const struct optdesc opt_ipv6_authhdr; +extern const struct optdesc opt_ipv6_dstopts; +extern const struct optdesc opt_ipv6_recvdstopts; +extern const struct optdesc opt_ipv6_hopopts; +extern const struct optdesc opt_ipv6_unicast_hops; +extern const struct optdesc opt_ipv6_recvhopopts; +extern const struct optdesc opt_ipv6_flowinfo; +extern const struct optdesc opt_ipv6_hoplimit; +extern const struct optdesc opt_ipv6_recvhoplimit; +extern const struct optdesc opt_ipv6_recverr; +extern const struct optdesc opt_ipv6_tclass; +extern const struct optdesc opt_ipv6_recvtclass; +extern const struct optdesc opt_ipv6_recvpathmtu; extern -int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *range); -extern int xiorange_ip6andmask(struct xiorange_ip6 *range); +int xioparsenetwork_ip6(const char *rangename, struct xiorange *range); +extern int xiorange_ip6andmask(struct xiorange *range); extern -int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange_ip6 *range); +int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range); +extern +int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num, + char *typbuff, int typlen, + char *nambuff, int namlen, + char *envbuff, int envlen, + char *valbuff, int vallen); +extern int +xiosetsockaddrenv_ip6(int idx, char *namebuff, size_t namelen, + char *valuebuff, size_t valuelen, + struct sockaddr_in6 *sa, int ipproto); #endif /* WITH_IP6 */ diff --git a/xio-ipapp.c b/xio-ipapp.c index 75d8d09..6848680 100644 --- a/xio-ipapp.c +++ b/xio-ipapp.c @@ -50,8 +50,8 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, if (_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto, xfd->para.socket.ip.res_opts[1], xfd->para.socket.ip.res_opts[0], - them, &themlen, us, &uslen, &needbind, &lowport, - &socktype) != STAT_OK) { + them, &themlen, us, &uslen, &needbind, &lowport, + socktype) != STAT_OK) { return STAT_NORETRY; } @@ -102,31 +102,27 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, #if WITH_RETRY if (dofork) { pid_t pid; - while ((pid = Fork()) < 0) { - int level = E_ERROR; - if (xfd->forever || --xfd->retry) { - level = E_WARN; /* most users won't expect a problem here, + int level = E_ERROR; + if (xfd->forever || xfd->retry) { + level = E_WARN; /* most users won't expect a problem here, so Notice is too weak */ - } - Msg1(level, "fork(): %s", strerror(errno)); - if (xfd->forever || xfd->retry) { - dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); + } + while ((pid = xio_fork(false, level)) < 0) { + if (xfd->forever || --xfd->retry) { Nanosleep(&xfd->intervall, NULL); continue; } return STAT_RETRYLATER; } - if (pid == 0) { /* child process */ - Info1("just born: TCP client process "F_pid, Getpid()); - /* drop parents locks, reset FIPS... */ - if (xio_forked_inchild() != 0) { - Exit(1); - } + if (pid == 0) { /* child process */ + xfd->forever = false; xfd->retry = 0; break; } + /* parent process */ Notice1("forked off child process "F_pid, pid); Close(xfd->fd1); + /* with and without retry */ Nanosleep(&xfd->intervall, NULL); dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); @@ -137,6 +133,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, break; } } while (true); + /* only "active" process breaks (master without fork, or child) */ if ((result = _xio_openlate(xfd, opts)) < 0) { return result; @@ -145,7 +142,11 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, } -/* returns STAT_OK on success or some other value on failure */ +/* returns STAT_OK on success or some other value on failure + applies and consumes the following options: + PH_EARLY + OPT_PROTOCOL_FAMILY, OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT + */ int _xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0, const char *hostname, @@ -156,7 +157,7 @@ int union sockaddr_union *them, socklen_t *themlen, union sockaddr_union *us, socklen_t *uslen, bool *needbind, bool *lowport, - int *socktype) { + int socktype) { uint16_t port; char infobuff[256]; int result; @@ -165,7 +166,7 @@ int if ((result = xiogetaddrinfo(hostname, portname, - *pf, *socktype, protocol, + *pf, socktype, protocol, (union sockaddr_union *)them, themlen, res_opts0, res_opts1 )) @@ -179,7 +180,7 @@ int applyopts(-1, opts, PH_EARLY); /* 3 means: IP address AND port accepted */ - if (retropt_bind(opts, *pf, *socktype, protocol, (struct sockaddr *)us, uslen, 3, + if (retropt_bind(opts, *pf, socktype, protocol, (struct sockaddr *)us, uslen, 3, res_opts0, res_opts1) != STAT_NOACTION) { *needbind = true; @@ -208,7 +209,6 @@ int } retropt_bool(opts, OPT_LOWPORT, lowport); - retropt_int(opts, OPT_SO_TYPE, socktype); *opts0 = copyopts(opts, GROUP_ALL); @@ -220,22 +220,24 @@ int #if _WITH_TCP && WITH_LISTEN +/* + applies and consumes the following options: + OPT_PROTOCOL_FAMILY, OPT_BIND + */ int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0, const char *portname, int *pf, int ipproto, unsigned long res_opts0, unsigned long res_opts1, union sockaddr_union *us, socklen_t *uslen, - int *socktype) { + int socktype) { char *bindname = NULL; int result; - retropt_int(opts, OPT_SO_TYPE, socktype); - retropt_socket_pf(opts, pf); retropt_string(opts, OPT_BIND, &bindname); if ((result = - xiogetaddrinfo(bindname, portname, *pf, *socktype, ipproto, + xiogetaddrinfo(bindname, portname, *pf, socktype, ipproto, (union sockaddr_union *)us, uslen, res_opts0, res_opts1)) != STAT_OK) { @@ -283,7 +285,7 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts, if (_xioopen_ipapp_listen_prepare(opts, &opts0, argv[1], &pf, ipproto, fd->stream.para.socket.ip.res_opts[1], fd->stream.para.socket.ip.res_opts[0], - us, &uslen, &socktype) + us, &uslen, socktype) != STAT_OK) { return STAT_NORETRY; } diff --git a/xio-ipapp.h b/xio-ipapp.h index ce5ece1..c2dcb1e 100644 --- a/xio-ipapp.h +++ b/xio-ipapp.h @@ -1,5 +1,5 @@ /* source: xio-ipapp.h */ -/* Copyright Gerhard Rieger 2001-2006 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_ipapp_h_included @@ -25,7 +25,7 @@ extern int union sockaddr_union *them, socklen_t *themlen, union sockaddr_union *us, socklen_t *uslen, bool *needbind, bool *lowport, - int *socktype); + int socktype); extern int _xioopen_ip4app_connect(const char *hostname, const char *portname, struct single *xfd, int socktype, int ipproto, void *protname, @@ -39,7 +39,7 @@ extern int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0, unsigned long res_opts0, unsigned long res_opts1, union sockaddr_union *us, socklen_t *uslen, - int *socktype); + int socktype); extern int xioopen_ip6app_connect(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *fd, unsigned groups, int socktype, int ipproto, diff --git a/xio-listen.c b/xio-listen.c index ec4e95c..f64a565 100644 --- a/xio-listen.c +++ b/xio-listen.c @@ -25,6 +25,13 @@ const struct optdesc opt_range = { "range", NULL, OPT_RANGE, GROUP_R #endif +/* + applies and consumes the following option: + PH_INIT, PH_PASTSOCKET, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY, + PH_PREOPEN, PH_FD, PH_CONNECTED, PH_LATE, PH_LATE2 + OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_BACKLOG, OPT_RANGE, tcpwrap, + OPT_SOURCEPORT, OPT_LOWPORT, cloexec + */ int xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, socklen_t uslen, @@ -81,15 +88,24 @@ int } -/* waits for incoming connection, checks its source address and port. Depending - on fork option, it may fork a subprocess. +/* creates the listening socket, bind, applies options; waits for incoming + connection, checks its source address and port. Depending on fork option, it + may fork a subprocess. + pf specifies the syntax expected for range option. In the case of generic + socket it is 0 (expecting raw binary data), and the real pf can be obtained + from us->af_family; for other socket types pf == us->af_family Returns 0 if a connection was accepted; with fork option, this is always in a subprocess! Other return values indicate a problem; this can happen in the master process or in a subprocess. - This function does not retry. If you need retries, handle this is a - loop in the calling function. - after fork, we set the forever/retry of the child process to 0 + This function does not retry. If you need retries, handle this in a + loop in the calling function (and always provide the options...) + After fork, we set the forever/retry of the child process to 0 + applies and consumes the following option: + PH_INIT, PH_PASTSOCKET, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY, + PH_PREOPEN, PH_FD, PH_CONNECTED, PH_LATE, PH_LATE2 + OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_BACKLOG, OPT_RANGE, tcpwrap, + OPT_SOURCEPORT, OPT_LOWPORT, cloexec */ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, socklen_t uslen, struct opt *opts, int pf, int socktype, int proto, int level) { @@ -98,9 +114,14 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl int backlog = 5; /* why? 1 seems to cause problems under some load */ char *rangename; bool dofork = false; - pid_t pid; /* mostly int; only used with fork */ char infobuff[256]; char lisname[256]; + union sockaddr_union _peername; + union sockaddr_union _sockname; + union sockaddr_union *pa = &_peername; /* peer address */ + union sockaddr_union *la = &_sockname; /* local address */ + socklen_t pas = sizeof(_peername); /* peer address size */ + socklen_t las = sizeof(_sockname); /* local address size */ int result; retropt_bool(opts, OPT_FORK, &dofork); @@ -119,9 +140,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl xiosetchilddied(); /* set SIGCHLD handler */ } - if ((xfd->fd1 = Socket(pf, socktype, proto)) < 0) { - Msg4(level, - "socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno)); + if ((xfd->fd1 = xiosocket(opts, us->sa_family, socktype, proto, level)) < 0) { return STAT_RETRYLATER; } xfd->fdtype = FDTYPE_SINGLE; @@ -170,7 +189,8 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl #if WITH_IP4 /*|| WITH_IP6*/ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { - if (parserange(rangename, us->sa_family, &xfd->para.socket.range) < 0) { + if (xioparserange(rangename, pf, &xfd->para.socket.range) + < 0) { free(rangename); return STAT_NORETRY; } @@ -190,6 +210,12 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport); #endif /* WITH_TCP || WITH_UDP */ + retropt_int(opts, OPT_BACKLOG, &backlog); + if (Listen(xfd->fd1, backlog) < 0) { + Error3("listen(%d, %d): %s", xfd->fd1, backlog, strerror(errno)); + return STAT_RETRYLATER; + } + if (xioopts.logopt == 'm') { Info("starting accept loop, switching to syslog"); diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y'; @@ -200,12 +226,6 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl char peername[256]; char sockname[256]; int ps; /* peer socket */ - union sockaddr_union _peername; - union sockaddr_union _sockname; - union sockaddr_union *pa = &_peername; /* peer address */ - union sockaddr_union *la = &_sockname; /* local address */ - socklen_t pas = sizeof(_peername); /* peer address size */ - socklen_t las = sizeof(_sockname); /* local address size */ salen = sizeof(struct sockaddr); do { @@ -233,16 +253,18 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl if (Getpeername(ps, &pa->soa, &pas) < 0) { Warn4("getpeername(%d, %p, {"F_socklen"}): %s", ps, pa, pas, strerror(errno)); + pa = NULL; } if (Getsockname(ps, &la->soa, &las) < 0) { Warn4("getsockname(%d, %p, {"F_socklen"}): %s", - ps, pa, pas, strerror(errno)); + ps, la, las, strerror(errno)); + la = NULL; } Notice2("accepting connection from %s on %s", - sockaddr_info(&pa->soa, pas, peername, sizeof(peername)), - sockaddr_info(&la->soa, las, sockname, sizeof(sockname))); + sockaddr_info(pa?&pa->soa:NULL, pas, peername, sizeof(peername)), + sockaddr_info(pa?&la->soa:NULL, las, sockname, sizeof(sockname))); - if (xiocheckpeer(xfd, pa, la) < 0) { + if (pa != NULL && la != NULL && xiocheckpeer(xfd, pa, la) < 0) { if (Shutdown(ps, 2) < 0) { Info2("shutdown(%d, 2): %s", ps, strerror(errno)); } @@ -254,16 +276,20 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl infobuff, sizeof(infobuff))); applyopts(xfd->fd1, opts, PH_FD); - applyopts(xfd->fd1, opts, PH_CONNECTED); if (dofork) { - if ((pid = Fork()) < 0) { - Msg1(level, "fork(): %s", strerror(errno)); + pid_t pid; /* mostly int; only used with fork */ + if ((pid = xio_fork(false, level==E_ERROR?level:E_WARN)) < 0) { Close(xfd->fd1); return STAT_RETRYLATER; } if (pid == 0) { /* child */ + pid_t cpid = Getpid(); + + Info1("just born: client process "F_pid, cpid); + xiosetenvulong("PID", cpid, 1); + if (Close(xfd->fd1) < 0) { Info2("close(%d): %s", xfd->fd1, strerror(errno)); } @@ -271,16 +297,10 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl #if WITH_RETRY /* !? */ - xfd->retry = 0; - xfd->forever = 0; + xfd->forever = false; xfd->retry = 0; level = E_ERROR; #endif /* WITH_RETRY */ - /* drop parents locks, reset FIPS... */ - if (xio_forked_inchild() != 0) { - Exit(1); - } - #if WITH_UNIX /* with UNIX sockets: only listening parent is allowed to remove the socket file */ @@ -296,7 +316,6 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl if (Close(ps) < 0) { Info2("close(%d): %s", ps, strerror(errno)); } - Notice1("forked off child process "F_pid, pid); Info("still listening"); } else { if (Close(xfd->fd1) < 0) { @@ -309,6 +328,10 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl if ((result = _xio_openlate(xfd, opts)) < 0) return result; + /* set the env vars describing the local and remote sockets */ + xiosetsockaddrenv("SOCK", la, las, proto); + xiosetsockaddrenv("PEER", pa, pas, proto); + return 0; } diff --git a/xio-nop.c b/xio-nop.c index b9fc72a..bc65993 100644 --- a/xio-nop.c +++ b/xio-nop.c @@ -1,4 +1,4 @@ -/* $Id: xio-socks.c,v 1.25 2006/02/08 19:46:59 gerhard Exp $ */ +/* source: xio-nop.c */ /* Copyright Gerhard Rieger 2006-2007 */ /* Published under the GNU General Public License V.2, see file COPYING */ diff --git a/xio-openssl.c b/xio-openssl.c index 2034c49..224b797 100644 --- a/xio-openssl.c +++ b/xio-openssl.c @@ -277,7 +277,7 @@ static int xfd->para.socket.ip.res_opts[1], xfd->para.socket.ip.res_opts[0], them, &themlen, us, &uslen, - &needbind, &lowport, &socktype); + &needbind, &lowport, socktype); if (result != STAT_OK) return STAT_NORETRY; } else if (argc = 1) { @@ -291,7 +291,6 @@ static int applyopts(-1, opts, PH_INIT); retropt_bool(opts, OPT_FORK, &dofork); - retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert); result = @@ -384,30 +383,22 @@ static int #if WITH_RETRY if (dofork) { pid_t pid; - while ((pid = Fork()) < 0) { - int level = E_ERROR; - if (xfd->forever || xfd->retry) { - level = E_WARN; - } - Msg1(level, "fork(): %s", strerror(errno)); - if (xfd->forever || xfd->retry) { - Nanosleep(&xfd->intervall, NULL); - --xfd->retry; - continue; + int level = E_ERROR; + if (xfd->forever || xfd->retry) { + level = E_WARN; + } + while ((pid = xio_fork(false, level)) < 0) { + if (xfd->forever || --xfd->retry) { + Nanosleep(&xfd->intervall, NULL); continue; } return STAT_RETRYLATER; } - if (pid == 0) { /* child process */ - Info1("just born: OpenSSL client process "F_pid, Getpid()); - /* drop parents locks, reset FIPS... */ - if (xio_forked_inchild() != 0) { - Exit(1); - } - xfd->forever = false; - xfd->retry = 0; + if (pid == 0) { /* child process */ + xfd->forever = false; xfd->retry = 0; break; } + /* parent process */ Notice1("forked off child process "F_pid, pid); Close(xfd->fd1); @@ -545,7 +536,7 @@ static int 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) + us, &uslen, socktype) != STAT_OK) { return STAT_NORETRY; } diff --git a/xio-progcall.c b/xio-progcall.c index 27b62a5..d0c31db 100644 --- a/xio-progcall.c +++ b/xio-progcall.c @@ -11,6 +11,9 @@ #include "xio-process.h" #include "xio-progcall.h" +#include "xio-socket.h" + + /* these options are used by address pty too */ #if HAVE_OPENPTY const struct optdesc opt_openpty = { "openpty", NULL, OPT_OPENPTY, GROUP_PTY, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC }; @@ -37,6 +40,8 @@ const struct optdesc opt_sigint = { "sigint", NULL, OPT_SIGINT, GROUP_P const struct optdesc opt_sigquit = { "sigquit", NULL, OPT_SIGQUIT, GROUP_PARENT, PH_LATE, TYPE_CONST, OFUNC_SIGNAL, SIGQUIT }; +#if 0 + /* fork for exec/system, but return before exec'ing. return=0: is child process return>0: is parent process @@ -45,11 +50,12 @@ const struct optdesc opt_sigquit = { "sigquit", NULL, OPT_SIGQUIT, GROUP_P int _xioopen_foxec_int(int xioflags, /* XIO_RDONLY etc. */ struct single *fd, unsigned groups, - struct opt **copts /* in: opts; out: opts for child */ + struct opt **copts, /* in: opts; out: opts for child */ + int *duptostderr /* out: redirect stderr to output fd */ ) { struct opt *popts; /* parent process options */ int numleft; - int d, type, protocol, sv[2], rdpip[2], wrpip[2]; + int d, sv[2], rdpip[2], wrpip[2]; int rw = (xioflags & XIO_ACCMODE); bool usepipes = false; #if HAVE_PTY @@ -399,13 +405,14 @@ int _xioopen_foxec_int(int xioflags, /* XIO_RDONLY etc. */ 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); + int socktype = SOCK_STREAM; + int protocol = 0; + d = AF_UNIX; + retropt_int(popts, OPT_SO_TYPE, &socktype); + result = Socketpair(d, socktype, protocol, sv); if (result < 0) { Error5("socketpair(%d, %d, %d, %p): %s", - d, type, protocol, sv, strerror(errno)); + d, socktype, protocol, sv, strerror(errno)); return STAT_RETRYLATER; } /*0 Info5("socketpair(%d, %d, %d, {%d,%d})", @@ -672,6 +679,8 @@ int _xioopen_foxec_int(int xioflags, /* XIO_RDONLY etc. */ return pid; /* indicate parent (main) process */ } +#endif /* 0 */ + /* fork for exec/system, but return before exec'ing. return=0: is child process @@ -681,11 +690,12 @@ int _xioopen_foxec_int(int xioflags, /* XIO_RDONLY etc. */ 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 **copts, /* in: opts; out: opts for child */ + int *duptostderr ) { struct opt *popts; /* parent process options */ int numleft; - int d, type, protocol, sv[2], rdpip[2], wrpip[2]; + int sv[2], rdpip[2], wrpip[2]; int rw = (xioflags & XIO_ACCMODE); bool usepipes = false; #if HAVE_PTY @@ -919,7 +929,7 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ } if (tn == NULL) { Error("could not open pty"); - return STAT_NORETRY; + return -1; } #endif Info1("opened pseudo terminal %s", tn); @@ -938,7 +948,7 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ #endif /* HAVE_OPENPTY */ free(*copts); if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) { - return STAT_RETRYLATER; + return -1; } applyopts_cloexec(ptyfd, popts);/*!*/ @@ -978,7 +988,7 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ if (rw != XIO_WRONLY) { if (Pipe(rdpip) < 0) { Error2("pipe(%p): %s", rdpip, strerror(errno)); - return STAT_RETRYLATER; + return -1; } } /*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/ @@ -986,7 +996,7 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ free(*copts); if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) { - return STAT_RETRYLATER; + return -1; } popts2 = copyopts(popts, GROUP_ALL); @@ -1001,7 +1011,7 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ if (rw != XIO_RDONLY) { if (Pipe(wrpip) < 0) { Error2("pipe(%p): %s", wrpip, strerror(errno)); - return STAT_RETRYLATER; + return -1; } } /*0 Info2("pipe({%d,%d})", wrpip[0], wrpip[1]);*/ @@ -1033,20 +1043,17 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ 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); + int pf = AF_UNIX; + retropt_int(popts, OPT_PROTOCOL_FAMILY, &pf); + result = xiosocketpair(popts, pf, SOCK_STREAM, 0, sv); if (result < 0) { - Error5("socketpair(%d, %d, %d, %p): %s", - d, type, protocol, sv, strerror(errno)); - return STAT_RETRYLATER; + return -1; } /*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; + return -1; } applyopts(sv[0], *copts, PH_PASTSOCKET); applyopts(sv[1], popts, PH_PASTSOCKET); @@ -1077,37 +1084,30 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ if (applyopts_single(fd, popts, PH_LATE) < 0) return -1; } /*0 if ((optpr = copyopts(*copts, GROUP_PROCESS)) == NULL) - return STAT_RETRYLATER;*/ + return -1;*/ retropt_bool(*copts, OPT_STDERR, &withstderr); xiosetchilddied(); /* set SIGCHLD handler */ + xiosetchilddied(); /* set SIGCHLD handler */ + 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(); + pid = xio_fork(true, E_ERROR); 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); + return -1; } if (pid > 0) { /* for parent (this is our socat process) */ xiosigchld_register(pid, xiosigaction_child, fd); - Sigprocmask(SIG_SETMASK, &oldset, NULL); /* disable SIGCHLD */ + Sigprocmask(SIG_SETMASK, &oldset, NULL); /* enable SIGCHLD */ } if (pid == 0) { /* child */ @@ -1115,7 +1115,7 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ if (xio_forked_inchild() != 0) { Exit(1); } - Sigprocmask(SIG_SETMASK, &oldset, NULL); /* disable SIGCHLD */ + Sigprocmask(SIG_SETMASK, &oldset, NULL); /* enable SIGCHLD */ } } if (!withfork || pid == 0) { /* child */ @@ -1132,13 +1132,13 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ if (rw != XIO_RDONLY && fdi != ttyfd) { if (Dup2(ttyfd, fdi) < 0) { Error3("dup2(%d, %d): %s", ttyfd, fdi, strerror(errno)); - return STAT_RETRYLATER; } + return -1; } /*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; } + return -1; } /*0 Info2("dup2(%d, %d)", ttyfd, fdo);*/ } if ((rw == XIO_RDONLY || fdi != ttyfd) && @@ -1160,7 +1160,7 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ if (fdi == rdpip[1]) { /* a conflict here */ if ((tmpi = Dup(wrpip[0])) < 0) { Error2("dup(%d): %s", wrpip[0], strerror(errno)); - return STAT_RETRYLATER; + return -1; } /*0 Info2("dup(%d) -> %d", wrpip[0], tmpi);*/ rdpip[1] = tmpi; @@ -1168,7 +1168,7 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ if (fdo == wrpip[0]) { /* a conflict here */ if ((tmpo = Dup(rdpip[1])) < 0) { Error2("dup(%d): %s", rdpip[1], strerror(errno)); - return STAT_RETRYLATER; + return -1; } /*0 Info2("dup(%d) -> %d", rdpip[1], tmpo);*/ wrpip[0] = tmpo; @@ -1177,7 +1177,7 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ 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; + return -1; } Close(rdpip[1]); /*0 Info2("dup2(%d, %d)", rdpip[1], fdo);*/ @@ -1186,7 +1186,7 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ 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; + return -1; } Close(wrpip[0]); /*0 Info2("dup2(%d, %d)", wrpip[0], fdi);*/ @@ -1203,13 +1203,13 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ 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; } + return -1; } /*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; } + return -1; } /*0 Info2("dup2(%d, %d)", sv[1], fdo);*/ } if (fdi != sv[1] && fdo != sv[1]) { @@ -1224,36 +1224,6 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ 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) { @@ -1262,6 +1232,12 @@ int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ if (retropt_uidt(*copts, OPT_SETUID, &user) >= 0) { Setuid(user); } + if (withstderr) { + *duptostderr = fdo; + } else { + *duptostderr = -1; + } + return 0; /* indicate child process */ } diff --git a/xio-progcall.h b/xio-progcall.h index 2910d31..3f42be0 100644 --- a/xio-progcall.h +++ b/xio-progcall.h @@ -1,5 +1,5 @@ /* source: xio-progcall.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_progcall_h_included @@ -21,13 +21,18 @@ extern const struct optdesc opt_sigquit; extern int _xioopen_foxec_int(int rw, /* O_RDONLY etc. */ struct single *fd, unsigned groups, - struct opt **opts + struct opt **opts, + int *duptostderr ); -extern int _xioopen_foxec_end(int rw, /* O_RDONLY etc. */ +extern int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */ struct single *fd, unsigned groups, - struct opt **opts - ); + struct opt **opts, + int *duptostderr + ); + extern int setopt_path(struct opt *opts, char **path); +extern +int _xioopen_redir_stderr(int fdo); #endif /* !defined(__xio_progcall_h_included) */ diff --git a/xio-proxy.c b/xio-proxy.c index f262e52..3153695 100644 --- a/xio-proxy.c +++ b/xio-proxy.c @@ -201,7 +201,7 @@ static int xioopen_proxy_connect3(int argc, const char *argv[], struct opt *opts xfd->para.socket.ip.res_opts[1], xfd->para.socket.ip.res_opts[0], them, &themlen, us, &uslen, - &needbind, &lowport, &socktype); + &needbind, &lowport, socktype); if (result != STAT_OK) return result; Notice4("opening connection to %s:%u via proxy %s:%s", proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport); @@ -262,28 +262,22 @@ static int xioopen_proxy_connect3(int argc, const char *argv[], struct opt *opts #if WITH_RETRY if (dofork) { pid_t pid; - while ((pid = Fork()) < 0) { - int level = E_ERROR; - if (xfd->forever || xfd->retry) { - level = E_WARN; - } - Msg1(level, "fork(): %s", strerror(errno)); - if (xfd->forever || xfd->retry--) { - Nanosleep(&xfd->intervall, NULL); - continue; + int level = E_ERROR; + if (xfd->forever || xfd->retry) { + level = E_WARN; + } + while ((pid = xio_fork(false, level)) < 0) { + if (xfd->forever || --xfd->retry) { + Nanosleep(&xfd->intervall, NULL); continue; } return STAT_RETRYLATER; } - if (pid == 0) { /* child process */ - Info1("just born: proxy client process "F_pid, Getpid()); - /* drop parents locks, reset FIPS... */ - if (xio_forked_inchild() != 0) { - Exit(1); - } + if (pid == 0) { /* child process */ xfd->forever = false; xfd->retry = 0; break; } + /* parent process */ Notice1("forked off child process "F_pid, pid); Close(xfd->fd1); @@ -321,9 +315,11 @@ int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts, host = Gethostbyname(targetname); if (host == NULL) { int level = E_WARN; + /* note: cast is req on AIX: */ Msg2(level, "gethostbyname(\"%s\"): %s", targetname, - h_errno == NETDB_INTERNAL ? strerror(errno) : - hstrerror(h_errno)/*0 h_messages[h_errno-1]*/); + h_errno == NETDB_INTERNAL ? strerror(errno) : + (char *)hstrerror(h_errno)/*0 h_messages[h_errno-1]*/); + proxyvars->targetaddr = strdup(targetname); } else { #define LEN 16 /* www.xxx.yyy.zzz\0 */ diff --git a/xio-rawip.c b/xio-rawip.c index c28c152..66fb7c8 100644 --- a/xio-rawip.c +++ b/xio-rawip.c @@ -17,7 +17,6 @@ #include "xio-rawip.h" - static int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int pf, @@ -37,7 +36,7 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts, static int _xioopen_rawip_sendto(const char *hostname, const char *protname, struct opt *opts, int xioflags, - xiofile_t *xxfd, unsigned groups, int pf); + xiofile_t *xxfd, unsigned groups, int *pf); 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("::") }; const union xioaddr_desc *xioaddrs_rawip_sendto[] = { (union xioaddr_desc *)&xioaddr_rawip_sendto2, NULL }; @@ -85,17 +84,24 @@ int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts, return STAT_NORETRY; } if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd, - groups, pf)) != STAT_OK) { + groups, &pf)) != STAT_OK) { return result; } _xio_openlate(&xxfd->stream, opts); return STAT_OK; } +/* + applies and consumes the following options: + PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE + OFUNC_OFFSET + OPT_PROTOCOL_FAMILY, OPT_BIND, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, + OPT_GROUP, OPT_CLOEXEC + */ static int _xioopen_rawip_sendto(const char *hostname, const char *protname, struct opt *opts, int xioflags, xiofile_t *xxfd, - unsigned groups, int pf) { + unsigned groups, int *pf) { char *garbage; xiosingle_t *xfd = &xxfd->stream; union sockaddr_union us; @@ -116,7 +122,7 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname, /*return STAT_NORETRY;*/ } - retropt_int(opts, OPT_SO_TYPE, &socktype); + retropt_int(opts, OPT_PROTOCOL_FAMILY, pf); /* ...res_opts[] */ if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; @@ -124,30 +130,30 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname, xfd->salen = sizeof(xfd->peersa); if ((result = - xiogetaddrinfo(hostname, NULL, pf, socktype, ipproto, + xiogetaddrinfo(hostname, NULL, *pf, socktype, ipproto, &xfd->peersa, &xfd->salen, xfd->para.socket.ip.res_opts[0], xfd->para.socket.ip.res_opts[1])) != STAT_OK) { return result; } - if (pf == PF_UNSPEC) { - pf = xfd->peersa.soa.sa_family; + if (*pf == PF_UNSPEC) { + *pf = xfd->peersa.soa.sa_family; } - uslen = socket_init(pf, &us); + uslen = socket_init(*pf, &us); xfd->fdtype = FDTYPE_SINGLE; 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, xfd->para.socket.ip.res_opts[0], xfd->para.socket.ip.res_opts[1]) != STAT_NOACTION) { needbind = true; } return _xioopen_dgram_sendto(needbind?&us:NULL, uslen, - opts, xioflags, xfd, groups, pf, socktype, ipproto); + opts, xioflags, xfd, groups, *pf, socktype, ipproto); } @@ -167,7 +173,7 @@ int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts, } if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd, - groups, pf)) != STAT_OK) { + groups, &pf)) != STAT_OK) { return result; } @@ -180,7 +186,7 @@ int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts, /* which reply packets will be accepted - determine by range option */ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { - if (parserange(rangename, pf, &xfd->para.socket.range) < 0) { + if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) { free(rangename); return STAT_NORETRY; } @@ -227,7 +233,6 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts, } xfd->stream.howtoshut = XIOSHUT_NONE; xfd->stream.howtoclose = XIOCLOSE_CLOSE; - retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_socket_pf(opts, &pf); if (pf == PF_UNSPEC) { @@ -265,6 +270,7 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts, int pf, int socktype, int dummy3) { const char *protname = argv[1]; char *garbage; + bool needbind = false; union sockaddr_union us; socklen_t uslen = sizeof(us); int ipproto; @@ -285,7 +291,6 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts, protname); /*return STAT_NORETRY;*/ } - retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_socket_pf(opts, &pf); if (pf == PF_UNSPEC) { @@ -298,18 +303,24 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts, #endif } - if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, 1, + if (retropt_bind(opts, pf, socktype, ipproto, + &/*us.soa*/xfd->stream.para.socket.la.soa, &uslen, 1, xfd->stream.para.socket.ip.res_opts[0], - xfd->stream.para.socket.ip.res_opts[1]) != + xfd->stream.para.socket.ip.res_opts[1]) == STAT_OK) { + needbind = true; + } else { /* pf is required during xioread checks */ xfd->stream.para.socket.la.soa.sa_family = pf; } xfd->stream.fdtype = FDTYPE_SINGLE; xfd->stream.dtype = XIODATA_RECV_SKIPIP; - result = _xioopen_dgram_recv(&xfd->stream, xioflags, NULL/*&us.soa*/, uslen, - opts, pf, socktype, ipproto, E_ERROR); + result = + _xioopen_dgram_recv(&xfd->stream, xioflags, + needbind?&/*us.soa*/xfd->stream.para.socket.la.soa:NULL, + uslen, + opts, pf, socktype, ipproto, E_ERROR); _xio_openlate(&xfd->stream, opts); return result; } diff --git a/xio-readline.c b/xio-readline.c index c8c7dd8..b4fbac8 100644 --- a/xio-readline.c +++ b/xio-readline.c @@ -1,5 +1,5 @@ /* source: xio-readline.c */ -/* Copyright Gerhard Rieger 2002-2007 */ +/* Copyright Gerhard Rieger 2002-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for opening the readline address */ @@ -126,8 +126,10 @@ static int xioopen_readline(int argc, const char *argv[], struct opt *opts, if (xfd->stream.para.readline.history_file) { Read_history(xfd->stream.para.readline.history_file); } +#if _WITH_TERMIOS xiotermios_clrflag(xfd->stream.fd1, 3, ICANON); xiotermios_clrflag(xfd->stream.fd1, 3, ECHO); +#endif /* _WITH_TERMIOS */ return _xio_openlate(&xfd->stream, opts); } @@ -143,6 +145,7 @@ ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz) { pipe->para.readline.hasnoecho && !regexec(&pipe->para.readline.noecho, pipe->para.readline.dynprompt, 0, NULL, 0)) { +#if _WITH_TERMIOS /* under these conditions, we do not echo input, thus we circumvent readline */ struct termios saveterm, setterm; @@ -151,6 +154,7 @@ ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz) { setterm = saveterm; setterm.c_lflag |= ICANON; Tcsetattr(pipe->fd1, TCSANOW, &setterm); /*!*/ +#endif /* _WITH_TERMIOS */ do { bytes = Read(pipe->fd1, buff, bufsiz); } while (bytes < 0 && errno == EINTR); @@ -161,16 +165,20 @@ ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz) { errno = _errno; return -1; } +#if _WITH_TERMIOS setterm.c_lflag &= ~ICANON; Tcgetattr(pipe->fd1, &setterm); /*! error */ Tcsetattr(pipe->fd1, TCSANOW, &saveterm); /*!*/ +#endif /* _WITH_TERMIOS */ pipe->para.readline.dynend = pipe->para.readline.dynprompt; /*Write(pipe->fd1, "\n", 1);*/ /*!*/ return bytes; } #endif /* HAVE_REGEX_H */ +#if _WITH_TERMIOS xiotermios_setflag(pipe->fd1, 3, ECHO); +#endif /* _WITH_TERMIOS */ if (pipe->para.readline.prompt || pipe->para.readline.dynprompt) { /* we must carriage return, because readline will first print the prompt */ @@ -197,7 +205,9 @@ ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz) { if (line == NULL) { return 0; /* EOF */ } +#if _WITH_TERMIOS xiotermios_clrflag(pipe->fd1, 3, ECHO); +#endif /* _WITH_TERMIOS */ Add_history(line); bytes = strlen(line); strncpy(buff, line, bufsiz); diff --git a/xio-sctp.c b/xio-sctp.c new file mode 100644 index 0000000..b6c870f --- /dev/null +++ b/xio-sctp.c @@ -0,0 +1,77 @@ +/* source: xio-sctp.c */ +/* Copyright Gerhard Rieger 2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +/* this file contains the source for SCTP related functions and options */ + +#include "xiosysincludes.h" + +#if WITH_SCTP + +#include "xioopen.h" +#include "xio-listen.h" +#include "xio-ip4.h" +#include "xio-ipapp.h" +#include "xio-sctp.h" + +/****** SCTP addresses ******/ + +#if WITH_IP4 || WITH_IP6 +const struct xioaddr_endpoint_desc xioaddr_sctp_connect2 = { XIOADDR_SYS, "sctp-connect", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_SCTP|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_connect, SOCK_STREAM, IPPROTO_SCTP, PF_UNSPEC HELP("::") }; +const union xioaddr_desc *xioaddrs_sctp_connect[] = { + (union xioaddr_desc *)&xioaddr_sctp_connect2, + NULL +}; + +#if WITH_LISTEN +const struct xioaddr_endpoint_desc xioaddr_sctp_listen1 = { XIOADDR_SYS, "sctp-listen", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_SCTP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_listen, SOCK_STREAM, IPPROTO_SCTP, PF_UNSPEC HELP(":") }; +const union xioaddr_desc *xioaddrs_sctp_listen[] = { + (union xioaddr_desc *)&xioaddr_sctp_listen1, + NULL +}; +#endif /* WITH_LISTEN */ +#endif /* WITH_IP4 || WITH_IP6 */ + +#if WITH_IP4 +const struct xioaddr_endpoint_desc xioaddr_sctp4_connect2 = { XIOADDR_SYS, "sctp4-connect", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_SCTP|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_connect, SOCK_STREAM, IPPROTO_SCTP, PF_INET HELP("::") }; +const union xioaddr_desc *xioaddrs_sctp4_connect[] = { + (union xioaddr_desc *)&xioaddr_sctp4_connect2, + NULL +}; + +#if WITH_LISTEN +const struct xioaddr_endpoint_desc xioaddr_sctp4_listen1 = { XIOADDR_SYS, "sctp4-listen", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_SCTP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_listen, SOCK_STREAM, IPPROTO_SCTP, PF_INET HELP(":") }; +const union xioaddr_desc *xioaddrs_sctp4_listen[] = { + (union xioaddr_desc *)&xioaddr_sctp4_listen1, + NULL +}; +#endif /* WITH_LISTEN */ +#endif /* WITH_IP4 */ + +#if WITH_IP6 +const struct xioaddr_endpoint_desc xioaddr_sctp6_connect2 = { XIOADDR_SYS, "sctp6-connect", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_SCTP|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_connect, SOCK_STREAM, IPPROTO_SCTP, PF_INET6 HELP("::") }; +const union xioaddr_desc *xioaddrs_sctp6_connect[] = { + (union xioaddr_desc *)&xioaddr_sctp6_connect2, + NULL +}; + +#if WITH_LISTEN +const struct xioaddr_endpoint_desc xioaddr_sctp6_listen1 = { XIOADDR_SYS, "sctp6-listen", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_SCTP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_listen, SOCK_STREAM, IPPROTO_SCTP, PF_INET6 HELP(":") }; +const union xioaddr_desc *xioaddrs_sctp6_listen[] = { + (union xioaddr_desc *)&xioaddr_sctp6_listen1, + NULL +}; +#endif /* WITH_LISTEN */ +#endif /* WITH_IP6 */ + +/****** SCTP address options ******/ + +#ifdef SCTP_NODELAY +const struct optdesc opt_sctp_nodelay = { "sctp-nodelay", "nodelay", OPT_SCTP_NODELAY, GROUP_IP_SCTP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SCTP, SCTP_NODELAY }; +#endif +#ifdef SCTP_MAXSEG +const struct optdesc opt_sctp_maxseg = { "sctp-maxseg", "mss", OPT_SCTP_MAXSEG, GROUP_IP_SCTP, PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SCTP, SCTP_MAXSEG }; +const struct optdesc opt_sctp_maxseg_late={"sctp-maxseg-late","mss-late",OPT_SCTP_MAXSEG_LATE,GROUP_IP_SCTP,PH_CONNECTED,TYPE_INT,OFUNC_SOCKOPT, SOL_SCTP, SCTP_MAXSEG}; +#endif + +#endif /* WITH_SCTP */ diff --git a/xio-sctp.h b/xio-sctp.h new file mode 100644 index 0000000..e97b343 --- /dev/null +++ b/xio-sctp.h @@ -0,0 +1,19 @@ +/* source: xio-sctp.h */ +/* Copyright Gerhard Rieger 2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +#ifndef __xio_sctp_h_included +#define __xio_sctp_h_included 1 + +extern const union xioaddr_desc *xioaddrs_sctp_connect[]; +extern const union xioaddr_desc *xioaddrs_sctp_listen[]; +extern const union xioaddr_desc *xioaddrs_sctp4_connect[]; +extern const union xioaddr_desc *xioaddrs_sctp4_listen[]; +extern const union xioaddr_desc *xioaddrs_sctp6_connect[]; +extern const union xioaddr_desc *xioaddrs_sctp6_listen[]; + +extern const struct optdesc opt_sctp_nodelay; +extern const struct optdesc opt_sctp_maxseg; +extern const struct optdesc opt_sctp_maxseg_late; + +#endif /* !defined(__xio_sctp_h_included) */ diff --git a/xio-socket.c b/xio-socket.c index ae632c6..193fca5 100644 --- a/xio-socket.c +++ b/xio-socket.c @@ -2,7 +2,8 @@ /* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ -/* this file contains the source for socket related functions */ +/* this file contains the source for socket related functions, and the + implementation of generic socket addresses */ #include "xiosysincludes.h" @@ -10,8 +11,10 @@ #include "xioopen.h" #include "xiosigchld.h" +#include "xio-ascii.h" #include "xio-socket.h" #include "xio-named.h" +#include "xio-unix.h" #if WITH_IP4 #include "xio-ip4.h" #endif /* WITH_IP4 */ @@ -19,9 +22,94 @@ #include "xio-ip6.h" #endif /* WITH_IP6 */ #include "xio-ip.h" +#include "xio-listen.h" #include "xio-ipapp.h" /*! not clean */ #include "xio-tcpwrap.h" + +static +int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xfd, unsigned groups, + int dummy1, int dummy2, int dummy3); +static +int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xfd, unsigned groups, + int dummy1, int dummy2, int dummy3); +static +int xioopen_socket_sendto(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xfd, unsigned groups, + int dummy1, int dummy2, int dummy3); +static +int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xfd, unsigned groups, + int dummy1, int dummy2, int dummy3); +static +int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xfd, unsigned groups, + int dummy1, int socktype, int dummy3); +static +int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xfd, unsigned groups, + int dumy1, int dummy2, int dummy3); + +static +int _xioopen_socket_sendto(const char *pfname, const char *type, + const char *proto, const char *address, + struct opt *opts, int xioflags, xiofile_t *xxfd, + unsigned groups); + +static int +xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num, + char *typbuff, int typlen, + char *nambuff, int namlen, + char *envbuff, int envlen, + char *valbuff, int vallen); + + +#if WITH_GENERICSOCKET +/* generic socket addresses */ +const struct xioaddr_endpoint_desc xioaddr_socket_connect3 = { XIOADDR_ENDPOINT, "socket-connect", 3, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_socket_connect, 0, 0, 0 HELP(":::") }; +const union xioaddr_desc *xioaddrs_socket_connect[] = { + (union xioaddr_desc *)&xioaddr_socket_connect3, + NULL +}; + +#if WITH_LISTEN +const struct xioaddr_endpoint_desc xioaddr_socket_listen3 = { XIOADDR_ENDPOINT, "socket-listen", 3, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_LISTEN|GROUP_RANGE|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_socket_listen, 0, 0, 0 HELP(":::") }; +const union xioaddr_desc *xioaddrs_socket_listen[] = { + (union xioaddr_desc *)&xioaddr_socket_listen3, + NULL +}; +#endif /* WITH_LISTEN */ + +const struct xioaddr_endpoint_desc xioaddr_socket_sendto4 = { XIOADDR_ENDPOINT, "socket-sendto", 4, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_socket_sendto, 0, 0, 0 HELP("::::") }; +const union xioaddr_desc *xioaddrs_socket_sendto[] = { + (union xioaddr_desc *)&xioaddr_socket_sendto4, + NULL +}; + +const struct xioaddr_endpoint_desc xioaddr_socket_datagram4 = { XIOADDR_ENDPOINT, "socket-datagram",4, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_socket_datagram, 0, 0, 0 HELP("::::") }; +const union xioaddr_desc *xioaddrs_socket_datagram[] = { + (union xioaddr_desc *)&xioaddr_socket_datagram4, + NULL +}; + +const struct xioaddr_endpoint_desc xioaddr_socket_recvfrom4 = { XIOADDR_ENDPOINT, "socket-recvfrom",4, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_RANGE|GROUP_CHILD, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_socket_recvfrom, 0, 0, 0 HELP("::::") }; +const union xioaddr_desc *xioaddrs_socket_recvfrom[] = { + (union xioaddr_desc *)&xioaddr_socket_recvfrom4, + NULL +}; + +const struct xioaddr_endpoint_desc xioaddr_socket_recv4 = { XIOADDR_ENDPOINT, "socket-recv", 4, XIOBIT_RDONLY,GROUP_FD|GROUP_SOCKET|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_socket_recv, 0, 0, 0 HELP("::::") }; +const union xioaddr_desc *xioaddrs_socket_recv[] = { + (union xioaddr_desc *)&xioaddr_socket_recv4, + NULL +}; +#endif /* WITH_GENERICSOCKET */ + + +/* the following options apply not only to generic socket addresses but to all + addresses that have anything to do with sockets */ const struct optdesc opt_so_debug = { "so-debug", "debug", OPT_SO_DEBUG, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_DEBUG }; #ifdef SO_ACCEPTCONN /* AIX433 */ const struct optdesc opt_so_acceptconn={ "so-acceptconn","acceptconn",OPT_SO_ACCEPTCONN,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_ACCEPTCONN}; @@ -40,7 +128,7 @@ const struct optdesc opt_so_sndbuf_late={ "so-sndbuf-late","sndbuf-late",OPT_SO_ const struct optdesc opt_so_rcvbuf = { "so-rcvbuf", "rcvbuf", OPT_SO_RCVBUF, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_RCVBUF}; const struct optdesc opt_so_rcvbuf_late={"so-rcvbuf-late","rcvbuf-late",OPT_SO_RCVBUF_LATE,GROUP_SOCKET,PH_LATE,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_RCVBUF }; const struct optdesc opt_so_error = { "so-error", "error", OPT_SO_ERROR, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_ERROR}; -const struct optdesc opt_so_type = { "so-type", "type", OPT_SO_TYPE, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_TYPE }; +const struct optdesc opt_so_type = { "so-type", "type", OPT_SO_TYPE, GROUP_SOCKET, PH_SOCKET, TYPE_INT, OFUNC_SPEC, SOL_SOCKET, SO_TYPE }; const struct optdesc opt_so_dontroute= { "so-dontroute", "dontroute", OPT_SO_DONTROUTE,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_DONTROUTE }; #ifdef SO_RCVLOWAT const struct optdesc opt_so_rcvlowat = { "so-rcvlowat", "rcvlowat", OPT_SO_RCVLOWAT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_RCVLOWAT }; @@ -74,6 +162,9 @@ const struct optdesc opt_so_bsdcompat= { "so-bsdcompat","bsdcompat",OPT_SO_BSDCO #ifdef SO_CKSUMRECV const struct optdesc opt_so_cksumrecv= { "so-cksumrecv","cksumrecv",OPT_SO_CKSUMRECV,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_CKSUMRECV }; #endif /* SO_CKSUMRECV */ +#ifdef SO_TIMESTAMP +const struct optdesc opt_so_timestamp= { "so-timestamp","timestamp",OPT_SO_TIMESTAMP,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_TIMESTAMP }; +#endif #ifdef SO_KERNACCEPT /* AIX 4.3.3 */ const struct optdesc opt_so_kernaccept={ "so-kernaccept","kernaccept",OPT_SO_KERNACCEPT,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_KERNACCEPT}; #endif /* SO_KERNACCEPT */ @@ -116,9 +207,9 @@ const struct optdesc opt_so_dgram_errind={"so-dgram-errind","dgramerrind",OPT_SO #ifdef SO_DONTLINGER /* Solaris */ const struct optdesc opt_so_dontlinger = {"so-dontlinger", "dontlinger", OPT_SO_DONTLINGER, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DONTLINGER }; #endif -#ifdef SO_PROTOTYPE /* Solaris, HP-UX */ -const struct optdesc opt_so_prototype = {"so-prototype", "prototype", OPT_SO_PROTOTYPE, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_PROTOTYPE }; -#endif +/* the SO_PROTOTYPE is OS defined on Solaris, HP-UX; we lend this for a more + general purpose */ +const struct optdesc opt_so_prototype = {"so-prototype", "prototype", OPT_SO_PROTOTYPE, GROUP_SOCKET,PH_SOCKET, TYPE_INT,OFUNC_SPEC, SOL_SOCKET,SO_PROTOTYPE }; #ifdef FIOSETOWN const struct optdesc opt_fiosetown = { "fiosetown", NULL, OPT_FIOSETOWN, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_IOCTL, FIOSETOWN }; #endif @@ -128,15 +219,520 @@ const struct optdesc opt_siocspgrp = { "siocspgrp", NULL, OPT_SIOCSPGRP, GRO const struct optdesc opt_bind = { "bind", NULL, OPT_BIND, GROUP_SOCKET, PH_BIND, TYPE_STRING,OFUNC_SPEC }; const struct optdesc opt_connect_timeout = { "connect-timeout", NULL, OPT_CONNECT_TIMEOUT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_TIMEVAL, OFUNC_OFFSET, (int)&((xiofile_t *)0)->stream.para.socket.connect_timeout }; const struct optdesc opt_protocol_family = { "protocol-family", "pf", OPT_PROTOCOL_FAMILY, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC }; +const struct optdesc opt_protocol = { "protocol", NULL, OPT_PROTOCOL, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC }; + +/* generic setsockopt() options */ +const struct optdesc opt_setsockopt_int = { "setsockopt-int", "sockopt-int", OPT_SETSOCKOPT_INT, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_INT, OFUNC_SOCKOPT_GENERIC, 0, 0 }; +const struct optdesc opt_setsockopt_bin = { "setsockopt-bin", "sockopt-bin", OPT_SETSOCKOPT_BIN, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 }; +const struct optdesc opt_setsockopt_string = { "setsockopt-string", "sockopt-string", OPT_SETSOCKOPT_STRING, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_STRING, OFUNC_SOCKOPT_GENERIC, 0, 0 }; + + +#if WITH_GENERICSOCKET + +static +int xioopen_socket_connect(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; + const char *pfname = argv[1]; + const char *protname = argv[2]; + const char *address = argv[3]; + char *garbage; + int pf; + int proto; + int socktype = SOCK_STREAM; + int needbind = 0; + union sockaddr_union them; socklen_t themlen; + union sockaddr_union us; socklen_t uslen = sizeof(us); + int result; + + if (argc != 4) { + Error2("%s: wrong number of parameters (%d instead of 3)", + argv[0], argc-1); + return STAT_NORETRY; + } + + pf = strtoul(pfname, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + proto = strtoul(protname, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + retropt_socket_pf(opts, &pf); + retropt_int(opts, OPT_SO_TYPE, &socktype); + /*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/ + + applyopts(-1, opts, PH_INIT); + if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + applyopts(-1, opts, PH_EARLY); + + themlen = 0; + if ((result = + dalan(address, (char *)&them.soa.sa_data, &themlen, sizeof(them))) + < 0) { + Error1("data too long: \"%s\"", address); + } else if (result > 0) { + Error1("syntax error in \"%s\"", address); + } + them.soa.sa_family = pf; + themlen += +#if HAVE_STRUCT_SOCKADDR_SALEN + sizeof(them.soa.sa_len) + +#endif + sizeof(them.soa.sa_family); + + xfd->dtype = XIOREAD_STREAM|XIOWRITE_STREAM; + + socket_init(0, &us); + if (retropt_bind(opts, 0 /*pf*/, socktype, proto, (struct sockaddr *)&us, &uslen, 3, + 0, 0) + != STAT_NOACTION) { + needbind = true; + us.soa.sa_family = pf; + } + + if ((result = + xioopen_connect(xfd, + needbind?(struct sockaddr *)&us:NULL, uslen, + (struct sockaddr *)&them, themlen, + opts, pf, socktype, proto, false)) != 0) { + return result; + } + if ((result = _xio_openlate(xfd, opts)) < 0) { + return result; + } + return STAT_OK; +} + +#if WITH_LISTEN +static +int xioopen_socket_listen(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; + const char *pfname = argv[1]; + const char *protname = argv[2]; + const char *usname = argv[3]; + char *garbage; + int pf; + int proto; + int socktype = SOCK_STREAM; + union sockaddr_union us; socklen_t uslen; + struct opt *opts0; + int result; + + if (argc != 4) { + Error2("%s: wrong number of parameters (%d instead of 3)", + argv[0], argc-1); + return STAT_NORETRY; + } + + pf = strtoul(pfname, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + proto = strtoul(protname, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + retropt_socket_pf(opts, &pf); + retropt_int(opts, OPT_SO_TYPE, &socktype); + /*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/ + + socket_init(0, &us); + uslen = 0; + if ((result = + dalan(usname, (char *)&us.soa.sa_data, &uslen, sizeof(us))) + < 0) { + Error1("data too long: \"%s\"", usname); + } else if (result > 0) { + Error1("syntax error in \"%s\"", usname); + } + uslen += sizeof(us.soa.sa_family) +#if HAVE_STRUCT_SOCKADDR_SALEN + + sizeof(us.soa.sa_len) +#endif + ; + us.soa.sa_family = pf; + + if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + applyopts(-1, opts, PH_INIT); + applyopts(-1, opts, PH_EARLY); + + opts0 = copyopts(opts, GROUP_ALL); + + if ((result = + xioopen_listen(xfd, xioflags, + (struct sockaddr *)&us, uslen, + opts, opts0, 0/*instead of pf*/, socktype, proto)) + != STAT_OK) + return result; + return STAT_OK; +} +#endif /* WITH_LISTEN */ + +/* we expect the form: ...:domain:type:protocol:remote-address */ +static +int xioopen_socket_sendto(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xxfd, unsigned groups, + int dummy1, int dummy2, int dummy3) { + int result; + + if (argc != 5) { + Error2("%s: wrong number of parameters (%d instead of 4)", + argv[0], argc-1); + return STAT_NORETRY; + } + if ((result = + _xioopen_socket_sendto(argv[1], argv[2], argv[3], argv[4], + opts, xioflags, xxfd, groups)) + != STAT_OK) { + return result; + } + _xio_openlate(&xxfd->stream, opts); + return STAT_OK; +} + +static +int _xioopen_socket_sendto(const char *pfname, const char *type, + const char *protname, const char *address, + struct opt *opts, int xioflags, xiofile_t *xxfd, + unsigned groups) { + xiosingle_t *xfd = &xxfd->stream; + char *garbage; + union sockaddr_union us = {{0}}; + socklen_t uslen = 0; + socklen_t themlen = 0; + int pf; + int socktype = SOCK_RAW; + int proto; + bool needbind = false; + char *bindstring = NULL; + int result; + + pf = strtoul(pfname, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + socktype = strtoul(type, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + proto = strtoul(protname, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + retropt_socket_pf(opts, &pf); + retropt_int(opts, OPT_SO_TYPE, &socktype); + /*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/ + + xfd->peersa.soa.sa_family = pf; + themlen = 0; + if ((result = + dalan(address, (char *)&xfd->peersa.soa.sa_data, &themlen, + sizeof(xfd->peersa))) + < 0) { + Error1("data too long: \"%s\"", address); + } else if (result > 0) { + Error1("syntax error in \"%s\"", address); + } + xfd->salen = themlen + sizeof(sa_family_t) +#if HAVE_STRUCT_SOCKADDR_SALEN + + sizeof(xfd->peersa.soa.sa_len) +#endif + ; +#if HAVE_STRUCT_SOCKADDR_SALEN + xfd->peersa.soa.sa_len = + sizeof(xfd->peersa.soa.sa_len) + sizeof(xfd->peersa.soa.sa_family) + + themlen; +#endif + + /* ...res_opts[] */ + if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + applyopts(-1, opts, PH_INIT); + + if (pf == PF_UNSPEC) { + pf = xfd->peersa.soa.sa_family; + } + + xfd->dtype = XIODATA_RECVFROM; + + if (retropt_string(opts, OPT_BIND, &bindstring) == 0) { + uslen = 0; + if ((result = + dalan(bindstring, (char *)&us.soa.sa_data, &uslen, sizeof(us))) + < 0) { + Error1("data too long: \"%s\"", bindstring); + } else if (result > 0) { + Error1("syntax error in \"%s\"", bindstring); + } + us.soa.sa_family = pf; + uslen += sizeof(sa_family_t) +#if HAVE_STRUCT_SOCKADDR_SALEN + + sizeof(us.soa.sa_len) +#endif + ; + needbind = true; + } + + return + _xioopen_dgram_sendto(needbind?&us:NULL, uslen, + opts, xioflags, xfd, groups, pf, socktype, proto); +} + + +/* we expect the form: ...:domain:socktype:protocol:local-address */ +static +int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xxfd, unsigned groups, + int dummy, int summy2, int dummy3) { + struct single *xfd = &xxfd->stream; + const char *pfname = argv[1]; + const char *typename = argv[2]; + const char *protname = argv[3]; + const char *address = argv[4]; + char *garbage; + union sockaddr_union *us = &xfd->para.socket.la; + socklen_t uslen = sizeof(*us); + int pf, socktype, proto; + char *rangename; + int result; + + if (argc != 5) { + Error2("%s: wrong number of parameters (%d instead of 4)", + argv[0], argc-1); + return STAT_NORETRY; + } + + pf = strtoul(pfname, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + socktype = strtoul(typename, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + proto = strtoul(protname, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + retropt_socket_pf(opts, &pf); + retropt_int(opts, OPT_SO_TYPE, &socktype); + /*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/ + + uslen = 0; + if ((result = + dalan(address, (char *)&us->soa.sa_data, &uslen, sizeof(*us))) + < 0) { + Error1("data too long: \"%s\"", address); + } else if (result > 0) { + Error1("syntax error in \"%s\"", address); + } + us->soa.sa_family = pf; + uslen += sizeof(us->soa.sa_family) +#if HAVE_STRUCT_SOCKADDR_SALEN + + sizeof(us->soa.sa_len); +#endif + ; + xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO; + + if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { + if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) { + return STAT_NORETRY; + } + xfd->para.socket.dorange = true; + free(rangename); + } + + if ((result = + _xioopen_dgram_recvfrom(xfd, xioflags, &us->soa, uslen, + opts, pf, socktype, proto, E_ERROR)) + != STAT_OK) { + return result; + } + _xio_openlate(xfd, opts); + return STAT_OK; +} + +/* we expect the form: ...:domain:type:protocol:local-address */ +static +int xioopen_socket_recv(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; + const char *pfname = argv[1]; + const char *typename = argv[2]; + const char *protname = argv[3]; + const char *address = argv[4]; + char *garbage; + union sockaddr_union us; + socklen_t uslen = sizeof(us); + int pf, socktype, proto; + char *rangename; + int result; + + if (argc != 5) { + Error2("%s: wrong number of parameters (%d instead of 4)", + argv[0], argc-1); + return STAT_NORETRY; + } + + pf = strtoul(pfname, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + socktype = strtoul(typename, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + proto = strtoul(protname, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + retropt_socket_pf(opts, &pf); + retropt_int(opts, OPT_SO_TYPE, &socktype); + /*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/ + + uslen = 0; + if ((result = + dalan(address, (char *)&us.soa.sa_data, &uslen, sizeof(us))) + < 0) { + Error1("data too long: \"%s\"", address); + } else if (result > 0) { + Error1("syntax error in \"%s\"", address); + } + us.soa.sa_family = pf; + uslen += sizeof(sa_family_t) +#if HAVE_STRUCT_SOCKADDR_SALEN + +sizeof(us.soa.sa_len) +#endif + ; + xfd->dtype = XIOREAD_RECV; + xfd->para.socket.la.soa.sa_family = pf; + + if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { + if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) { + return STAT_NORETRY; + } + xfd->para.socket.dorange = true; + free(rangename); + } + + if ((result = + _xioopen_dgram_recv(xfd, xioflags, &us.soa, + uslen, opts, pf, socktype, proto, E_ERROR)) + != STAT_OK) { + return result; + } + _xio_openlate(xfd, opts); + return STAT_OK; +} + + +/* we expect the form: ...:domain:type:protocol:remote-address */ +static +int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts, + int xioflags, xiofile_t *xxfd, unsigned groups, + int dummy1, int dummy2, int dummy3) { + xiosingle_t *xfd = &xxfd->stream; + const char *pfname = argv[1]; + const char *typename = argv[2]; + const char *protname = argv[3]; + const char *address = argv[4]; + char *garbage; + char *rangename; + socklen_t themlen; + int pf; + int result; + + if (argc != 5) { + Error2("%s: wrong number of parameters (%d instead of 4)", + argv[0], argc-1); + return STAT_NORETRY; + } + + pf = strtoul(pfname, &garbage, 0); + if (*garbage != '\0') { + Warn1("garbage in parameter: \"%s\"", garbage); + } + + retropt_socket_pf(opts, &pf); + /*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/ + + xfd->peersa.soa.sa_family = pf; + themlen = 0; + if ((result = + dalan(address, (char *)&xfd->peersa.soa.sa_data, &themlen, + sizeof(xfd->peersa))) + < 0) { + Error1("data too long: \"%s\"", address); + } else if (result > 0) { + Error1("syntax error in \"%s\"", address); + } + xfd->salen = themlen + sizeof(sa_family_t); +#if HAVE_STRUCT_SOCKADDR_SALEN + xfd->peersa.soa.sa_len = + sizeof(xfd->peersa.soa.sa_len) + sizeof(xfd->peersa.soa.sa_family) + + themlen; +#endif + + if ((result = + _xioopen_socket_sendto(pfname, typename, protname, address, + opts, xioflags, xxfd, groups)) + != STAT_OK) { + return result; + } + + xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO; + + xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family; + + /* which reply sockets will accept - determine by range option */ + if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { + if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) { + free(rangename); + return STAT_NORETRY; + } + xfd->para.socket.dorange = true; + xfd->dtype |= XIOREAD_RECV_CHECKRANGE; + free(rangename); + } + + _xio_openlate(xfd, opts); + return STAT_OK; +} + +#endif /* WITH_GENERICSOCKET */ + /* a subroutine that is common to all socket addresses that want to connect to a peer address. might fork. + applies and consumes the following options: + PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECT, + PH_CONNECTED, PH_LATE, + OFUNC_OFFSET, + OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC returns 0 on success. */ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, struct sockaddr *them, size_t themlen, - struct opt *opts, int pf, int stype, int proto, + struct opt *opts, int pf, int socktype, int protocol, bool alt, int level) { int fcntl_flags = 0; char infobuff[256]; @@ -145,9 +741,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, int _errno; int result; - if ((xfd->fd1 = Socket(pf, stype, proto)) < 0) { - Msg4(level, - "socket(%d, %d, %d): %s", pf, stype, proto, strerror(errno)); + if ((xfd->fd1 = xiosocket(opts, pf, socktype, protocol, level)) < 0) { return STAT_RETRYLATER; } xfd->fdtype = FDTYPE_SINGLE; @@ -272,18 +866,19 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, if (xfd->para.socket.connect_timeout.tv_sec != 0 || xfd->para.socket.connect_timeout.tv_usec != 0) { struct timeval timeout; - fd_set readfds, writefds, exceptfds; + struct pollfd writefd; int result; + Info4("connect(%d, %s, "F_Zd"): %s", xfd->fd1, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)), themlen, strerror(errno)); timeout = xfd->para.socket.connect_timeout; - FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds); - FD_SET(xfd->fd1, &readfds); FD_SET(xfd->fd1, &writefds); - result = - Select(xfd->fd1+1, &readfds, &writefds, &exceptfds, &timeout); + writefd.fd = xfd->fd1; + writefd.events = (POLLIN|POLLHUP|POLLERR); + result = xiopoll(&writefd, 1, &timeout); if (result < 0) { - Msg2(level, "select(%d,,,,): %s", xfd->fd1+1, strerror(errno)); + Msg4(level, "xiopoll({%d,POLLIN|POLLHUP|POLLER},,{"F_tv_sec"."F_tv_usec"): %s", + xfd->fd1, timeout.tv_sec, timeout.tv_usec, strerror(errno)); return STAT_RETRYLATER; } if (result == 0) { @@ -292,7 +887,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, strerror(ETIMEDOUT)); return STAT_RETRYLATER; } - if (FD_ISSET(xfd->fd1, &readfds)) { + if (writefd.revents & POLLOUT) { #if 0 unsigned char dummy[1]; Read(xfd->fd1, &dummy, 1); /* get error message */ @@ -340,9 +935,10 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, } } - applyopts_fchown(xfd->fd1, opts); + applyopts_fchown(xfd->fd1, opts); /* OPT_USER, OPT_GROUP */ applyopts(xfd->fd1, opts, PH_CONNECTED); applyopts(xfd->fd1, opts, PH_LATE); + Notice1("successfully connected from local address %s", sockaddr_info(&la.soa, themlen, infobuff, sizeof(infobuff))); @@ -353,11 +949,16 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, /* a subroutine that is common to all socket addresses that want to connect to a peer address. might fork. + applies and consumes the following option: + PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECT, + PH_CONNECTED, PH_LATE, + OFUNC_OFFSET, + OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC returns 0 on success. */ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, struct sockaddr *them, size_t themlen, - struct opt *opts, int pf, int stype, int proto, + struct opt *opts, int pf, int socktype, int protocol, bool alt) { bool dofork = false; struct opt *opts0; @@ -366,7 +967,6 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, int result; retropt_bool(opts, OPT_FORK, &dofork); - retropt_int(opts, OPT_SO_TYPE, &stype); opts0 = copyopts(opts, GROUP_ALL); @@ -383,7 +983,7 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, level = E_ERROR; result = _xioopen_connect(xfd, us, uslen, them, themlen, opts, - pf, stype, proto, alt, level); + pf, socktype, protocol, alt, level); switch (result) { case STAT_OK: break; #if WITH_RETRY @@ -409,28 +1009,25 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, #if WITH_RETRY if (dofork) { pid_t pid; - while ((pid = Fork()) < 0) { - int level = E_ERROR; - if (xfd->forever || --xfd->retry) { - level = E_WARN; /* most users won't expect a problem here, + int level = E_ERROR; + if (xfd->forever || xfd->retry) { + level = E_WARN; /* most users won't expect a problem here, so Notice is too weak */ - } - Msg1(level, "fork(): %s", strerror(errno)); + } + + while ((pid = xio_fork(false, level)) < 0) { + --xfd->retry; if (xfd->forever || xfd->retry) { dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL); Nanosleep(&xfd->intervall, NULL); continue; } return STAT_RETRYLATER; } - if (pid == 0) { /* child process */ - Info1("just born: TCP client process "F_pid, Getpid()); - /* drop parents locks, reset FIPS... */ - if (xio_forked_inchild() != 0) { - Exit(1); - } + if (pid == 0) { /* child process */ break; } + /* parent process */ Notice1("forked off child process "F_pid, pid); Close(xfd->fd1); @@ -453,7 +1050,12 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, } -/* common to xioopen_udp_sendto, ..unix_sendto, ..rawip */ +/* common to xioopen_udp_sendto, ..unix_sendto, ..rawip + applies and consumes the following option: + PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE + OFUNC_OFFSET + OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC + */ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */ union sockaddr_union *us, socklen_t uslen, struct opt *opts, @@ -463,9 +1065,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */ union sockaddr_union la; socklen_t lalen = sizeof(la); char infobuff[256]; - if ((xfd->fd1 = Socket(pf, socktype, ipproto)) < 0) { - Msg4(level, - "socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno)); + if ((xfd->fd1 = xiosocket(opts, pf, socktype, ipproto, level)) < 0) { return STAT_RETRYLATER; } @@ -510,43 +1110,83 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */ } -static pid_t xio_waitingfor; -static bool xio_hashappened; -void xiosigaction_hasread(int signum, siginfo_t *siginfo, void *ucontext) { +/* when the recvfrom address (with option fork) receives a packet it keeps this + packet in the IP stacks input queue and forks a sub process. The sub process + then reads this packet for processing its data. + There is a problem because the parent process would find the same packet + again if it calls select()/poll() before the client process reads the + packet. + To solve this problem we implement the following mechanism: + The sub process sends a SIGUSR1 when it has read the packet (or a SIGCHLD if + it dies before). The parent process waits until it receives that signal and + only then continues to listen. + To prevent a signal from another process to trigger our loop, we pass the + pid of the sub process to the signal handler in xio_waitingfor. The signal + handler sets xio_hashappened if the pid matched. +*/ +static pid_t xio_waitingfor; /* info from recv loop to signal handler: + indicates the pid that of the child process + that should send us the USR1 signal */ +static bool xio_hashappened; /* info from signal handler to loop: child + process has read ("consumed") the packet */ +/* this is the signal handler for USR1 and CHLD */ +void xiosigaction_hasread(int signum +#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO) + , siginfo_t *siginfo, void *ucontext +#endif + ) { pid_t pid; int _errno; int status = 0; bool wassig = false; +#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO) Debug5("xiosigaction_hasread(%d, {%d,%d,%d,"F_pid"}, )", signum, siginfo->si_signo, siginfo->si_errno, siginfo->si_code, siginfo->si_pid); - _errno = errno; - do { - pid = Waitpid(-1, &status, WNOHANG); - if (pid == 0) { - Msg(wassig?E_INFO:E_WARN, - "waitpid(-1, {}, WNOHANG): no child has exited"); - Info("childdied() finished"); - errno = _errno; - return; - } else if (pid < 0 && errno == ECHILD) { - Msg1(wassig?E_INFO:E_WARN, - "waitpid(-1, {}, WNOHANG): %s", strerror(errno)); - Info("childdied() finished"); - errno = _errno; - return; - } - wassig = true; - if (pid < 0) { - Warn2("waitpid(-1, {%d}, WNOHANG): %s", status, strerror(errno)); - Info("childdied() finished"); - errno = _errno; - return; - } - } while (1); +#else + Debug1("xiosigaction_hasread(%d)", signum); +#endif + if (signum == SIGCHLD) { + _errno = errno; + do { + pid = Waitpid(-1, &status, WNOHANG); + if (pid == 0) { + Msg(wassig?E_INFO:E_WARN, + "waitpid(-1, {}, WNOHANG): no child has exited"); + Info("childdied() finished"); + errno = _errno; + Debug("xiosigaction_hasread() ->"); + return; + } else if (pid < 0 && errno == ECHILD) { + Msg1(wassig?E_INFO:E_WARN, + "waitpid(-1, {}, WNOHANG): %s", strerror(errno)); + Info("childdied() finished"); + errno = _errno; + Debug("xiosigaction_hasread() ->"); + return; + } + wassig = true; + if (pid < 0) { + Warn2("waitpid(-1, {%d}, WNOHANG): %s", status, strerror(errno)); + Info("childdied() finished"); + errno = _errno; + Debug("xiosigaction_hasread() ->"); + return; + } + if (pid == xio_waitingfor) { + xio_hashappened = true; + Debug("xiosigaction_hasread() ->"); + return; + } + } while (1); + } +#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO) if (xio_waitingfor == siginfo->si_pid) { xio_hashappened = true; } +#else + xio_hashappened = true; +#endif Debug("xiosigaction_hasread() ->"); return; } @@ -561,6 +1201,10 @@ void xiosigaction_hasread(int signum, siginfo_t *siginfo, void *ucontext) { This function does not retry. If you need retries, handle this is a loop in the calling function. after fork, we set the forever/retry of the child process to 0 + applies and consumes the following options: + PH_INIT, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY, PH_PREOPEN, PH_FD, + PH_CONNECTED, PH_LATE, PH_LATE2 + OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, cloexec, OPT_RANGE, tcpwrap */ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, struct sockaddr *us, socklen_t uslen, @@ -597,7 +1241,11 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, |SA_NOMASK #endif ; +#if HAVE_SIGACTION + act.sa_sigaction = childdied; +#else act.sa_handler = childdied; +#endif if (Sigaction(SIGCHLD, &act, NULL) < 0) { /*! man does not say that errno is defined */ Warn2("sigaction(SIGCHLD, %p, NULL): %s", childdied, strerror(errno)); @@ -610,9 +1258,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, } #endif /* 1 */ - if ((xfd->fd1 = Socket(pf, socktype, proto)) < 0) { - Msg4(level, - "socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno)); + if ((xfd->fd1 = xiosocket(opts, pf, socktype, proto, level)) < 0) { return STAT_RETRYLATER; } @@ -646,9 +1292,9 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, } #endif /* WITH_UNIX */ -#if WITH_IP4 /*|| WITH_IP6*/ + /* for generic sockets, this has already been retrieved */ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { - if (parserange(rangename, pf, &xfd->para.socket.range) + if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) { free(rangename); return STAT_NORETRY; @@ -656,7 +1302,6 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, free(rangename); xfd->para.socket.dorange = true; } -#endif #if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP xio_retropt_tcpwrap(xfd, opts); @@ -682,10 +1327,10 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, |SA_NOMASK #endif ; -#if 1 || HAVE_SIGACTION_SASIGACTION +#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO) act.sa_sigaction = xiosigaction_hasread; #else /* Linux 2.0(.33) does not have sigaction.sa_sigaction */ - act.sa_handler = xiosighandler_hasread; + act.sa_handler = xiosigaction_hasread; #endif if (Sigaction(SIGUSR1, &act, NULL) < 0) { /*! Linux man does not explicitely say that errno is defined */ @@ -714,6 +1359,8 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, union sockaddr_union *pa = &_peername; /* peer address */ union sockaddr_union *la = &_sockname; /* local address */ socklen_t palen = sizeof(_peername); /* peer address size */ + char ctrlbuff[1024]; /* ancillary messages */ + struct msghdr msgh = {0}; socket_init(pf, pa); salen = sizeof(struct sockaddr); @@ -725,18 +1372,18 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, drop = true; } - /* loop until select() returns valid */ + /* loop until select()/poll() returns valid */ do { - fd_set in, out, expt; + struct pollfd readfd; /*? int level = E_ERROR;*/ if (us != NULL) { Notice1("receiving on %s", sockaddr_info(us, uslen, lisname, sizeof(lisname))); } else { Notice1("receiving IP protocol %u", proto); } - FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt); - FD_SET(xfd->fd1, &in); - if (Select(xfd->fd1+1, &in, &out, &expt, NULL) > 0) { + readfd.fd = xfd->fd1; + readfd.events = POLLIN; + if (xiopoll(&readfd, 1, NULL) > 0) { break; } @@ -744,19 +1391,30 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, continue; } - Msg2(level, "select(, {%d}): %s", xfd->fd1, strerror(errno)); + Msg2(level, "xiopoll({%d,,},,-1): %s", xfd->fd1, strerror(errno)); Close(xfd->fd1); return STAT_RETRYLATER; } while (true); - if (xiogetpacketsrc(xfd->fd1, pa, &palen) < 0) { + msgh.msg_name = pa; + msgh.msg_namelen = palen; +#if HAVE_STRUCT_MSGHDR_MSGCONTROL + msgh.msg_control = ctrlbuff; +#endif +#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN + msgh.msg_controllen = sizeof(ctrlbuff); +#endif + if (xiogetpacketsrc(xfd->fd1, &msgh) < 0) { return STAT_RETRYLATER; } + palen = msgh.msg_namelen; Notice1("receiving packet from %s"/*"src"*/, sockaddr_info((struct sockaddr *)pa, palen, peername, sizeof(peername))/*, sockaddr_info(&la->soa, sockname, sizeof(sockname))*/); + xiodopacketinfo(&msgh, true, true); + if (xiocheckpeer(xfd, pa, la) < 0) { /* drop packet */ char buff[512]; @@ -767,6 +1425,10 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, sockaddr_info((struct sockaddr *)pa, palen, infobuff, sizeof(infobuff))); + /* set the env vars describing the local and remote sockets */ + /*xiosetsockaddrenv("SOCK", la, lalen, proto);*/ + xiosetsockaddrenv("PEER", pa, palen, proto); + applyopts(xfd->fd1, opts, PH_FD); applyopts(xfd->fd1, opts, PH_CONNECTED); @@ -776,8 +1438,6 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, if (dofork) { sigset_t mask_sigchldusr1; - const char *forkwaitstring; - int forkwaitsecs = 0; /* we must prevent that the current packet triggers another fork; therefore we wait for a signal from the recent child: USR1 @@ -789,17 +1449,11 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, sigaddset(&mask_sigchldusr1, SIGUSR1); Sigprocmask(SIG_BLOCK, &mask_sigchldusr1, NULL); - if ((pid = Fork()) < 0) { - Msg1(level, "fork(): %s", strerror(errno)); + if ((pid = xio_fork(false, level)) < 0) { Close(xfd->fd1); Sigprocmask(SIG_UNBLOCK, &mask_sigchldusr1, NULL); 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) { /* child */ /* no reason to block SIGCHLD in child process */ @@ -814,11 +1468,6 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, level = E_ERROR; #endif /* WITH_RETRY */ - /* drop parents locks, reset FIPS... */ - if (xio_forked_inchild() != 0) { - Exit(1); - } - #if WITH_UNIX /* with UNIX sockets: only listening parent is allowed to remove the socket file */ @@ -829,8 +1478,6 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags, } /* server: continue loop with listen */ - Notice1("forked off child process "F_pid, pid); - xio_waitingfor = pid; /* now we are ready to handle signals */ Sigprocmask(SIG_UNBLOCK, &mask_sigchldusr1, NULL); @@ -863,9 +1510,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags, if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; - if ((xfd->fd1 = Socket(pf, socktype, proto)) < 0) { - Msg4(level, - "socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno)); + if ((xfd->fd1 = xiosocket(opts, pf, socktype, proto, level)) < 0) { return STAT_RETRYLATER; } @@ -901,7 +1546,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags, #if WITH_IP4 /*|| WITH_IP6*/ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { - if (parserange(rangename, pf, &xfd->para.socket.range) + if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) { free(rangename); return STAT_NORETRY; @@ -930,8 +1575,8 @@ int retropt_socket_pf(struct opt *opts, int *pf) { char *pfname; if (retropt_string(opts, OPT_PROTOCOL_FAMILY, &pfname) >= 0) { - if (false) { - ; + if (isdigit(pfname[0])) { + *pf = strtoul(pfname, NULL /*!*/, 0); #if WITH_IP4 } else if (!strcasecmp("inet", pfname) || !strcasecmp("inet4", pfname) || @@ -958,80 +1603,153 @@ int retropt_socket_pf(struct opt *opts, int *pf) { } - -int xiogetpacketsrc(int fd, union sockaddr_union *pa, socklen_t *palen) { - char infobuff[256]; +/* this function calls recvmsg(..., MSG_PEEK, ...) to obtain information about + the arriving packet. in msgh the msg_name pointer must refer to an (empty) + sockaddr storage. */ +int xiogetpacketsrc(int fd, struct msghdr *msgh) { char peekbuff[1]; - -#if 0 - - struct msghdr msgh = {0}; #if HAVE_STRUCT_IOVEC struct iovec iovec; #endif - char ctrlbuff[5120]; - msgh.msg_name = pa; - msgh.msg_namelen = *palen; #if HAVE_STRUCT_IOVEC iovec.iov_base = peekbuff; iovec.iov_len = sizeof(peekbuff); - msgh.msg_iov = &iovec; - msgh.msg_iovlen = 1; -#endif -#if HAVE_STRUCT_MSGHDR_MSGCONTROL - msgh.msg_control = ctrlbuff; -#endif -#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN - msgh.msg_controllen = sizeof(ctrlbuff); + msgh->msg_iov = &iovec; + msgh->msg_iovlen = 1; #endif #if HAVE_STRUCT_MSGHDR_MSGFLAGS - msgh.msg_flags = 0; + msgh->msg_flags = 0; #endif - if (Recvmsg(fd, &msgh, MSG_PEEK + if (Recvmsg(fd, msgh, MSG_PEEK #ifdef MSG_TRUNC - |MSG_TRUNC + |MSG_TRUNC #endif ) < 0) { - Notice1("packet from %s", - sockaddr_info(&pa->soa, infobuff, sizeof(infobuff))); Warn1("recvmsg(): %s", strerror(errno)); return STAT_RETRYLATER; } - *palen = msgh.msg_namelen; return STAT_OK; - -#else - - if (Recvfrom(fd, peekbuff, sizeof(peekbuff), MSG_PEEK -#ifdef MSG_TRUNC - |MSG_TRUNC -#endif - , - &pa->soa, palen) < 0) { - Notice1("packet from %s", - sockaddr_info(&pa->soa, *palen, infobuff, sizeof(infobuff))); - Warn1("recvfrom(): %s", strerror(errno)); - return STAT_RETRYLATER; - } - return STAT_OK; - -#endif } -int xiocheckrange(union sockaddr_union *sa, union xiorange_union *range) { +/* works through the ancillary messages found in the given socket header record + and logs the relevant information (E_DEBUG, E_INFO). + calls protocol/layer specific functions for handling the messages + creates appropriate environment vars if withenv is set */ +int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv) { +#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA) + struct cmsghdr *cmsg; + + /* parse ancillary messages */ + cmsg = CMSG_FIRSTHDR(msgh); + while (cmsg != NULL) { + int num = 0; /* number of data components of a ancill.msg */ + int i; + char typbuff[16], *typp; + char nambuff[128], *namp; + char valbuff[256], *valp; + char envbuff[256], *envp; + + if (withlog) { + xiodump(CMSG_DATA(cmsg), + cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg), + valbuff, sizeof(valbuff)-1, 0); + Debug4("ancillary message: len="F_socklen", level=%d, type=%d, data=%s", + cmsg->cmsg_len, cmsg->cmsg_level, cmsg->cmsg_type, + valbuff); + } + + /* try to get the anc.msg. contents in handy components, protocol/level + dependent */ + switch (cmsg->cmsg_level) { + case SOL_SOCKET: + xiolog_ancillary_socket(cmsg, &num, typbuff, sizeof(typbuff)-1, + nambuff, sizeof(nambuff)-1, + envbuff, sizeof(envbuff)-1, + valbuff, sizeof(valbuff)-1); + break; +#if WITH_IP4 || WITH_IP6 + case SOL_IP: + xiolog_ancillary_ip(cmsg, &num, typbuff, sizeof(typbuff)-1, + nambuff, sizeof(nambuff)-1, + envbuff, sizeof(envbuff)-1, + valbuff, sizeof(valbuff)-1); + break; +#endif /* WITH_IP4 || WITH_IP6 */ +#if WITH_IP6 + case SOL_IPV6: + xiolog_ancillary_ip6(cmsg, &num, typbuff, sizeof(typbuff)-1, + nambuff, sizeof(nambuff)-1, + envbuff, sizeof(envbuff)-1, + valbuff, sizeof(valbuff)-1); + break; +#endif /* WITH_IP6 */ + default: + num = 1; + snprintf(typbuff, sizeof(typbuff)-1, "LEVEL%u", cmsg->cmsg_level); + snprintf(nambuff, sizeof(nambuff)-1, "type%u", cmsg->cmsg_type); + xiodump(CMSG_DATA(cmsg), + cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg), + valbuff, sizeof(valbuff)-1, 0); + } + /* here the info is in typbuff (one string), nambuff (num consecutive + strings), and valbuff (num consecutive strings) */ + i = 0; + typp = typbuff; namp = nambuff; envp = envbuff; valp = valbuff; + while (i < num) { + if (withlog) { + Info3("ancillary message: %s: %s=%s", typp, namp, valp); + } + if (withenv) { + if (*envp) { + xiosetenv(envp, valp, 1); + } else if (!strcasecmp(typp+strlen(typp)-strlen(namp), namp)) { + xiosetenv(typp, valp, 1); + } else { + xiosetenv2(typp, namp, valp, 1); + } + } + if (++i == num) break; + namp = strchr(namp, '\0')+1; + envp = strchr(envp, '\0')+1; + valp = strchr(valp, '\0')+1; + } + cmsg = CMSG_NXTHDR(msgh, cmsg); + } + return 0; +#else /* !(defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)) */ + return -1; +#endif /* !(defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)) */ +} + + +/* check if peer address is within permitted range. + return >= 0 if so. */ +int xiocheckrange(union sockaddr_union *sa, struct xiorange *range) { switch (sa->soa.sa_family) { #if WITH_IP4 case PF_INET: return - xiocheckrange_ip4(&sa->ip4, &range->ip4); + xiocheckrange_ip4(&sa->ip4, range); #endif /* WITH_IP4 */ #if WITH_IP6 case PF_INET6: return - xiocheckrange_ip6(&sa->ip6, &range->ip6); + xiocheckrange_ip6(&sa->ip6, range); #endif /* WITH_IP6 */ +#if 0 + case PF_UNSPEC: + { + socklen_t i; + for (i = 0; i < sizeof(sa->soa.sa_data); ++i) { + if ((range->netmask.soa.sa_data[i] & sa->soa.sa_data[i]) != range->netaddr.soa.sa_data[i]) { + return -1; + } + } + return 0; + } +#endif } return -1; } @@ -1043,6 +1761,7 @@ int xiocheckpeer(xiosingle_t *xfd, #if WITH_IP4 if (xfd->para.socket.dorange) { + if (pa == NULL) { return -1; } if (xiocheckrange(pa, &xfd->para.socket.range) < 0) { char infobuff[256]; Warn1("refusing connection from %s due to range option", @@ -1058,6 +1777,7 @@ int xiocheckpeer(xiosingle_t *xfd, #if WITH_TCP || WITH_UDP if (xfd->para.socket.ip.dosourceport) { + if (pa == NULL) { return -1; } #if WITH_IP4 if (pa->soa.sa_family == AF_INET && ntohs(((struct sockaddr_in *)pa)->sin_port) != xfd->para.socket.ip.sourceport) { @@ -1080,6 +1800,7 @@ int xiocheckpeer(xiosingle_t *xfd, sockaddr_info((struct sockaddr *)pa, 0, infobuff, sizeof(infobuff))); } else if (xfd->para.socket.ip.lowport) { + if (pa == NULL) { return -1; } if (pa->soa.sa_family == AF_INET && ntohs(((struct sockaddr_in *)pa)->sin_port) >= IPPORT_RESERVED) { Warn1("refusing connection from %s due to lowport option", @@ -1121,4 +1842,334 @@ int xiocheckpeer(xiosingle_t *xfd, return 0; /* permitted */ } + +#if HAVE_STRUCT_CMSGHDR +/* converts the ancillary message in *cmsg into a form useable for further + processing. knows the specifics of common message types. + returns the number of resulting syntax elements is *num + returns a sequence of \0 terminated type strings in *typbuff + returns a sequence of \0 terminated name strings in *nambuff + returns a sequence of \0 terminated value strings in *valbuff + the respective len parameters specify the available space in the buffers + returns STAT_OK + */ +static int +xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num, + char *typbuff, int typlen, + char *nambuff, int namlen, + char *envbuff, int envlen, + char *valbuff, int vallen) { + const char *cmsgtype, *cmsgname, *cmsgenvn; + size_t msglen; + struct timeval *tv; + +#if defined(CMSG_DATA) + + msglen = cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg); + switch (cmsg->cmsg_type) { +#ifdef SO_PASSCRED + case SO_PASSCRED: /* this is really a UNIX/LOCAL message */ + /*! needs implementation */ +#endif /* SO_PASSCRED */ +#ifdef SO_RIGHTS + case SO_RIGHTS: /* this is really a UNIX/LOCAL message */ + /*! needs implementation */ +#endif + default: /* binary data */ + snprintf(typbuff, typlen, "SOCKET.%u", cmsg->cmsg_type); + strncpy(nambuff, "data", namlen); + xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0); + return STAT_OK; +#ifdef SO_TIMESTAMP +# ifdef SCM_TIMESTAMP + case SCM_TIMESTAMP: +# else + case SO_TIMESTAMP: +# endif + tv = (struct timeval *)CMSG_DATA(cmsg); + cmsgtype = +#ifdef SCM_TIMESTAMP + "SCM_TIMESTAMP" /* FreeBSD */ +#else + "SO_TIMESTAMP" /* Linux */ +#endif + ; + cmsgname = "timestamp"; + cmsgenvn = "TIMESTAMP"; + { time_t t = tv->tv_sec; ctime_r(&t, valbuff); } + sprintf(strchr(valbuff, '\0')-1/*del \n*/, ", %06ld usecs", tv->tv_usec); + break; +#endif /* defined(SO_TIMESTAMP) */ + ; + } + /* when we come here we provide a single parameter + with type in cmsgtype, name in cmsgname, + and value already in valbuff */ + *num = 1; + if (strlen(cmsgtype) >= typlen) Fatal("buff too short"); + strncpy(typbuff, cmsgtype, typlen); + if (strlen(cmsgname) >= namlen) Fatal("buff too short"); + strncpy(nambuff, cmsgname, namlen); + if (strlen(cmsgenvn) >= envlen) Fatal("buff too short"); + strncpy(envbuff, cmsgenvn, envlen); + return STAT_OK; + +#else /* !defined(CMSG_DATA) */ + + return STAT_NORETRY; + +#endif /* !defined(CMSG_DATA) */ +} +#endif /* HAVE_STRUCT_CMSGHDR */ + + +/* return the name of the interface with given index + or NULL if is fails + The system call requires an arbitrary socket; the calling program may + provide one in parameter ins to avoid creation of a dummy socket. ins must + be <0 if it does not specify a socket fd. */ +char *xiogetifname(int ind, char *val, int ins) { +#if !HAVE_IF_INDEXTONAME + int s; + struct ifreq ifr; + + if (ins >= 0) { + s = ins; + } else { + if ((s = Socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { + Error1("socket(PF_INET, SOCK_DGRAM, IPPROTO_IP): %s", strerror(errno)); + return NULL; + } + } + +#if HAVE_STRUCT_IFREQ_IFR_INDEX + ifr.ifr_index = ind; +#elif HAVE_STRUCT_IFREQ_IFR_IFINDEX + ifr.ifr_ifindex = ind; +#endif +#ifdef SIOCGIFNAME + if(Ioctl(s, SIOCGIFNAME, &ifr) < 0) { +#if HAVE_STRUCT_IFREQ_IFR_INDEX + Info3("ioctl(%d, SIOCGIFNAME, {..., ifr_index=%d, ...}: %s", + s, ifr.ifr_index, strerror(errno)); +#elif HAVE_STRUCT_IFREQ_IFR_IFINDEX + Info3("ioctl(%d, SIOCGIFNAME, {..., ifr_ifindex=%d, ...}: %s", + s, ifr.ifr_ifindex, strerror(errno)); +#endif + if (ins < 0) Close(s); + return NULL; + } +#endif /* SIOCGIFNAME */ + if (ins < 0) Close(s); + strcpy(val, ifr.ifr_name); + return val; +#else /* HAVE_IF_INDEXTONAME */ + return if_indextoname(ind, val); +#endif /* HAVE_IF_INDEXTONAME */ +} + + +/* parses a network specification consisting of an address and a mask. */ +int xioparsenetwork(const char *rangename, int pf, struct xiorange *range) { + size_t addrlen = 0, masklen = 0; + int result; + + switch (pf) { +#if WITH_IP4 + case PF_INET: + return xioparsenetwork_ip4(rangename, range); + break; +#endif /* WITH_IP4 */ +#if WITH_IP6 + case PF_INET6: + return xioparsenetwork_ip6(rangename, range); + break; +#endif /* WITH_IP6 */ + case PF_UNSPEC: + { + char *addrname; + const char *maskname; + if ((maskname = strchr(rangename, ':')) == NULL) { + Error1("syntax error in range \"%s\": use :", rangename); + return STAT_NORETRY; + } + ++maskname; /* skip ':' */ + if ((addrname = Malloc(maskname-rangename)) == NULL) { + return STAT_NORETRY; + } + strncpy(addrname, rangename, maskname-rangename-1); + addrname[maskname-rangename-1] = '\0'; + result = + dalan(addrname, (char *)&range->netaddr.soa.sa_data, &addrlen, + sizeof(range->netaddr)-(size_t)(&((struct sockaddr *)0)->sa_data) + /* data length */); + if (result < 0) { + Error1("data too long: \"%s\"", addrname); + free(addrname); return STAT_NORETRY; + } else if (result > 0) { + Error1("syntax error in \"%s\"", addrname); + free(addrname); return STAT_NORETRY; + } + free(addrname); + result = + dalan(maskname, (char *)&range->netmask.soa.sa_data, &masklen, + sizeof(range->netaddr)-(size_t)(&((struct sockaddr *)0)->sa_data) + /* data length */); + if (result < 0) { + Error1("data too long: \"%s\"", maskname); + return STAT_NORETRY; + } else if (result > 0) { + Error1("syntax error in \"%s\"", maskname); + return STAT_NORETRY; + } + if (addrlen != masklen) { + Error2("network address is "F_Zu" bytes long, mask is "F_Zu" bytes long", + addrlen, masklen); + /* recover by padding the shorter component with 0 */ + memset((char *)&range->netaddr.soa.sa_data+addrlen, 0, + MAX(0, addrlen-masklen)); + memset((char *)&range->netmask.soa.sa_data+masklen, 0, + MAX(0, masklen-addrlen)); + } + } + break; + default: + Error1("range option not supported with address family %d", pf); + return STAT_NORETRY; + } + return STAT_OK; +} + + +/* parses a string of form address/bits or address:mask, and fills the fields + of the range union. The addr component is masked with mask. */ +int xioparserange(const char *rangename, int pf, struct xiorange *range) { + int i; + if (xioparsenetwork(rangename, pf, range) < 0) { + return -1; + } + /* we have parsed the address and mask; now we make sure that the stored + address has 0 where mask is 0, to simplify comparisions */ + switch (pf) { +#if WITH_IP4 + case PF_INET: + range->netaddr.ip4.sin_addr.s_addr &= range->netmask.ip4.sin_addr.s_addr; + break; +#endif /* WITH_IP4 */ +#if WITH_IP6 + case PF_INET6: + return xiorange_ip6andmask(range); + break; +#endif /* WITH_IP6 */ + case PF_UNSPEC: + for (i = 0; i < sizeof(range->netaddr); ++i) { + ((char *)&range->netaddr)[i] &= ((char *)&range->netmask)[i]; + } + break; + default: + Error1("range option not supported with address family %d", pf); + return STAT_NORETRY; + } + return 0; +} + + +/* set environment variables describing (part of) a socket address, e.g. + SOCAT_SOCKADDR. lr (local/remote) specifies a string like "SOCK" or "PEER". + proto should correspond to the third parameter of socket(2) and is used to + determine the presence of port information. */ +int xiosetsockaddrenv(const char *lr, + union sockaddr_union *sau, socklen_t salen, + int proto) { +# define XIOSOCKADDRENVLEN 256 + char namebuff[XIOSOCKADDRENVLEN]; + char valuebuff[XIOSOCKADDRENVLEN]; + int idx = 0, result; + + strcpy(namebuff, lr); + switch (sau->soa.sa_family) { +#if WITH_UNIX + case PF_UNIX: + result = + xiosetsockaddrenv_unix(idx, strchr(namebuff, '\0'), XIOSOCKADDRENVLEN-strlen(lr), + valuebuff, XIOSOCKADDRENVLEN, + &sau->un, salen, proto); + xiosetenv(namebuff, valuebuff, 1); + break; +#endif /* WITH_UNIX */ +#if WITH_IP4 + case PF_INET: + do { + result = + xiosetsockaddrenv_ip4(idx, strchr(namebuff, '\0'), XIOSOCKADDRENVLEN-strlen(lr), + valuebuff, XIOSOCKADDRENVLEN, + &sau->ip4, proto); + xiosetenv(namebuff, valuebuff, 1); + namebuff[strlen(lr)] = '\0'; ++idx; + } while (result > 0); + break; +#endif /* WITH_IP4 */ +#if WITH_IP6 + case PF_INET6: + strcpy(namebuff, lr); + do { + result = + xiosetsockaddrenv_ip6(idx, strchr(namebuff, '\0'), XIOSOCKADDRENVLEN-strlen(lr), + valuebuff, XIOSOCKADDRENVLEN, + &sau->ip6, proto); + xiosetenv(namebuff, valuebuff, 1); + namebuff[strlen(lr)] = '\0'; ++idx; + } while (result > 0); + break; +#endif /* WITH_IP6 */ +#if LATER + case PF_PACKET: + result = xiosetsockaddrenv_packet(lr, (void *)sau, proto); break; +#endif + default: + result = -1; + break; + } + return result; +# undef XIOSOCKADDRENVLEN +} + #endif /* _WITH_SOCKET */ + +/* these do sockets internally */ + +/* retrieves options so-type and so-prototype from opts, calls socketpair, and + ev. generates an appropriate error message. + returns 0 on success or -1 if an error occurred. */ +int +xiosocket(struct opt *opts, int pf, int socktype, int proto, int msglevel) { + int result; + + retropt_int(opts, OPT_SO_TYPE, &socktype); + retropt_int(opts, OPT_SO_PROTOTYPE, &proto); + result = Socket(pf, socktype, proto); + if (result < 0) { + Msg4(msglevel, "socket(%d, %d, %d): %s", + pf, socktype, proto, strerror(errno)); + return -1; + } + return result; +} + +/* retrieves options so-type and so-prototype from opts, calls socketpair, and + ev. generates an appropriate error message. + returns 0 on success or -1 if an error occurred. */ +int +xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]) { + int result; + + retropt_int(opts, OPT_SO_TYPE, &socktype); + retropt_int(opts, OPT_SO_PROTOTYPE, &proto); + result = Socketpair(pf, socktype, proto, sv); + if (result < 0) { + Error5("socketpair(%d, %d, %d, %p): %s", + pf, socktype, proto, sv, strerror(errno)); + return -1; + } + return result; +} diff --git a/xio-socket.h b/xio-socket.h index d218357..a35f3d2 100644 --- a/xio-socket.h +++ b/xio-socket.h @@ -1,10 +1,23 @@ /* source: xio-socket.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_socket_h_included #define __xio_socket_h_included 1 +/* SO_PROTOTYPE is OS defined on Solaris, HP-UX; we lend this for a more + general purpose */ +#ifndef SO_PROTOTYPE +#define SO_PROTOTYPE 0x9999 +#endif + +extern const union xioaddr_desc *xioaddrs_socket_connect[]; +extern const union xioaddr_desc *xioaddrs_socket_listen[]; +extern const union xioaddr_desc *xioaddrs_socket_sendto[]; +extern const union xioaddr_desc *xioaddrs_socket_datagram[]; +extern const union xioaddr_desc *xioaddrs_socket_recvfrom[]; +extern const union xioaddr_desc *xioaddrs_socket_recv[]; + extern const struct optdesc opt_connect_timeout; extern const struct optdesc opt_so_debug; extern const struct optdesc opt_so_acceptconn; @@ -31,6 +44,7 @@ extern const struct optdesc opt_so_detach_filter; extern const struct optdesc opt_so_bindtodevice; extern const struct optdesc opt_so_bsdcompat; extern const struct optdesc opt_so_cksumrecv; +extern const struct optdesc opt_so_timestamp; extern const struct optdesc opt_so_kernaccept; extern const struct optdesc opt_so_no_check; extern const struct optdesc opt_so_noreuseaddr; @@ -50,18 +64,27 @@ extern const struct optdesc opt_fiosetown; extern const struct optdesc opt_siocspgrp; extern const struct optdesc opt_bind; extern const struct optdesc opt_protocol_family; +extern const struct optdesc opt_setsockopt_int; +extern const struct optdesc opt_setsockopt_bin; +extern const struct optdesc opt_setsockopt_string; + + +extern +char *xiogetifname(int ind, char *val, int ins); extern int retropt_socket_pf(struct opt *opts, int *pf); extern int xioopen_connect(struct single *fd, struct sockaddr *us, size_t uslen, struct sockaddr *them, size_t themlen, - struct opt *opts, int pf, int stype, int proto, + struct opt *opts, + int pf, int socktype, int protocol, bool alt); extern int _xioopen_connect(struct single *fd, struct sockaddr *us, size_t uslen, struct sockaddr *them, size_t themlen, - struct opt *opts, int pf, int stype, int proto, + struct opt *opts, + int pf, int socktype, int protocol, bool alt, int level); /* common to xioopen_udp_sendto, ..unix_sendto, ..rawip */ @@ -81,10 +104,25 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags, struct sockaddr *us, socklen_t uslen, struct opt *opts, int pf, int socktype, int proto, int level); +extern +int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv); extern -int xiogetpacketsrc(int fd, union sockaddr_union *pa, socklen_t *palen); +int xiogetpacketsrc(int fd, struct msghdr *msgh); extern int xiocheckpeer(xiosingle_t *xfd, union sockaddr_union *pa, union sockaddr_union *la); +extern +int xiosetsockaddrenv(const char *lr, union sockaddr_union *sau, socklen_t salen, int proto); + +extern +int xioparsenetwork(const char *rangename, int pf, + struct xiorange *range); +extern +int xioparserange(const char *rangename, int pf, struct xiorange *range); + +extern int +xiosocket(struct opt *opts, int pf, int socktype, int proto, int level); +extern int +xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]); #endif /* !defined(__xio_socket_h_included) */ diff --git a/xio-socks.c b/xio-socks.c index 3e8a403..82b600d 100644 --- a/xio-socks.c +++ b/xio-socks.c @@ -119,7 +119,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts xfd->para.socket.ip.res_opts[1], xfd->para.socket.ip.res_opts[0], 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\"", @@ -213,28 +213,24 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts #if WITH_RETRY if (dofork) { pid_t pid; - while ((pid = Fork()) < 0) { - int level = E_ERROR; - if (xfd->forever || xfd->retry) { - level = E_WARN; - } - Msg1(level, "fork(): %s", strerror(errno)); - if (xfd->forever || xfd->retry--) { + int level = E_ERROR; + if (xfd->forever || xfd->retry) { + level = E_WARN; /* most users won't expect a problem here, + so Notice is too weak */ + } + while ((pid = xio_fork(false, level)) < 0) { + if (xfd->forever || --xfd->retry) { Nanosleep(&xfd->intervall, NULL); continue; } return STAT_RETRYLATER; } - if (pid == 0) { /* child process */ - Info1("just born: socks client process "F_pid, Getpid()); - /* drop parents locks, reset FIPS... */ - if (xio_forked_inchild() != 0) { - Exit(1); - } + if (pid == 0) { /* child process */ xfd->forever = false; xfd->retry = 0; break; } + /* parent process */ Notice1("forked off child process "F_pid, pid); Close(xfd->fd1); diff --git a/xio-socks5.c b/xio-socks5.c index ac76100..7c0f9e0 100644 --- a/xio-socks5.c +++ b/xio-socks5.c @@ -1,4 +1,4 @@ -/* $Id$ */ +/* source: xio-socks5.c */ /* Copyright Gerhard Rieger 2004-2007 */ /* Published under the GNU General Public License V.2, see file COPYING */ diff --git a/xio-streams.c b/xio-streams.c new file mode 100644 index 0000000..910b53e --- /dev/null +++ b/xio-streams.c @@ -0,0 +1,79 @@ +/* source: xio-streams.c */ +/* Copyright Gerhard Rieger 2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +/* this file contains definitions and functions for handling POSIX STREAMS */ + +/* with this source file a new experimental approach is being introduced: + normally when adding a new option at least four existing files have to be + adapted; this is similar for new address types. + + in the future i would like to have a more automatic assembling of socat from + topic oriented source files. this should make integration and control of + contributions more easy. + + all code of a new topic - address and option definitions, open code, option + handing code, ev.parser code, etc. should go into one source file. the + selection of the desired code parts during the compilation is done by + setting cpp defines. + + in the same was all public declarations should go in one header (.h) file. +*/ + +/* do not compile this file directly but include it from other .c files. with + CPP defines you select one part you want to really get included: + + ENABLE_OPTIONS: activate the definition of the address option records + ENABLE_APPLYOPTS: C code that applies the address option passed in opt +*/ + +#ifdef ENABLE_OPTIONS + +#ifdef I_POP +const struct optdesc opt_streams_i_pop_all = { "streams-i-pop-all", "pop-all", OPT_STREAMS_I_POP_ALL, GROUP_FD, PH_FD, TYPE_BOOL, OFUNC_STREAMS_I_POP_ALL, 0, 0 }; +#endif +#ifdef I_PUSH +const struct optdesc opt_streams_i_push = { "streams-i-push", "push", OPT_STREAMS_I_PUSH, GROUP_FD, PH_FD, TYPE_STRING, OFUNC_STREAMS_I_PUSH, 0, 0 }; +#endif + +#elif defined(ENABLE_APPLYOPT) + +#if 0 +void dummy(void) { + if (0) { { ; +#endif +#ifdef I_POP + } else if (opt->desc->func == OFUNC_STREAMS_I_POP_ALL) { + while (Ioctl(fd, I_POP, 0) >= 0) { + Warn2("ioctl(%d, I_POP, 0): %s", fd, strerror(errno)); + } +#endif +#ifdef I_PUSH + } else if (opt->desc->func == OFUNC_STREAMS_I_PUSH) { + if (Ioctl(fd, I_PUSH, opt->value.u_string) < 0) { + Warn3("ioctl(%d, I_PUSH, \"%s\"): %s", + fd, opt->value.u_string, strerror(errno)); + opt->desc = ODESC_ERROR; ++opt; continue; + } +#endif +#if 0 +} } } +#endif + +#else /* !defined(ENABLE_APPLYOPT) */ + +#include "xiosysincludes.h" +#if WITH_STREAMS /* make this address configure dependend */ +#include "xioopen.h" + +#include "xio-fd.h" +#include "xio-socket.h" /* _xioopen_connect() */ +#include "xio-listen.h" +#include "xio-ipapp.h" +#include "xio-openssl.h" + + + +#endif /* WITH_STREAMS */ + +#endif /* !defined(ENABLE_OPTIONS) */ diff --git a/xio-streams.h b/xio-streams.h new file mode 100644 index 0000000..bc1bdbe --- /dev/null +++ b/xio-streams.h @@ -0,0 +1,40 @@ +/* source: xio-streams.h */ +/* Copyright Gerhard Rieger 2008 */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +/* when including this file select one part that you need by defining the + appropriate CPP define: + + (none): standard define, variable, and function declarations + ENABLE_OPTCODE: option codes for use in enum e_optcode + ENABLE_OFUNC: option functions for use in enum e_func +*/ + +#ifdef ENABLE_OPTCODE + +#if 0 +enum { /* make syntax feature of editors cooperative */ +#endif + OPT_STREAMS_I_POP_ALL, /* with POSIX STREAMS */ + OPT_STREAMS_I_PUSH, /* with POSIX STREAMS */ +#if 0 +} ; +#endif + +#elif defined(ENABLE_OFUNC) + +#if 0 +enum { /* make syntax feature of editors cooperative */ +#endif + OFUNC_STREAMS_I_POP_ALL, + OFUNC_STREAMS_I_PUSH, +#if 0 +} ; +#endif + +#else /* normal declarations */ + +extern const struct optdesc opt_streams_i_pop_all; +extern const struct optdesc opt_streams_i_push; + +#endif diff --git a/xio-system.c b/xio-system.c index 6bff074..c293d42 100644 --- a/xio-system.c +++ b/xio-system.c @@ -35,10 +35,11 @@ static int xioopen_system(int argc, const char *argv[], struct opt *opts, ) { int status; char *path = NULL; + int duptostderr; int result; const char *string = argv[1]; - status = _xioopen_foxec_end(xioflags, &fd->stream, groups, &opts); + status = _xioopen_foxec_end(xioflags, &fd->stream, groups, &opts, &duptostderr); if (status < 0) return status; if (status == 0) { /* child */ int numleft; @@ -54,6 +55,11 @@ static int xioopen_system(int argc, const char *argv[], struct opt *opts, return STAT_NORETRY; } + /* only now redirect stderr */ + if (duptostderr >= 0) { + diag_dup(); + Dup2(duptostderr, 2); + } Info1("executing shell command \"%s\"", string); result = System(string); if (result != 0) { diff --git a/xio-tcpwrap.c b/xio-tcpwrap.c index a81800f..d8a03a9 100644 --- a/xio-tcpwrap.c +++ b/xio-tcpwrap.c @@ -1,5 +1,5 @@ /* source: xio-tcpwrap.c */ -/* Copyright Gerhard Rieger 2006-2007 */ +/* Copyright Gerhard Rieger 2006-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for tcpwrapper handling stuff */ @@ -93,6 +93,7 @@ int xio_tcpwrap_check(xiosingle_t *xfd, union sockaddr_union *us, if (!xfd->para.socket.ip.dolibwrap) { return 0; } + if (us == NULL || them == NULL) { return -1; } #if defined(HAVE_HOSTS_ALLOW_TABLE) save_hosts_allow_table = hosts_allow_table; diff --git a/xio-termios.c b/xio-termios.c index 04e46f3..4cddaf9 100644 --- a/xio-termios.c +++ b/xio-termios.c @@ -1,5 +1,5 @@ /* source: xio-termios.c */ -/* Copyright Gerhard Rieger 2001-2006 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for terminal I/O options */ @@ -10,6 +10,7 @@ #include "xio-termios.h" /****** TERMIOS addresses ******/ +#if _WITH_TERMIOS #if WITH_TERMIOS const struct optdesc opt_tiocsctty={ "tiocsctty", "ctty",OPT_TIOCSCTTY, GROUP_TERMIOS, PH_LATE2, TYPE_BOOL, OFUNC_SPEC }; @@ -42,8 +43,10 @@ const struct optdesc opt_cr2 = { "cr2", NULL, OPT_CR2, GROUP_TERMIOS # endif # ifdef CR3 const struct optdesc opt_cr3 = { "cr3", NULL, OPT_CR3, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, CR3, CRDLY }; -#endif +# endif +# if CRDLY_SHIFT >= 0 const struct optdesc opt_crdly = { "crdly", NULL, OPT_CRDLY, GROUP_TERMIOS, PH_FD, TYPE_UINT, OFUNC_TERMIOS_VALUE, 1, CRDLY, CRDLY_SHIFT }; +# endif #endif /* defined(CRDLY) */ #ifdef NLDLY # ifdef NL0 @@ -90,8 +93,10 @@ const struct optdesc opt_tab3 = { "tab3", NULL, OPT_TAB3, GROUP_TERMIOS # ifdef XTABS const struct optdesc opt_xtabs = { "xtabs", NULL, OPT_XTABS, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_FLAG, 1, XTABS, TABDLY }; # endif +# if TABDLY_SHIFT >= 0 const struct optdesc opt_tabdly = { "tabdly", NULL, OPT_TABDLY, GROUP_TERMIOS, PH_FD, TYPE_UINT, OFUNC_TERMIOS_VALUE, 1, TABDLY, TABDLY_SHIFT }; -#endif +# endif +#endif /* defined(TABDLY) */ #ifdef BSDLY # ifdef BS0 const struct optdesc opt_bs0 = { "bs0", NULL, OPT_BS0, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, BS0, BSDLY }; @@ -196,7 +201,9 @@ const struct optdesc opt_cs5 = { "cs5", NULL, OPT_CS5, GROUP_TERMIOS const struct optdesc opt_cs6 = { "cs6", NULL, OPT_CS6, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, CS6, CSIZE }; const struct optdesc opt_cs7 = { "cs7", NULL, OPT_CS7, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, CS7, CSIZE }; const struct optdesc opt_cs8 = { "cs8", NULL, OPT_CS8, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, CS8, CSIZE }; +#if CSIZE_SHIFT >= 0 const struct optdesc opt_csize = { "csize", NULL, OPT_CSIZE, GROUP_TERMIOS, PH_FD, TYPE_UINT, OFUNC_TERMIOS_VALUE, 2, CSIZE, CSIZE_SHIFT }; +#endif const struct optdesc opt_cstopb = { "cstopb", NULL, OPT_CSTOPB, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 2, CSTOPB }; const struct optdesc opt_cread = { "cread", NULL, OPT_CREAD, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 2, CREAD }; const struct optdesc opt_parenb = { "parenb", NULL, OPT_PARENB, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 2, PARENB }; @@ -324,3 +331,5 @@ int xiotermios_clrflag(int fd, int word, tcflag_t mask) { return 0; } +#endif /* _WITH_TERMIOS */ + diff --git a/xio-termios.h b/xio-termios.h index 00e7118..7944c67 100644 --- a/xio-termios.h +++ b/xio-termios.h @@ -1,5 +1,5 @@ /* source: xio-termios.h */ -/* Copyright Gerhard Rieger 2001-2006 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_termios_h_included @@ -138,10 +138,10 @@ extern const struct optdesc opt_sane; extern const struct optdesc opt_ispeed; extern const struct optdesc opt_ospeed; -#if WITH_TERMIOS /* otherwise tcflag_t might be reported undefined */ +#if _WITH_TERMIOS /* otherwise tcflag_t might be reported undefined */ extern int xiotermios_setflag(int fd, int word, tcflag_t mask); extern int xiotermios_clrflag(int fd, int word, tcflag_t mask); extern int xiotermiosflag_applyopt(int fd, struct opt *opt); -#endif /* WITH_TERMIOS */ +#endif /* _WITH_TERMIOS */ #endif /* !defined(__xio_termios_h_included) */ diff --git a/xio-test.c b/xio-test.c index 52c46e4..1488622 100644 --- a/xio-test.c +++ b/xio-test.c @@ -1,4 +1,4 @@ -/* $Id$ */ +/* source: xio-test.c */ /* Copyright Gerhard Rieger 2007 */ /* Published under the GNU General Public License V.2, see file COPYING */ diff --git a/xio-tun.c b/xio-tun.c index 2f989ca..7aa2311 100644 --- a/xio-tun.c +++ b/xio-tun.c @@ -1,5 +1,5 @@ /* source: xio-tun.c */ -/* Copyright Gerhard Rieger 2007 */ +/* Copyright Gerhard Rieger 2007-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for opening addresses of tun/tap type */ @@ -17,8 +17,6 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3); -#define XIO_OFFSETOF(x) ((size_t)&((xiosingle_t *)0)->x) - /****** TUN addresses ******/ const struct optdesc opt_tun_device = { "tun-device", NULL, OPT_TUN_DEVICE, GROUP_TUN, PH_OPEN, TYPE_FILENAME, OFUNC_SPEC }; const struct optdesc opt_tun_name = { "tun-name", NULL, OPT_TUN_NAME, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC }; @@ -46,20 +44,20 @@ 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 }; #endif -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(":/") }; +static const struct xioaddr_endpoint_desc xioendpoint_tun1 = { XIOADDR_SYS, "tun", 1, XIOBIT_ALL, GROUP_FD|GROUP_NAMED|GROUP_OPEN|GROUP_TUN, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_tun, 0, 0, 0 HELP(":/") }; const union xioaddr_desc *xioaddrs_tun[] = { (union xioaddr_desc *)&xioendpoint_tun1, NULL }; - -// "if-name"=tun3 +/* "if-name"=tun3 // "route"=address/netmask // "ip6-route"=address/netmask // "iff-broadcast" // "iff-debug" // "iff-promisc" // see .../linux/if.h +*/ #if LATER @@ -75,7 +73,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl char *tundevice = NULL; char *tunname = NULL, *tuntype = NULL; int pf = /*! PF_UNSPEC*/ PF_INET; - union xiorange_union network; + struct xiorange network; bool no_pi = false; const char *namedargv[] = { "tun", NULL, NULL }; int rw = (xioflags & XIO_ACCMODE); @@ -162,12 +160,14 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl return result; } socket_init(pf, (union sockaddr_union *)&ifr.ifr_addr); - ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = network.ip4.netaddr; + ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = + network.netaddr.ip4.sin_addr; if (Ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) { Error4("ioctl(%d, SIOCSIFADDR, {\"%s\", \"%s\"}: %s", sockfd, ifr.ifr_name, ifaddr, strerror(errno)); } - ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr = network.ip4.netmask; + ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr = + network.netmask.ip4.sin_addr; if (Ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) { Error4("ioctl(%d, SIOCSIFNETMASK, {\"0x%08u\", \"%s\"}, %s", sockfd, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr, diff --git a/xio-udp.c b/xio-udp.c index 9e964af..2c2bd9a 100644 --- a/xio-udp.c +++ b/xio-udp.c @@ -101,7 +101,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, union sockaddr_union themunion; union sockaddr_union *them = &themunion; int socktype = SOCK_DGRAM; - fd_set in, out, expt; + struct pollfd readfd; bool dofork = false; pid_t pid; char *rangename; @@ -133,7 +133,6 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, fd->stream.fdtype = FDTYPE_SINGLE; uslen = socket_init(pf, &us); - retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_bind(opts, pf, socktype, IPPROTO_UDP, (struct sockaddr *)&us, &uslen, 1, fd->stream.para.socket.ip.res_opts[1], @@ -164,7 +163,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, #if WITH_IP4 /*|| WITH_IP6*/ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { - if (parserange(rangename, pf, &fd->stream.para.socket.range) < 0) { + if (xioparserange(rangename, pf, &fd->stream.para.socket.range) < 0) { free(rangename); return STAT_NORETRY; } @@ -195,8 +194,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, union sockaddr_union _sockname; union sockaddr_union *la = &_sockname; /* local address */ - if ((fd->stream.fd1 = Socket(pf, socktype, ipproto)) < 0) { - Error4("socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno)); + if ((fd->stream.fd1 = xiosocket(opts, pf, socktype, ipproto, E_ERROR)) < 0) { return STAT_RETRYLATER; } /*0 Info4("socket(%d, %d, %d) -> %d", pf, socktype, ipproto, fd->stream.fd);*/ @@ -225,9 +223,9 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, Notice1("listening on UDP %s", sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff))); - FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt); - FD_SET(fd->stream.fd1, &in); - while (Select(fd->stream.fd1+1, &in, &out, &expt, NULL) < 0) { + readfd.fd = fd->stream.fd1; + readfd.events = POLLIN|POLLERR; + while (xiopoll(&readfd, 1, NULL) < 0) { if (errno != EINTR) break; } @@ -249,33 +247,29 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, if (xiocheckpeer(&fd->stream, them, la) < 0) { /* drop packet */ char buff[512]; - Recv(fd->stream.fd1, buff, sizeof(buff), 0); + Recv(fd->stream.fd1, buff, sizeof(buff), 0); /* drop packet */ + Close(fd->stream.fd1); continue; } Info1("permitting UDP connection from %s", sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff))); if (dofork) { - pid = Fork(); + pid = xio_fork(false, E_ERROR); if (pid < 0) { - Error1("fork(): %s", strerror(errno)); return STAT_RETRYLATER; } - if (pid == 0) { /* child */ - /* drop parents locks, reset FIPS... */ - if (xio_forked_inchild() != 0) { - Exit(1); - } + if (pid == 0) { /* child */ break; } - /* server: continue loop with select */ + + /* server: continue loop with socket()+recvfrom() */ /* when we dont close this we get awkward behaviour on Linux 2.4: recvfrom gives 0 bytes with invalid socket address */ if (Close(fd->stream.fd1) < 0) { Info2("close(%d): %s", fd->stream.fd1, strerror(errno)); } - Notice1("forked off child process "F_pid, pid); Sleep(1); /*! give child a chance to consume the old packet */ continue; @@ -292,6 +286,14 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, return STAT_RETRYLATER; } + /* set the env vars describing the local and remote sockets */ + if (Getsockname(fd->stream.fd1, &us.soa, &uslen) < 0) { + Warn4("getsockname(%d, %p, {%d}): %s", + fd->stream.fd1, &us.soa, uslen, strerror(errno)); + } + xiosetsockaddrenv("SOCK", &us, uslen, IPPROTO_UDP); + xiosetsockaddrenv("PEER", them, themlen, IPPROTO_UDP); + applyopts_fchown(fd->stream.fd1, opts); applyopts(fd->stream.fd1, opts, PH_LATE); @@ -313,6 +315,8 @@ int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts, argv[0], argc-1); return STAT_NORETRY; } + + retropt_socket_pf(opts, &pf); if ((result = _xioopen_udp_sendto(argv[1], argv[2], opts, xioflags, xxfd, groups, pf, socktype, ipproto)) != STAT_OK) { @@ -322,6 +326,12 @@ int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts, return STAT_OK; } +/* + applies and consumes the following option: + PH_INIT, PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE + OFUNC_OFFSET + OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC + */ static int _xioopen_udp_sendto(const char *hostname, const char *servname, struct opt *opts, @@ -421,6 +431,7 @@ int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts, return STAT_RETRYLATER; } + retropt_socket_pf(opts, &pf); result = _xioopen_udp_sendto(hostname, argv[2], opts, xioflags, xxfd, groups, pf, socktype, ipproto); @@ -440,7 +451,7 @@ int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts, /* which reply packets will be accepted - determine by range option */ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { - if (parserange(rangename, pf, &xfd->para.socket.range) < 0) { + if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) { free(rangename); return STAT_NORETRY; } @@ -597,7 +608,7 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts, #if WITH_IP4 /*|| WITH_IP6*/ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { - if (parserange(rangename, pf, &xfd->stream.para.socket.range) < 0) { + if (xioparserange(rangename, pf, &xfd->stream.para.socket.range) < 0) { return STAT_NORETRY; } xfd->stream.para.socket.dorange = true; diff --git a/xio-unix.c b/xio-unix.c index b21839f..40980ab 100644 --- a/xio-unix.c +++ b/xio-unix.c @@ -1,5 +1,5 @@ /* source: xio-unix.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for opening addresses of UNIX socket type */ @@ -15,85 +15,85 @@ #if WITH_UNIX -static int xioopen_unix_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_unix_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_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int dummy2, int dummy3); -static int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3); +/* to avoid unneccessary "live" if () conditionals when no abstract support is + compiled in (or at least to give optimizing compilers a good chance) we need + a constant that can be used in C expressions */ +#if WITH_ABSTRACT_UNIXSOCKET +# define ABSTRACT 1 +#else +# define ABSTRACT 0 +#endif +static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3); +static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3); +static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3); +static int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3); static int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts, - int xioflags, xiofile_t *xfd, unsigned groups, - int pf, int socktype, int ipproto); + int xioflags, xiofile_t *xxfd, unsigned groups, + int abstract, int dummy2, int dummy3); 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); -#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_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_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int dummy2, int dummy3); -static int xioopen_abstract_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3); -static -int xioopen_abstract_recv(int argc, const char *argv[], struct opt *opts, - int xioflags, xiofile_t *xfd, unsigned groups, - int pf, int socktype, int ipproto); -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); -#endif /* WITH_ABSTRACT_UNIXSOCKET */ +int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3); -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(":") }; +/* the first free parameter is 0 for "normal" unix domain sockets, or 1 for + abstract unix sockets (Linux); the second and third parameters are unsused */ +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, 0, 0 HELP(":") }; const union xioaddr_desc *xioaddrs_unix_connect[] = { (union xioaddr_desc *)&xioendpoint_unix_connect1, NULL }; + #if WITH_LISTEN -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(":") }; +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, 0, 0 HELP(":") }; const union xioaddr_desc *xioaddrs_unix_listen[] = { (union xioaddr_desc *)&xioendpoint_unix_listen1, NULL }; #endif /* WITH_LISTEN */ -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(":") }; + +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, 0, 0 HELP(":") }; const union xioaddr_desc *xioaddrs_unix_sendto[] = { (union xioaddr_desc *)&xioendpoint_unix_sendto1, NULL }; -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(":") }; + +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, 0, 0, 0 HELP(":") }; 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(":") }; + +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, 0, 0, 0 HELP(":") }; 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(":") }; + +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, 0, 0, 0 HELP(":") }; const union xioaddr_desc *xioaddrs_unix_client[] = { (union xioaddr_desc *)&xioendpoint_unix_client1, NULL }; #if WITH_ABSTRACT_UNIXSOCKET -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(":") }; +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_unix_connect, 1, 0, 0 HELP(":") }; const union xioaddr_desc *xioaddrs_abstract_connect[] = { (union xioaddr_desc *)&xioendpoint_abstract_connect1, NULL }; #if WITH_LISTEN -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(":") }; +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_unix_listen, 1, 0, 0 HELP(":") }; const union xioaddr_desc *xioaddrs_abstract_listen[] = { (union xioaddr_desc *)&xioendpoint_abstract_listen1, NULL }; #endif /* WITH_LISTEN */ -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(":") }; +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_unix_sendto, 1, 0, 0 HELP(":") }; const union xioaddr_desc *xioaddrs_abstract_sendto[] = { (union xioaddr_desc *)&xioendpoint_abstract_sendto1, NULL }; -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(":") }; +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_unix_recvfrom, 1, 0, 0 HELP(":") }; 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(":") }; +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_unix_recv, 1, 0, 0 HELP(":") }; 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(":") }; +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_unix_client, 1, 0, 0 HELP(":") }; const union xioaddr_desc *xioaddrs_abstract_client[] = { (union xioaddr_desc *)&xioendpoint_abstract_client1, NULL }; #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 xioopt_unix_tightsocklen = { "unix-tightsocklen", "tightsocklen", OPT_UNIX_TIGHTSOCKLEN, GROUP_SOCK_UNIX, PH_INIT, TYPE_BOOL, OFUNC_SPEC, 0, 0 }; +/* fills the socket address struct and returns its effective length. + abstract is usually 0; != 0 generates an abstract socket address on Linux. + tight!=0 calculates the resulting length from the path length, not from the + structures length; this is more common. + the struct need not be initialized when calling this function. +*/ socklen_t -xiosetunix(struct sockaddr_un *saun, +xiosetunix(int pf, + struct sockaddr_un *saun, const char *path, bool abstract, bool tight) { size_t pathlen; socklen_t len; - if (!abstract) { - if ((pathlen = strlen(path)) > sizeof(saun->sun_path)) { - Warn2("unix socket address "F_Zu" characters long, truncating to "F_Zu"", - pathlen, sizeof(saun->sun_path)); - } - strncpy(saun->sun_path, path, sizeof(saun->sun_path)); - if (tight) { - len = sizeof(struct sockaddr_un)-sizeof(saun->sun_path)+ - MIN(pathlen, sizeof(saun->sun_path)); - } else { - len = sizeof(struct sockaddr_un); - } - } else { + socket_un_init(saun); +#ifdef WITH_ABSTRACT_UNIXSOCKET + if (abstract) { if ((pathlen = strlen(path)) >= sizeof(saun->sun_path)) { Warn2("socket address "F_Zu" characters long, truncating to "F_Zu"", pathlen+1, sizeof(saun->sun_path)); @@ -103,18 +103,41 @@ xiosetunix(struct sockaddr_un *saun, if (tight) { len = sizeof(struct sockaddr_un)-sizeof(saun->sun_path)+ MIN(pathlen+1, sizeof(saun->sun_path)); +#if HAVE_STRUCT_SOCKADDR_SALEN + saun->sun_len = len; +#endif } else { len = sizeof(struct sockaddr_un); } + return len; + } +#endif /* WITH_ABSTRACT_UNIXSOCKET */ + + if ((pathlen = strlen(path)) > sizeof(saun->sun_path)) { + Warn2("unix socket address "F_Zu" characters long, truncating to "F_Zu"", + pathlen, sizeof(saun->sun_path)); + } + strncpy(saun->sun_path, path, sizeof(saun->sun_path)); + if (tight) { + len = sizeof(struct sockaddr_un)-sizeof(saun->sun_path)+ + MIN(pathlen, sizeof(saun->sun_path)); +#if HAVE_STRUCT_SOCKADDR_SALEN + saun->sun_len = len; +#endif + } else { + len = sizeof(struct sockaddr_un); } return len; } #if WITH_LISTEN -static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) { +static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) { /* we expect the form: filename */ const char *name; xiosingle_t *xfd = &xxfd->stream; + int pf = PF_UNIX; + int socktype = SOCK_STREAM; + int protocol = 0; struct sockaddr_un us; socklen_t uslen; bool tight = true; @@ -129,48 +152,48 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i return STAT_NORETRY; } - socket_un_init(&us); - - retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); name = argv[1]; - uslen = xiosetunix(&us, name, false, tight); + retropt_socket_pf(opts, &pf); + retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); + uslen = xiosetunix(pf, &us, name, abstract, tight); - retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); - retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); - - if (opt_unlink_close) { - if ((xfd->unlink_close = strdup(name)) == NULL) { - Error1("strdup(\"%s\"): out of memory", name); + if (!(ABSTRACT && abstract)) { + /* only for non abstract because abstract do not work in file system */ + retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); + retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); + if (opt_unlink_close) { + if ((xfd->unlink_close = strdup(name)) == NULL) { + Error1("strdup(\"%s\"): out of memory", name); + } + xfd->opt_unlink_close = true; } - xfd->opt_unlink_close = true; } applyopts(-1, opts, PH_INIT); - if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; applyopts(-1, opts, PH_EARLY); - if (opt_unlink_early) { - if (Unlink(name) < 0) { - if (errno == ENOENT) { - Warn2("unlink(\"%s\"): %s", name, strerror(errno)); - } else { - Error2("unlink(\"%s\"): %s", name, strerror(errno)); + if (!(ABSTRACT && abstract)) { + if (opt_unlink_early) { + if (Unlink(name) < 0) { + if (errno == ENOENT) { + Warn2("unlink(\"%s\"): %s", name, strerror(errno)); + } else { + Error2("unlink(\"%s\"): %s", name, strerror(errno)); + } } } + + /* trying to set user-early, perm-early etc. here is useless because + file system entry is available only past bind() call. */ + applyopts_named(name, opts, PH_EARLY); /* umask! */ } - /* trying to set user-early, perm-early etc. here is useless because - file system entry is available only past bind() call. */ - applyopts_named(name, opts, PH_EARLY); /* umask! */ - - retropt_int(opts, OPT_SO_TYPE, &socktype); - opts0 = copyopts(opts, GROUP_ALL); if ((result = xioopen_listen(xfd, xioflags, (struct sockaddr *)&us, uslen, - opts, opts0, PF_UNIX, socktype, 0)) + opts, opts0, pf, socktype, protocol)) != 0) return result; return 0; @@ -178,10 +201,13 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i #endif /* WITH_LISTEN */ -static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) { +static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) { /* we expect the form: filename */ const char *name; struct single *xfd = &xxfd->stream; + int pf = PF_UNIX; + int socktype = SOCK_STREAM; + int protocol = 0; struct sockaddr_un them, us; socklen_t themlen, uslen; bool tight = true; @@ -195,15 +221,15 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, return STAT_NORETRY; } - socket_un_init(&us); - socket_un_init(&them); - - retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); name = argv[1]; - themlen = xiosetunix(&them, name, false, tight); - retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); - - if (retropt_bind(opts, AF_UNIX, socktype, 0, (struct sockaddr *)&us, &uslen, 0, 0, 0) + retropt_socket_pf(opts, &pf); + retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); + themlen = xiosetunix(pf, &them, name, abstract, tight); + if (!(ABSTRACT && abstract)) { + /* only for non abstract because abstract do not work in file system */ + retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); + } + if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen, 0, 0, 0) != STAT_NOACTION) { needbind = true; } @@ -223,23 +249,26 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, xioopen_connect(xfd, needbind?(struct sockaddr *)&us:NULL, uslen, (struct sockaddr *)&them, themlen, - opts, PF_UNIX, socktype, 0, false)) != 0) { + opts, pf, socktype, protocol, false)) != 0) { return result; } if ((result = _xio_openlate(xfd, opts)) < 0) { return result; } - return 0; + return STAT_OK; } -static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) { +static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy, int dummy3) { + /* we expect the form: filename */ const char *name; xiosingle_t *xfd = &xxfd->stream; + int pf = PF_UNIX; + int socktype = SOCK_DGRAM; + int protocol = 0; union sockaddr_union us; socklen_t uslen; bool tight = true; - int pf = PF_UNIX; bool needbind = false; bool opt_unlink_close = false; @@ -256,13 +285,17 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); name = argv[1]; - xfd->salen = xiosetunix(&xfd->peersa.un, name, false, tight); + retropt_socket_pf(opts, &pf); + xfd->salen = xiosetunix(pf, &xfd->peersa.un, name, abstract, tight); - retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); + if (!(ABSTRACT && abstract)) { + /* only for non abstract because abstract do not work in file system */ + retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); + } xfd->dtype = XIODATA_RECVFROM; - if (retropt_bind(opts, pf, socktype, 0, &us.soa, &uslen, 0, 0, 0) + if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 0, 0, 0) != STAT_NOACTION) { needbind = true; } @@ -279,15 +312,21 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i return _xioopen_dgram_sendto(needbind?&us:NULL, uslen, - opts, xioflags, xfd, groups, pf, socktype, 0); + opts, xioflags, xfd, groups, + pf, socktype, protocol); } static int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, - int xioflags, xiofile_t *xfd, unsigned groups, - int pf, int socktype, int dummy3) { + int xioflags, xiofile_t *xxfd, unsigned groups, + int abstract, int dummy2, int dummy3) { + /* we expect the form: filename */ const char *name; + xiosingle_t *xfd = &xxfd->stream; + int pf = PF_UNIX; + int socktype = SOCK_DGRAM; + int protocol = 0; struct sockaddr_un us; socklen_t uslen; bool tight = true; @@ -301,48 +340,60 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, return STAT_NORETRY; } - socket_un_init(&us); - - retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); name = argv[1]; - uslen = xiosetunix(&us, name, false, tight); + retropt_socket_pf(opts, &pf); + retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); + uslen = xiosetunix(pf, &us, name, abstract, tight); 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, protocol, (struct sockaddr *)&us, &uslen, + 1, 0, 0); retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); - if (opt_unlink_close) { - if ((xfd->stream.unlink_close = strdup(name)) == NULL) { - Error1("strdup(\"%s\"): out of memory", name); + if (!(ABSTRACT && abstract)) { + /* only for non abstract because abstract do not work in file system */ + retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); + retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); + if (opt_unlink_close) { + if ((xfd->unlink_close = strdup(name)) == NULL) { + Error1("strdup(\"%s\"): out of memory", name); + } + xfd->opt_unlink_close = true; } - xfd->stream.opt_unlink_close = true; - } - if (opt_unlink_early) { - if (Unlink(name) < 0) { - if (errno == ENOENT) { - Warn2("unlink(\"%s\"): %s", name, strerror(errno)); - } else { - Error2("unlink(\"%s\"): %s", name, strerror(errno)); + if (opt_unlink_early) { + if (Unlink(name) < 0) { + if (errno == ENOENT) { + Warn2("unlink(\"%s\"): %s", name, strerror(errno)); + } else { + Error2("unlink(\"%s\"): %s", name, strerror(errno)); + } } } } - xfd->stream.para.socket.la.soa.sa_family = pf; + xfd->para.socket.la.soa.sa_family = pf; - xfd->stream.dtype = XIODATA_RECVFROM_ONE; - return _xioopen_dgram_recvfrom(&xfd->stream, xioflags, - needbind?(struct sockaddr *)&us:NULL, uslen, - opts, pf, socktype, 0, E_ERROR); + xfd->dtype = XIODATA_RECVFROM_ONE; + return + _xioopen_dgram_recvfrom(xfd, xioflags, + needbind?(struct sockaddr *)&us:NULL, uslen, + opts, pf, socktype, protocol, E_ERROR); } static int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts, - int xioflags, xiofile_t *xfd, unsigned groups, - int pf, int socktype, int ipproto) { + int xioflags, xiofile_t *xxfd, unsigned groups, + int abstract, int dummy2, int dummy3) { + /* we expect the form: filename */ const char *name; + xiosingle_t *xfd = &xxfd->stream; + int pf = PF_UNIX; + int socktype = SOCK_DGRAM; + int protocol = 0; union sockaddr_union us; socklen_t uslen; bool tight = true; @@ -356,75 +407,96 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts, return STAT_NORETRY; } - retropt_int(opts, OPT_SO_TYPE, &socktype); - - socket_un_init(&us.un); - - retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); name = argv[1]; - uslen = xiosetunix(&us.un, name, false, tight); + retropt_socket_pf(opts, &pf); + retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); + uslen = xiosetunix(pf, &us.un, name, abstract, tight); #if 1 /*!!! why bind option? */ - retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, 1, 0, 0); + retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 1, 0, 0); #endif - retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); - if (opt_unlink_early) { - if (Unlink(name) < 0) { - if (errno == ENOENT) { - Warn2("unlink(\"%s\"): %s", name, strerror(errno)); - } else { - Error2("unlink(\"%s\"): %s", name, strerror(errno)); + if (!(ABSTRACT && abstract)) { + /* only for non abstract because abstract do not work in file system */ + retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); + if (opt_unlink_early) { + if (Unlink(name) < 0) { + if (errno == ENOENT) { + Warn2("unlink(\"%s\"): %s", name, strerror(errno)); + } else { + Error2("unlink(\"%s\"): %s", name, strerror(errno)); + } } } - } - retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); + retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); - if (opt_unlink_close) { - if ((xfd->stream.unlink_close = strdup(name)) == NULL) { - Error1("strdup(\"%s\"): out of memory", name); + if (opt_unlink_close) { + if ((xfd->unlink_close = strdup(name)) == NULL) { + Error1("strdup(\"%s\"): out of memory", name); + } + xfd->opt_unlink_close = true; } - xfd->stream.opt_unlink_close = true; } - xfd->stream.para.socket.la.soa.sa_family = pf; + xfd->para.socket.la.soa.sa_family = pf; - xfd->stream.dtype = XIODATA_RECV; - result = _xioopen_dgram_recv(&xfd->stream, xioflags, &us.soa, uslen, - opts, pf, socktype, ipproto, E_ERROR); + xfd->dtype = XIODATA_RECV; + result = _xioopen_dgram_recv(xfd, xioflags, &us.soa, uslen, + opts, pf, socktype, protocol, E_ERROR); return result; } -static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) { - const char *name; - xiosingle_t *xfd = &xxfd->stream; - bool tight = true; - int pf = PF_UNIX; - union sockaddr_union them, us; - socklen_t themlen; - socklen_t uslen; - bool needbind = false; - bool opt_unlink_close = false; - int result; - +static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) { + /* we expect the form: filename */ if (argc != 2) { Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); } - retropt_int(opts, OPT_SO_TYPE, &socktype); + return + _xioopen_unix_client(&xxfd->stream, xioflags, groups, abstract, opts, + argv[1]); +} - uslen = socket_init(pf, &us); - themlen = socket_init(pf, &them); +/* establishes communication with an existing UNIX type socket. supports stream + and datagram socket types: first tries to connect(), but when this fails it + falls back to sendto(). + applies and consumes the following option: + PH_INIT, PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, + PH_CONNECTED, PH_LATE, ?PH_CONNECT + OFUNC_OFFSET, + OPT_PROTOCOL_FAMILY, OPT_UNIX_TIGHTSOCKLEN, OPT_UNLINK_CLOSE, OPT_BIND, + OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_CLOEXEC, OPT_USER, OPT_GROUP, ?OPT_FORK, +*/ +int +_xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups, + int abstract, struct opt *opts, const char *name) { + int pf = PF_UNIX; + int socktype = 0; /* to be determined by server socket type */ + int protocol = 0; + union sockaddr_union them, us; + socklen_t themlen, uslen; + bool tight = true; + bool needbind = false; + bool opt_unlink_close = false; + struct opt *opts0; + int result; + + applyopts(-1, opts, PH_INIT); + if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + + retropt_socket_pf(opts, &pf); retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); - name = argv[1]; - themlen = xiosetunix(&them.un, name, false, tight); + themlen = xiosetunix(pf, &them.un, name, abstract, tight); - retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); + if (!(ABSTRACT && abstract)) { + /* only for non abstract because abstract do not work in file system */ + retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); + } - if (retropt_bind(opts, pf, socktype, 0, &us.soa, &uslen, 0, 0, 0) + if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 0, 0, 0) != STAT_NOACTION) { needbind = true; } @@ -436,26 +508,29 @@ static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, i xfd->opt_unlink_close = true; } + /* save options, because we might have to start again */ + opts0 = copyopts(opts, GROUP_ALL); + /* xfd->dtype = DATA_STREAM; // is default */ if ((result = xioopen_connect(xfd, - needbind?(struct sockaddr *)&us:NULL, uslen, + needbind?(struct sockaddr *)&us:NULL, uslen, (struct sockaddr *)&them, themlen, - opts, PF_UNIX, socktype?socktype:SOCK_STREAM, 0, false)) != 0) { + opts, pf, socktype?socktype:SOCK_STREAM, protocol, + false)) != 0) { if (errno == EPROTOTYPE) { if (needbind) { Unlink(us.un.sun_path); } - applyopts(-1, opts, PH_INIT); - if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + dropopts2(opts, PH_INIT, PH_SPEC); opts = opts0; xfd->peersa = them; xfd->salen = sizeof(struct sockaddr_un); if ((result = _xioopen_dgram_sendto(needbind?&us:NULL, uslen, - opts, xioflags, xfd, groups, pf, - socktype?socktype:SOCK_DGRAM, 0)) + opts, xioflags, xfd, groups, + pf, socktype?socktype:SOCK_DGRAM, protocol)) != 0) { return result; } @@ -469,270 +544,25 @@ static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, i } -#if WITH_ABSTRACT_UNIXSOCKET -#if WITH_LISTEN -static int xioopen_abstract_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) { - /* we expect the form: filename */ - const char *name; - xiosingle_t *xfd = &xxfd->stream; - bool tight = true; - struct sockaddr_un us; - socklen_t uslen; - struct opt *opts0 = NULL; - int result; - - if (argc != 2) { - Error2("%s: wrong number of parameters (%d instead of 1)", - argv[0], argc-1); - return STAT_NORETRY; +/* returns information that can be used for constructing an environment + variable describing the socket address. + if idx is 0, this function writes "ADDR" into namebuff and the path into + valuebuff, and returns 0 (which means that no more info is there). + if idx is != 0, it returns -1 + namelen and valuelen contain the max. allowed length of output chars in the + respective buffer. + on error this function returns -1. +*/ +int +xiosetsockaddrenv_unix(int idx, char *namebuff, size_t namelen, + char *valuebuff, size_t valuelen, + struct sockaddr_un *sa, socklen_t salen, int ipproto) { + if (idx != 0) { + return -1; } - - socket_un_init(&us); - - retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); - name = argv[1]; - uslen = xiosetunix(&us, name, true, tight); - - applyopts(-1, opts, PH_INIT); - if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; - applyopts(-1, opts, PH_EARLY); - - /* trying to set user-early, perm-early etc. here is useless because - file system entry is available only past bind() call. */ - - retropt_int(opts, OPT_SO_TYPE, &socktype); - - opts0 = copyopts(opts, GROUP_ALL); - - if ((result = - xioopen_listen(xfd, xioflags, - (struct sockaddr *)&us, uslen, - opts, opts0, PF_UNIX, socktype, 0)) - != 0) - return result; + strcpy(namebuff, "ADDR"); + sockaddr_unix_info(sa, salen, valuebuff, valuelen); return 0; } -#endif /* WITH_LISTEN */ - -static int xioopen_abstract_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) { - /* we expect the form: filename */ - const char *name; - struct single *xfd = &xxfd->stream; - bool tight = true; - struct sockaddr_un them, us; - socklen_t themlen, uslen; - bool needbind = false; - int result; - - if (argc != 2) { - Error2("%s: wrong number of parameters (%d instead of 1)", - argv[0], argc-1); - return STAT_NORETRY; - } - - socket_un_init(&us); - socket_un_init(&them); - - retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); - name = argv[1]; - themlen = xiosetunix(&them, name, true, tight); - - if (retropt_bind(opts, AF_UNIX, socktype, 0, (struct sockaddr *)&us, &uslen, 0, 0, 0) - != STAT_NOACTION) { - needbind = true; - } - - applyopts(-1, opts, PH_INIT); - if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; - applyopts(-1, opts, PH_EARLY); - - if ((result = - xioopen_connect(xfd, - needbind?(struct sockaddr *)&us:NULL, uslen, - (struct sockaddr *)&them, themlen, - opts, PF_UNIX, socktype, 0, false)) != 0) { - return result; - } - if ((result = _xio_openlate(xfd, opts)) < 0) { - return result; - } - return 0; -} - - -static int xioopen_abstract_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) { - const char *name; - xiosingle_t *xfd = &xxfd->stream; - union sockaddr_union us; - socklen_t uslen; - bool tight = true; - int pf = PF_UNIX; - bool needbind = false; - - if (argc != 2) { - Error2("%s: wrong number of parameters (%d instead of 1)", - argv[0], argc-1); - return STAT_NORETRY; - } - - uslen = socket_init(pf, &us); - xfd->salen = socket_init(pf, &xfd->peersa); - - retropt_int(opts, OPT_SO_TYPE, &socktype); - - retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); - name = argv[1]; - xfd->salen = xiosetunix(&xfd->peersa.un, name, true, tight); - - xfd->dtype = XIODATA_RECVFROM; - - if (retropt_bind(opts, pf, socktype, 0, &us.soa, &uslen, 0, 0, 0) - != STAT_NOACTION) { - needbind = true; - } - - applyopts(-1, opts, PH_INIT); - if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; - - return - _xioopen_dgram_sendto(needbind?&us:NULL, uslen, - opts, xioflags, xfd, groups, pf, socktype, 0); -} - - -static -int xioopen_abstract_recvfrom(int argc, const char *argv[], struct opt *opts, - int xioflags, xiofile_t *xfd, unsigned groups, - int pf, int socktype, int dummy3) { - const char *name; - struct sockaddr_un us; - socklen_t uslen; - bool tight = true; - bool needbind = true; - - if (argc != 2) { - Error2("%s: wrong number of parameters (%d instead of 1)", - argv[0], argc-1); - return STAT_NORETRY; - } - - socket_un_init(&us); - - retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); - name = argv[1]; - uslen = xiosetunix(&us, name, true, tight); - - retropt_int(opts, OPT_SO_TYPE, &socktype); - retropt_bind(opts, pf, socktype, 0, (struct sockaddr *)&us, &uslen, 1, 0, 0); - - xfd->stream.para.socket.la.soa.sa_family = pf; - - xfd->stream.dtype = XIODATA_RECVFROM_ONE; - return _xioopen_dgram_recvfrom(&xfd->stream, xioflags, - needbind?(struct sockaddr *)&us:NULL, uslen, - opts, pf, socktype, 0, E_ERROR); -} - - -static -int xioopen_abstract_recv(int argc, const char *argv[], struct opt *opts, - int xioflags, xiofile_t *xfd, unsigned groups, - int pf, int socktype, int ipproto) { - const char *name; - union sockaddr_union us; - socklen_t uslen; - bool tight = true; - int result; - - if (argc != 2) { - Error2("%s: wrong number of parameters (%d instead of 1)", - argv[0], argc-1); - return STAT_NORETRY; - } - - retropt_int(opts, OPT_SO_TYPE, &socktype); - - socket_un_init(&us.un); - - retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); - name = argv[1]; - uslen = xiosetunix(&us.un, name, true, tight); - -#if 1 /*!!! why bind option? */ - retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, 1, 0, 0); -#endif - - xfd->stream.para.socket.la.soa.sa_family = pf; - - xfd->stream.dtype = XIODATA_RECV; - result = _xioopen_dgram_recv(&xfd->stream, xioflags, &us.soa, uslen, - opts, pf, socktype, ipproto, E_ERROR); - return result; -} - - -static int xioopen_abstract_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int dummy1, int socktype, int dummy3) { - const char *name; - xiosingle_t *xfd = &xxfd->stream; - bool tight = true; - int pf = PF_UNIX; - union sockaddr_union them, us; - socklen_t themlen; - socklen_t uslen; - bool needbind = false; - int result; - - if (argc != 2) { - Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); - } - - retropt_int(opts, OPT_SO_TYPE, &socktype); - - uslen = socket_init(pf, &us); - themlen = socket_init(pf, &them); - - retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); - name = argv[1]; - themlen = xiosetunix(&them.un, name, true, tight); - - if (retropt_bind(opts, pf, socktype, 0, &us.soa, &uslen, 0, 0, 0) - != STAT_NOACTION) { - needbind = true; - } - - /* xfd->dtype = DATA_STREAM; // is default */ - if ((result = - xioopen_connect(xfd, - needbind?(struct sockaddr *)&us:NULL, uslen, - (struct sockaddr *)&them, themlen, - opts, PF_UNIX, socktype?socktype:SOCK_STREAM, 0, false)) != 0) { - if (errno == EPROTOTYPE) { - if (needbind) { - Unlink(us.un.sun_path); - } - - /* ...res_opts[] */ - applyopts(-1, opts, PH_INIT); - if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; - - xfd->peersa = them; - xfd->salen = themlen; - if ((result = - _xioopen_dgram_sendto(needbind?&us:NULL, uslen, - opts, xioflags, xfd, groups, pf, - socktype?socktype:SOCK_DGRAM, 0)) - != 0) { - return result; - } - xfd->dtype = XIODATA_RECVFROM; - } - } - if ((result = _xio_openlate(xfd, opts)) < 0) { - return result; - } - return 0; -} - -#endif /* WITH_ABSTRACT_UNIXSOCKET */ #endif /* WITH_UNIX */ diff --git a/xio-unix.h b/xio-unix.h index 10e80c4..b80e7b0 100644 --- a/xio-unix.h +++ b/xio-unix.h @@ -1,5 +1,5 @@ /* source: xio-unix.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_unix_h_included @@ -18,12 +18,21 @@ extern const union xioaddr_desc *xioaddrs_abstract_recvfrom[]; extern const union xioaddr_desc *xioaddrs_abstract_recv[]; extern const union xioaddr_desc *xioaddrs_abstract_client[]; -extern const struct optdesc opt_unix_tightsocklen; +extern const struct optdesc xioopt_unix_tightsocklen; extern socklen_t -xiosetunix(struct sockaddr_un *saun, +xiosetunix(int pf, + struct sockaddr_un *saun, const char *path, bool abstract, bool tight); +extern int +xiosetsockaddrenv_unix(int idx, char *namebuff, size_t namelen, + char *valuebuff, size_t valuelen, + struct sockaddr_un *sa, socklen_t salen, int ipproto); + +extern int +_xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups, + int abstract, struct opt *opts, const char *name); #endif /* !defined(__xio_unix_h_included) */ diff --git a/xio.h b/xio.h index 1237318..a08341e 100644 --- a/xio.h +++ b/xio.h @@ -180,10 +180,10 @@ struct xioaddr_inter_desc { } ; struct xioaddr_endpoint_desc { - int tag; /* 0: endpoint addr; 1: inter addr */ + int tag; /* XIOADDR_ENDPOINT, XIOADDR_INTER */ const char *defname; /* main (canonical) name of address */ int numparams; /* number of required parameters */ - int leftdirs; + int leftdirs; /* XIOBIT_* */ unsigned groups; int howtoshut; int howtoclose; @@ -337,6 +337,8 @@ typedef struct single { int (*sigchild)(struct single *); /* callback after sigchild */ } child; pid_t ppid; /* parent pid, only if we send it signals */ + int escape; /* escape character; -1 for no escape */ + bool actescape; /* escape character found in input data */ pthread_t subthread; /* thread handling next inter-addr in chain */ union { #if 0 @@ -350,7 +352,7 @@ typedef struct single { union sockaddr_union la; /* local socket address */ bool emptyiseof; /* with dgram: empty packet means EOF */ bool dorange; - union xiorange_union range; /* restrictions for peer address */ + struct xiorange range; /* restrictions for peer address */ #if _WITH_IP4 || _WITH_IP6 struct { unsigned int res_opts[2]; /* bits to be set in _res.options are @@ -532,7 +534,7 @@ union integral { } u_ip_mreq; #endif #if WITH_IP4 - in_addr_t u_ip4addr; + struct in_addr u_ip4addr; #endif } ; @@ -554,6 +556,8 @@ union integral { struct opt { const struct optdesc *desc; union integral value; + union integral value2; + union integral value3; } ; /* with threading, the arguments indirectly passed to xioengine() */ @@ -578,11 +582,14 @@ extern xiofile_t *sock[XIO_MAXSOCK]; not even by external changes correctable */ extern int xioinitialize(int xioflags); +extern int xioinitialize2(void); +extern pid_t xio_fork(bool subchild, int level); extern int xio_forked_inchild(void); extern int xiosetopt(char what, const char *arg); extern int xioinqopt(char what, char *arg, size_t n); extern xiofile_t *xioopen(const char *args, 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 xiofile_t *xioopenx(const char *addr, int xioflags, int infd, int outfd); +extern int xiosocketpair2(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); diff --git a/xioclose.c b/xioclose.c index aaff0b8..ede3820 100644 --- a/xioclose.c +++ b/xioclose.c @@ -47,15 +47,6 @@ int xioclose1(struct single *pipe) { break; #endif /* WITH_OPENSSL */ -#if WITH_TERMIOS - if (pipe->ttyvalid) { - if (Tcsetattr(pipe->fd1, 0, &pipe->savetty) < 0) { - Warn2("cannot restore terminal settings on fd %d: %s", - pipe->fd1, strerror(errno)); - } - } -#endif /* WITH_TERMIOS */ - case XIOCLOSE_SIGTERM: if (pipe->child.pid > 0) { if (Kill(pipe->child.pid, SIGTERM) < 0) { @@ -94,10 +85,19 @@ int xioclose1(struct single *pipe) { break; default: - Error2("xioclose(): bad end action 0x%x on 0x%x", pipe->howtoclose, pipe); + Error2("xioclose(): bad close action 0x%x on 0x%x", pipe->howtoclose, pipe); break; } +#if WITH_TERMIOS + if (pipe->ttyvalid) { + if (Tcsetattr(pipe->fd1, 0, &pipe->savetty) < 0) { + Warn2("cannot restore terminal settings on fd %d: %s", + pipe->fd1, strerror(errno)); + } + } +#endif /* WITH_TERMIOS */ + /* unlock */ if (pipe->havelock) { xiounlock(pipe->lock.lockfile); diff --git a/xioconfig.h b/xioconfig.h index 82fca6a..2007067 100644 --- a/xioconfig.h +++ b/xioconfig.h @@ -1,5 +1,5 @@ /* source: xioconfig.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xioconfig_h_included @@ -20,6 +20,10 @@ # define WITH_NAMED 1 #endif +#if WITH_TERMIOS || WITH_PTY || WITH_READLINE +# define _WITH_TERMIOS 1 +#endif + #if WITH_SOCKS4A # define _WITH_SOCKS4 1 #endif @@ -54,7 +58,7 @@ # define _WITH_UNIX 1 #endif -#if WITH_IP4 || WITH_IP6 || WITH_SOCKS4 || WITH_RAWIP || _WITH_UNIX +#if _WITH_UNIX || WITH_IP4 || WITH_IP6 || WITH_SOCKS4 || WITH_RAWIP || WITH_GENERICSOCKET # define WITH_SOCKET 1 #else # undef WITH_SOCKET @@ -68,7 +72,7 @@ # undef WITH_LIBWRAP #endif -#if WITH_SOCKET || WITH_TUN +#if WITH_GENERICSOCKET || WITH_TUN # define _WITH_SOCKET 1 #endif @@ -131,4 +135,8 @@ typedef unsigned int uint32_t; #endif +#ifndef HAVE_TYPE_SA_FAMILY_T + typedef uint16_t sa_family_t; +#endif + #endif /* !defined(__xioconfig_h_included) */ diff --git a/xioengine.c b/xioengine.c index 92728aa..83c9f48 100644 --- a/xioengine.c +++ b/xioengine.c @@ -1,5 +1,5 @@ -/* $Id$ */ -/* Copyright Gerhard Rieger 2007 */ +/* source: xioengine.c */ +/* Copyright Gerhard Rieger 2007-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this is the source file of the socat transfer loop/engine */ @@ -17,8 +17,9 @@ returns >0 if child died and left data */ int childleftdata(xiofile_t *xfd) { - fd_set in, out, expt; + struct pollfd in; 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 || @@ -26,35 +27,29 @@ int childleftdata(xiofile_t *xfd) { 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 }; + struct timeval timeout = { 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);*/ + in.fd = XIO_GETRDFD(xfd); + in.events = POLLIN/*|POLLRDBAND*/; + in.revents = 0; } do { - retval = Select(FD_SETSIZE, &in, &out, &expt, &time0); + retval = xiopoll(&in, 1, &timeout); } 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);*/ + Error5("xiopoll({%d,%0o}, 1, {"F_tv_sec"."F_tv_usec"}): %s", + in.fd, in.events, timeout.tv_sec, timeout.tv_usec, + strerror(errno)); + return -1; + } + if (retval == 0) { + Info("terminated child did not leave data for us"); + XIO_RDSTREAM(xfd)->eof = 2; + xfd->stream.eof = 2; + xfd->stream.closing = MAX(xfd->stream.closing, 1); } - return 1; } return 0; } @@ -72,7 +67,11 @@ void *xioengine(void *thread_arg) { 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; + struct pollfd fds[4], + *fd1in = &fds[0], + *fd1out = &fds[1], + *fd2in = &fds[2], + *fd2out = &fds[3]; int retval; unsigned char *buff; ssize_t bytes1, bytes2; @@ -134,19 +133,17 @@ int _socat(xiofile_t *xfd1, xiofile_t *xfd2) { 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", + Debug4("data loop: sock1->eof=%d, sock2->eof=%d, 1->closing=%d, 2->closing=%d, wasaction=%d, total_to={"F_tv_sec"."F_tv_usec"}", 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); + Debug6("wasaction=%d, total_to={"F_tv_sec"."F_tv_usec"}", + wasaction, total_timeout.tv_sec, total_timeout.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) { @@ -185,12 +182,13 @@ int _socat(xiofile_t *xfd1, xiofile_t *xfd2) { /* first eof already occurred, start end timer */ timeout = xioparams->closwait; to = &timeout; + /*0 closing = 2;*/ } #endif + /* frame 1: set the poll parameters and loop over poll() EINTR) */ do { int _errno; - FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt); childleftdata(sock1); childleftdata(sock2); @@ -216,35 +214,66 @@ int _socat(xiofile_t *xfd1, xiofile_t *xfd2) { } #endif + /* use the ignoreeof timeout if appropriate */ + if (polling) { + if ((sock1->stream.closing == 0 && sock2->stream.closing == 0) || + (xioparams->pollintv.tv_sec < timeout.tv_sec) || + ((xioparams->pollintv.tv_sec == timeout.tv_sec) && + xioparams->pollintv.tv_usec < timeout.tv_usec)) { + timeout = xioparams->pollintv; + } + } + + /* now the fds will be assigned */ 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 (!mayrd1 && !(XIO_RDSTREAM(sock1)->eof > 1)) { + fd1in->fd = XIO_GETRDFD(sock1); + fd1in->events = POLLIN; + } else { + fd1in->fd = -1; } if (!maywr2) { - FD_SET(XIO_GETWRFD(sock2), &out); + fd2out->fd = XIO_GETWRFD(sock2); + fd2out->events = POLLOUT; + } else { + fd2out->fd = -1; } - } + } else { + fd1in->fd = -1; + fd2out->fd = -1; + } 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 (!mayrd2 && !(XIO_RDSTREAM(sock2)->eof > 1)) { + fd2in->fd = XIO_GETRDFD(sock2); + fd2in->events = POLLIN; + } else { + fd2in->fd = -1; } if (!maywr1) { - FD_SET(XIO_GETWRFD(sock1), &out); + fd1out->fd = XIO_GETWRFD(sock1); + fd1out->events = POLLOUT; + } else { + fd1out->fd = -1; } + } else { + fd1out->fd = -1; + fd2in->fd = -1; + } + /* frame 0: innermost part of the transfer loop: check FD status */ + retval = xiopoll(fds, 4, to); + if (retval >= 0 || errno != EINTR) { + break; } - retval = Select(FD_SETSIZE, &in, &out, &expt, to); _errno = errno; - if (retval < 0 && errno == EINTR) { - Info1("select(): %s", strerror(errno)); - } + Info1("xiopoll(): %s", strerror(errno)); errno = _errno; - } while (retval < 0 && errno == EINTR); + } while (true); /* attention: when an exec'd process sends data and terminates, it is unpredictable @@ -252,27 +281,26 @@ int _socat(xiofile_t *xfd1, xiofile_t *xfd2) { */ 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 + Error11("xiopoll({%d,%0o}{%d,%0o}{%d,%0o}{%d,%0o}, 4, {"F_tv_sec"."F_tv_usec"}): %s", + fds[0].fd, fds[0].events, fds[1].fd, fds[1].events, + fds[2].fd, fds[2].events, fds[3].fd, fds[3].events, + timeout.tv_sec, timeout.tv_usec, strerror(errno)); return -1; } else if (retval == 0) { - Info2("select timed out (no data within %ld.%06ld seconds)", + Info2("poll 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 */ - ; + polling = 0; /*%%%*/ + if (XIO_RDSTREAM(sock1)->ignoreeof) { + mayrd1 = 0; + } + } else if (polling && wasaction) { + wasaction = 0; + } else if (xioparams->total_timeout.tv_sec != 0 || xioparams->total_timeout.tv_usec != 0) { /* there was a total inactivity timeout */ @@ -291,21 +319,40 @@ int _socat(xiofile_t *xfd1, xiofile_t *xfd2) { /*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; + (fd1in->revents /*&(POLLIN|POLLHUP|POLLERR)*/)) { + if (fd1in->revents & POLLNVAL) { + /* this is what we find on Mac OS X when poll()'ing on a device or + named pipe. a read() might imm. return with 0 bytes, resulting + in a loop? */ + Error1("poll(...[%d]: invalid request", fd1in->fd); + return -1; + } + 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)) { + (fd2in->revents)) { + if (fd2in->revents & POLLNVAL) { + Error1("poll(...[%d]: invalid request", fd2in->fd); + return -1; + } mayrd2 = true; } /*0 Debug2("mayrd2 = %d, maywr1 = %d", mayrd2, maywr1);*/ - if (XIO_GETWRFD(sock1) >= 0 && FD_ISSET(XIO_GETWRFD(sock1), &out)) { + if (XIO_GETWRFD(sock1) >= 0 && fd1out->fd >= 0 && fd1out->revents) { + if (fd1out->revents & POLLNVAL) { + Error1("poll(...[%d]: invalid request", fd1out->fd); + return -1; + } maywr1 = true; } - if (XIO_GETWRFD(sock2) >= 0 && FD_ISSET(XIO_GETWRFD(sock2), &out)) { + if (XIO_GETWRFD(sock2) >= 0 && fd2out->fd >= 0 && fd2out->revents) { + if (fd2out->revents & POLLNVAL) { + Error1("poll(...[%d]: invalid request", fd2out->fd); + return -1; + } maywr2 = true; } @@ -331,7 +378,12 @@ int _socat(xiofile_t *xfd1, xiofile_t *xfd2) { /* avoid idle when all readbytes already there */ mayrd1 = true; } - } else { /* bytes1 == 0 */ + /* escape char occurred? */ + if (XIO_RDSTREAM(sock1)->actescape) { + bytes1 = 0; /* indicate EOF */ + } + } + if (bytes1 == 0) { if (XIO_RDSTREAM(sock1)->ignoreeof && !sock1->stream.closing) { ; } else { @@ -365,7 +417,12 @@ int _socat(xiofile_t *xfd1, xiofile_t *xfd2) { /* avoid idle when all readbytes already there */ mayrd2 = true; } - } else { /* bytes == 0 */ + /* escape char occurred? */ + if (XIO_RDSTREAM(sock2)->actescape) { + bytes2 = 0; /* indicate EOF */ + } + } + if (bytes2 == 0) { if (XIO_RDSTREAM(sock2)->ignoreeof && !sock2->stream.closing) { ; } else { @@ -380,33 +437,45 @@ int _socat(xiofile_t *xfd1, xiofile_t *xfd2) { /* NOW handle EOFs */ if (bytes1 == 0 || XIO_RDSTREAM(sock1)->eof >= 2) { - if (XIO_RDSTREAM(sock1)->ignoreeof && !sock1->stream.closing) { + if (XIO_RDSTREAM(sock1)->ignoreeof && + !XIO_RDSTREAM(sock1)->actescape && !sock1->stream.closing) { Debug1("socket 1 (fd %d) is at EOF, ignoring", XIO_RDSTREAM(sock1)->fd1); /*! */ - polling = 1; + mayrd1 = true; + polling = 1; /* do not hook this eof fd to poll for pollintv*/ } else { Notice1("socket 1 (fd %d) is at EOF", XIO_GETRDFD(sock1)); xioshutdown(sock2, SHUT_WR); + XIO_RDSTREAM(sock1)->eof = 2; + XIO_RDSTREAM(sock1)->ignoreeof = false; sock2->stream.closing = MAX(sock2->stream.closing, 1); if (/*0 xioparams->lefttoright*/ !XIO_READABLE(sock2)) { break; } } + } else if (polling && XIO_RDSTREAM(sock1)->ignoreeof) { + polling = 0; } if (bytes2 == 0 || XIO_RDSTREAM(sock2)->eof >= 2) { - if (XIO_RDSTREAM(sock2)->ignoreeof && !sock2->stream.closing) { + if (XIO_RDSTREAM(sock2)->ignoreeof && + !XIO_RDSTREAM(sock2)->actescape && !sock2->stream.closing) { Debug1("socket 2 (fd %d) is at EOF, ignoring", XIO_RDSTREAM(sock2)->fd1); - polling = 1; + mayrd2 = true; + polling = 1; /* do not hook this eof fd to poll for pollintv*/ } else { Notice1("socket 2 (fd %d) is at EOF", XIO_GETRDFD(sock2)); xioshutdown(sock1, SHUT_WR); + XIO_RDSTREAM(sock2)->eof = 2; + XIO_RDSTREAM(sock2)->ignoreeof = false; sock1->stream.closing = MAX(sock1->stream.closing, 1); if (/*0 xioparams->righttoleft*/ !XIO_READABLE(sock1)) { break; } } + } else if (polling && XIO_RDSTREAM(sock2)->ignoreeof) { + polling = 0; } } diff --git a/xiohelp.c b/xiohelp.c index 1e7fb20..27b29d7 100644 --- a/xiohelp.c +++ b/xiohelp.c @@ -29,19 +29,21 @@ static const char *optiontypenames[] = { "STRUCT-IP_MREQ", #endif "IP4NAME", + "INT:INT", "INT:INTP", "INT:BIN", "INT:STRING", + "INT:INT:INT", "INT:INT:BIN", "INT:INT:STRING", } ; /* keep consistent with xioopts.h:#define GROUP_* ! */ static const char *addressgroupnames[] = { - "FD", "FIFO", "CHR", "BLK", + "FD", "FIFO", "SOCKS5", "BLK", "REG", "SOCKET", "READLINE", "undef", "NAMED", "OPEN", "EXEC", "FORK", "LISTEN", "DEVICE", "CHILD", "RETRY", "TERMIOS", "RANGE", "PTY", "PARENT", "UNIX", "IP4", "IP6", "INTERFACE", "UDP", "TCP", "SOCKS4", "OPENSSL", - "PROCESS", "APPL", "HTTP", "SOCKS5" + "PROCESS", "APPL", "HTTP", "SCTP" } ; diff --git a/xioinitialize.c b/xioinitialize.c index 69df965..0ab09c3 100644 --- a/xioinitialize.c +++ b/xioinitialize.c @@ -43,13 +43,15 @@ int xioinitialize(int xioflags) { /* some assertions about termios */ #if WITH_TERMIOS -#ifdef CRDLY +#if defined(CRDLY) && CRDLY_SHIFT >= 0 assert(3 << opt_crdly.arg3 == CRDLY); #endif -#ifdef TABDLY +#if defined(TABDLY) && TABDLY_SHIFT >= 0 assert(3 << opt_tabdly.arg3 == TABDLY); #endif +#if CSIZE_SHIFT >= 0 assert(3 << opt_csize.arg3 == CSIZE); +#endif { union { struct termios termarg; @@ -139,6 +141,14 @@ int xioinitialize(int xioflags) { return 0; } +/* call this function when option -lp (reset program name) has been applied */ +int xioinitialize2(void) { + pid_t pid = Getpid(); + xiosetenvulong("PID", pid, 1); + xiosetenvulong("PPID", pid, 1); + return 0; +} + /* well, this function is not for initialization, but I could not find a better source file for it @@ -196,6 +206,7 @@ static int xio_nokill(xiofile_t *sock) { returns 0 on success or != 0 if an error occurred */ int xio_forked_inchild(void) { int result = 0; + xiodroplocks(); #if WITH_FIPS if (xio_reset_fips_mode() != 0) { @@ -221,3 +232,45 @@ int xio_forked_inchild(void) { return result; } + +/* subchild != 0 means that the current process is already a child process of + the master process and thus the new sub child process should not set the + SOCAT_PID variable */ +pid_t xio_fork(bool subchild, int level) { + pid_t pid; + const char *forkwaitstring; + int forkwaitsecs = 0; + + if ((pid = Fork()) < 0) { + Msg1(level, "fork(): %s", strerror(errno)); + return pid; + } + + if (pid == 0) { /* child process */ + pid_t cpid = Getpid(); + + Info1("just born: client process "F_pid, cpid); + if (!subchild) { + /* set SOCAT_PID to new value */ + xiosetenvulong("PID", pid, 1); + } + /* gdb recommends to have env controlled sleep after fork */ + if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) { + forkwaitsecs = atoi(forkwaitstring); + Sleep(forkwaitsecs); + } + if (xio_forked_inchild() != 0) { + Exit(1); + } + return 0; + } + + /* parent process */ + Notice1("forked off child process "F_pid, pid); + /* gdb recommends to have env controlled sleep after fork */ + if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) { + forkwaitsecs = atoi(forkwaitstring); + Sleep(forkwaitsecs); + } + return pid; +} diff --git a/xiolayer.c b/xiolayer.c index e8ce025..65a80f1 100644 --- a/xiolayer.c +++ b/xiolayer.c @@ -16,6 +16,7 @@ const struct optdesc opt_crnl = { "crnl", NULL, OPT_CRNL, GROUP_A const struct optdesc opt_readbytes = { "readbytes", "bytes", OPT_READBYTES, GROUP_APPL, PH_LATE, TYPE_SIZE_T, OFUNC_EXT, (int)(&((struct single *)0)->readbytes), sizeof(((struct single *)0)->readbytes) }; const struct optdesc opt_lockfile = { "lockfile", NULL, OPT_LOCKFILE, 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 }; +const struct optdesc opt_escape = { "escape", NULL, OPT_ESCAPE, GROUP_APPL, PH_INIT, TYPE_INT, OFUNC_OFFSET, XIO_OFFSETOF(escape), sizeof(((xiosingle_t *)0)->escape) }; /****** APPL addresses ******/ #if WITH_RETRY 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) }; diff --git a/xiolayer.h b/xiolayer.h index 926dede..4ec2c5e 100644 --- a/xiolayer.h +++ b/xiolayer.h @@ -1,5 +1,5 @@ /* source: xiolayer.h */ -/* Copyright Gerhard Rieger 2001-2005 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xiolayer_h_included @@ -11,6 +11,7 @@ extern const struct optdesc opt_crnl; extern const struct optdesc opt_readbytes; extern const struct optdesc opt_lockfile; extern const struct optdesc opt_waitlock; +extern const struct optdesc opt_escape; extern const struct optdesc opt_forever; extern const struct optdesc opt_intervall; extern const struct optdesc opt_retry; diff --git a/xiomodes.h b/xiomodes.h index 36716da..72383c3 100644 --- a/xiomodes.h +++ b/xiomodes.h @@ -1,5 +1,5 @@ /* source: xiomodes.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xiomodes_h_included @@ -15,11 +15,12 @@ #include "xio-creat.h" #include "xio-gopen.h" #include "xio-pipe.h" -#if WITH_SOCKET +#if _WITH_SOCKET #include "xio-socket.h" #include "xio-listen.h" #include "xio-unix.h" #include "xio-rawip.h" +#include "xio-interface.h" #include "xio-ip.h" #if WITH_IP4 #include "xio-ip4.h" @@ -28,10 +29,11 @@ #include "xio-ipapp.h" #include "xio-tcp.h" #include "xio-udp.h" +#include "xio-sctp.h" #include "xio-socks.h" #include "xio-socks5.h" #include "xio-proxy.h" -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ #include "xio-progcall.h" #include "xio-exec.h" #include "xio-system.h" @@ -42,6 +44,7 @@ #include "xio-tcpwrap.h" #include "xio-ext2.h" #include "xio-tun.h" +#include "xio-streams.h" #include "xio-nop.h" #include "xio-test.h" diff --git a/xioopen.c b/xioopen.c index 837b84d..ba78614 100644 --- a/xioopen.c +++ b/xioopen.c @@ -1,5 +1,5 @@ /* source: xioopen.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this is the source file of the extended open function */ @@ -55,6 +55,10 @@ const struct xioaddrname address_names[] = { { "creat", xioaddrs_creat }, { "create", xioaddrs_creat }, #endif +#if WITH_GENERICSOCKET + { "datagram", xioaddrs_socket_datagram }, + { "dgram", xioaddrs_socket_datagram }, +#endif #if WITH_PIPE { "echo", xioaddrs_pipe }, #endif @@ -73,6 +77,9 @@ const struct xioaddrname address_names[] = { #if WITH_GOPEN { "gopen", xioaddrs_gopen }, #endif +#if WITH_INTERFACE + { "if", xioaddrs_interface }, +#endif #if (WITH_IP4 || WITH_IP6) && WITH_TCP { "inet", xioaddrs_tcp_connect }, #endif @@ -94,6 +101,9 @@ const struct xioaddrname address_names[] = { { "inet6-l", xioaddrs_tcp6_listen }, { "inet6-listen", xioaddrs_tcp6_listen }, #endif +#if WITH_INTERFACE + { "interface", xioaddrs_interface }, +#endif #if WITH_RAWIP #if (WITH_IP4 || WITH_IP6) { "ip", xioaddrs_rawip_sendto }, @@ -154,6 +164,43 @@ const struct xioaddrname address_names[] = { #if WITH_READLINE { "readline", xioaddrs_readline }, #endif +#if (WITH_IP4 || WITH_IP6) && WITH_SCTP + { "sctp", xioaddrs_sctp_connect }, + { "sctp-connect", xioaddrs_sctp_connect }, +#if WITH_LISTEN + { "sctp-l", xioaddrs_sctp_listen }, + { "sctp-listen", xioaddrs_sctp_listen }, +#endif +#if WITH_IP4 + { "sctp4", xioaddrs_sctp4_connect }, + { "sctp4-connect", xioaddrs_sctp4_connect }, +#if WITH_LISTEN + { "sctp4-l", xioaddrs_sctp4_listen }, + { "sctp4-listen", xioaddrs_sctp4_listen }, +#endif +#endif /* WITH_IP4 */ +#if WITH_IP6 + { "sctp6", xioaddrs_sctp6_connect }, + { "sctp6-connect", xioaddrs_sctp6_connect }, +#if WITH_LISTEN + { "sctp6-l", xioaddrs_sctp6_listen }, + { "sctp6-listen", xioaddrs_sctp6_listen }, +#endif +#endif /* WITH_IP6 */ +#endif /* (WITH_IP4 || WITH_IP6) && WITH_SCTP */ +#if WITH_GENERICSOCKET + { "sendto", xioaddrs_socket_sendto }, +#endif +#if WITH_GENERICSOCKET + { "socket-connect", xioaddrs_socket_connect }, + { "socket-datagram", xioaddrs_socket_datagram }, +#if WITH_LISTEN + { "socket-listen", xioaddrs_socket_listen }, +#endif /* WITH_LISTEN */ + { "socket-recv", xioaddrs_socket_recv }, + { "socket-recvfrom", xioaddrs_socket_recvfrom }, + { "socket-sendto", xioaddrs_socket_sendto }, +#endif #if WITH_SOCKS4 { "socks", xioaddrs_socks4_connect }, { "socks-client", xioaddrs_socks4_connect }, @@ -333,12 +380,13 @@ xiofile_t *xioallocfd(void) { fd->stream.fd2 = -1; fd->stream.fdtype = FDTYPE_SINGLE; fd->stream.dtype = XIODATA_STREAM; -#if WITH_SOCKET +#if _WITH_SOCKET /* fd->stream.salen = 0; */ -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ /* fd->stream.howtoshut = XIOSHUT_UNSPEC;*/ /* fd->stream.howtoclose = XIOCLOSE_UNSPEC;*/ /* fd->stream.name = NULL; */ + fd->stream.escape = -1; /* fd->stream.para.exec.pid = 0; */ fd->stream.lineterm = LINETERM_RAW; diff --git a/xioopen.h b/xioopen.h index 5c93d12..8984ebc 100644 --- a/xioopen.h +++ b/xioopen.h @@ -1,5 +1,5 @@ /* source: xioopen.h */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xioopen_h_included diff --git a/xioopts.c b/xioopts.c index 530af72..2497875 100644 --- a/xioopts.c +++ b/xioopts.c @@ -40,7 +40,7 @@ bool xioopts_ignoregroups; # define IF_EXEC(a,b) #endif -#if WITH_SOCKET +#if _WITH_SOCKET # define IF_SOCKET(a,b) {a,b}, #else # define IF_SOCKET(a,b) @@ -82,6 +82,12 @@ bool xioopts_ignoregroups; # define IF_TCP(a,b) #endif +#if WITH_SCTP +# define IF_SCTP(a,b) {a,b}, +#else +# define IF_SCTP(a,b) +#endif + #if WITH_SOCKS4 # define IF_SOCKS4(a,b) {a,b}, #else @@ -171,6 +177,9 @@ const struct optname optionnames[] = { #ifdef SO_AUDIT /* AIX 4.3.3 */ IF_SOCKET ("audit", &opt_so_audit) #endif /* SO_AUDIT */ +#ifdef IPV6_AUTHHDR + IF_IP6 ("authhdr", &opt_ipv6_authhdr) +#endif IF_TUN ("automedia", &opt_iff_automedia) #ifdef CBAUD IF_TERMIOS("b0", &opt_b0) @@ -313,7 +322,9 @@ const struct optname optionnames[] = { # ifdef CR3 IF_TERMIOS("cr3", &opt_cr3) # endif +# if CRDLY_SHIFT >= 0 IF_TERMIOS("crdly", &opt_crdly) +# endif #endif /* defined(CRDLY) */ IF_TERMIOS("cread", &opt_cread) IF_OPEN ("creat", &opt_o_create) @@ -329,7 +340,9 @@ const struct optname optionnames[] = { IF_TERMIOS("cs6", &opt_cs6) IF_TERMIOS("cs7", &opt_cs7) IF_TERMIOS("cs8", &opt_cs8) +#if CSIZE_SHIFT >= 0 IF_TERMIOS("csize", &opt_csize) +#endif IF_TERMIOS("cstopb", &opt_cstopb) IF_TERMIOS("ctlecho", &opt_echoctl) IF_TERMIOS("ctty", &opt_tiocsctty) @@ -381,6 +394,7 @@ const struct optname optionnames[] = { IF_SOCKET ("dontlinger", &opt_so_dontlinger) #endif IF_SOCKET ("dontroute", &opt_so_dontroute) + IF_IP6 ("dstopts", &opt_ipv6_dstopts) #ifdef VDSUSP /* HP-UX */ IF_TERMIOS("dsusp", &opt_vdsusp) #endif @@ -403,6 +417,7 @@ const struct optname optionnames[] = { IF_TERMIOS("eol2", &opt_veol2) IF_TERMIOS("erase", &opt_verase) IF_SOCKET ("error", &opt_so_error) + IF_ANY ("escape", &opt_escape) IF_OPEN ("excl", &opt_o_excl) #if WITH_EXT2 && defined(EXT2_APPEND_FL) IF_ANY ("ext2-append", &opt_ext2_append) @@ -506,6 +521,9 @@ const struct optname optionnames[] = { IF_ANY ("flock-nb", &opt_flock_ex_nb) IF_ANY ("flock-sh", &opt_flock_sh) IF_ANY ("flock-sh-nb", &opt_flock_sh_nb) +#endif +#ifdef IPV4_FLOWINFO + IF_IP6 ("flowinfo", &opt_ipv6_flowinfo) #endif IF_TERMIOS("flusho", &opt_flusho) IF_RETRY ("forever", &opt_forever) @@ -533,6 +551,8 @@ const struct optname optionnames[] = { #endif IF_READLINE("history", &opt_history_file) IF_READLINE("history-file", &opt_history_file) + IF_IP6 ("hoplimit", &opt_ipv6_hoplimit) + IF_IP6 ("hopopts", &opt_ipv6_hopopts) #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE) IF_IPAPP ("hosts-allow", &opt_tcpwrap_hosts_allow_table) #endif @@ -541,6 +561,12 @@ const struct optname optionnames[] = { #endif IF_TERMIOS("hup", &opt_hupcl) IF_TERMIOS("hupcl", &opt_hupcl) +#ifdef I_POP + IF_ANY ("i-pop-all", &opt_streams_i_pop_all) +#endif +#ifdef I_PUSH + IF_ANY ("i-push", &opt_streams_i_push) +#endif IF_TERMIOS("icanon", &opt_icanon) IF_TERMIOS("icrnl", &opt_icrnl) IF_TERMIOS("iexten", &opt_iexten) @@ -589,6 +615,12 @@ const struct optname optionnames[] = { IF_RETRY ("interval", &opt_intervall) IF_RETRY ("intervall", &opt_intervall) IF_TERMIOS("intr", &opt_vintr) + IF_ANY ("ioctl", &opt_ioctl_void) + IF_ANY ("ioctl-bin", &opt_ioctl_bin) + IF_ANY ("ioctl-int", &opt_ioctl_int) + IF_ANY ("ioctl-intp", &opt_ioctl_intp) + IF_ANY ("ioctl-string", &opt_ioctl_string) + IF_ANY ("ioctl-void", &opt_ioctl_void) #ifdef IP_ADD_MEMBERSHIP IF_IP ("ip-add-membership", &opt_ip_add_membership) #endif @@ -619,9 +651,15 @@ const struct optname optionnames[] = { #ifdef IP_PKTOPTIONS IF_IP ("ip-pktoptions", &opt_ip_pktoptions) #endif +#ifdef IP_RECVDSTADDR + IF_IP ("ip-recvdstaddr", &opt_ip_recvdstaddr) +#endif #ifdef IP_RECVERR IF_IP ("ip-recverr", &opt_ip_recverr) #endif +#ifdef IP_RECVIF + IF_IP ("ip-recvif", &opt_ip_recvif) +#endif #ifdef IP_RECVOPTS IF_IP ("ip-recvopts", &opt_ip_recvopts) #endif @@ -662,6 +700,9 @@ const struct optname optionnames[] = { #ifdef IP_PKTOPTIONS IF_IP ("ippktoptions", &opt_ip_pktoptions) #endif +#ifdef IP_RECVDSTADDR + IF_IP ("iprecvdstaddr", &opt_ip_recvdstaddr) +#endif #ifdef IP_RECVERR IF_IP ("iprecverr", &opt_ip_recverr) #endif @@ -683,7 +724,46 @@ const struct optname optionnames[] = { IF_IP ("iptos", &opt_ip_tos) IF_IP ("ipttl", &opt_ip_ttl) IF_IP6 ("ipv6-add-membership", &opt_ipv6_join_group) +#ifdef IPV6_AUTHHDR + IF_IP6 ("ipv6-authhdr", &opt_ipv6_authhdr) +#endif + IF_IP6 ("ipv6-dstopts", &opt_ipv6_dstopts) +#ifdef IPV4_FLOWINFO + IF_IP6 ("ipv6-flowinfo", &opt_ipv6_flowinfo) +#endif + IF_IP6 ("ipv6-hoplimit", &opt_ipv6_hoplimit) + IF_IP6 ("ipv6-hopopts", &opt_ipv6_hopopts) IF_IP6 ("ipv6-join-group", &opt_ipv6_join_group) + IF_IP6 ("ipv6-pktinfo", &opt_ipv6_pktinfo) +#ifdef IPV6_RECVDSTOPTS + IF_IP6 ("ipv6-recvdstopts", &opt_ipv6_recvdstopts) +#endif +#ifdef IPV6_RECVERR + IF_IP6 ("ipv6-recverr", &opt_ipv6_recverr) +#endif +#ifdef IPV6_RECVHOPLIMIT + IF_IP6 ("ipv6-recvhoplimit", &opt_ipv6_recvhoplimit) +#endif +#ifdef IPV6_RECVHOPOPTS + IF_IP6 ("ipv6-recvhopopts", &opt_ipv6_recvhopopts) +#endif +#ifdef IPV6_PATHMTU + IF_IP6 ("ipv6-recvpathmtu", &opt_ipv6_recvpathmtu) +#endif +#ifdef IPV6_RECVPKTINFO + IF_IP6 ("ipv6-recvpktinfo", &opt_ipv6_recvpktinfo) +#endif +#ifdef IPV6_RECVRTHDR + IF_IP6 ("ipv6-recvrthdr", &opt_ipv6_recvrthdr) +#endif +#ifdef IPV6_RECVTCLASS + IF_IP6 ("ipv6-recvtclass", &opt_ipv6_recvtclass) +#endif + IF_IP6 ("ipv6-rthdr", &opt_ipv6_rthdr) +#ifdef IPV6_TCLASS + IF_IP6 ("ipv6-tclass", &opt_ipv6_tclass) +#endif + IF_IP6 ("ipv6-unicast-hops", &opt_ipv6_unicast_hops) #ifdef IPV6_V6ONLY IF_IP6 ("ipv6-v6only", &opt_ipv6_v6only) IF_IP6 ("ipv6only", &opt_ipv6_v6only) @@ -917,53 +997,6 @@ const struct optname optionnames[] = { #endif IF_OPEN ("o-trunc", &opt_o_trunc) IF_OPEN ("o-wronly", &opt_o_wronly) - IF_OPEN ("o_create", &opt_o_create) -#ifdef O_DEFER - IF_OPEN ("o_defer", &opt_o_defer) -#endif -#ifdef O_DELAY - IF_OPEN ("o_delay", &opt_o_delay) -#endif -#ifdef O_DIRECT - IF_OPEN ("o_direct", &opt_o_direct) -#endif -#ifdef O_DIRECTORY - IF_OPEN ("o_directory", &opt_o_directory) -#endif -#ifdef O_DSYNC - IF_OPEN ("o_dsync", &opt_o_dsync) -#endif - IF_OPEN ("o_excl", &opt_o_excl) -#ifdef O_LARGEFILE - IF_OPEN ("o_largefile", &opt_o_largefile) -#endif -#if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK) - IF_ANY ("o_ndelay", &opt_o_ndelay) -#else - IF_ANY ("o_ndelay", &opt_nonblock) -#endif - IF_OPEN ("o_noctty", &opt_o_noctty) -#ifdef O_NOFOLLOW - IF_OPEN ("o_nofollow", &opt_o_nofollow) -#endif -#ifdef O_NSHARE - IF_OPEN ("o_nshare", &opt_o_nshare) -#endif -#ifdef O_PRIV - IF_OPEN ("o_priv", &opt_o_priv) -#endif - IF_OPEN ("o_rdonly", &opt_o_rdonly) - IF_OPEN ("o_rdwr", &opt_o_rdwr) -#ifdef O_RSHARE - IF_OPEN ("o_rshare", &opt_o_rshare) -#endif -#ifdef O_RSYNC - IF_OPEN ("o_rsync", &opt_o_rsync) -#endif -#ifdef O_SYNC - IF_OPEN ("o_sync", &opt_o_sync) -#endif - IF_OPEN ("o_wronly", &opt_o_wronly) #ifdef OCRNL IF_TERMIOS("ocrnl", &opt_ocrnl) #endif @@ -1035,6 +1068,9 @@ const struct optname optionnames[] = { IF_IP ("pktopts", &opt_ip_pktoptions) #endif IF_TUN ("pointopoint", &opt_iff_pointopoint) +#ifdef I_POP + IF_ANY ("pop-all", &opt_streams_i_pop_all) +#endif /*IF_IPAPP("port", &opt_port)*/ IF_TUN ("portsel", &opt_iff_portsel) #if HAVE_RESOLV_H @@ -1048,12 +1084,15 @@ const struct optname optionnames[] = { #endif IF_TUN ("promisc", &opt_iff_promisc) IF_READLINE("prompt", &opt_prompt) +#ifdef SO_PROTOTYPE + IF_SOCKET ("protocol", &opt_so_prototype) +#endif IF_SOCKET ("protocol-family", &opt_protocol_family) #ifdef SO_PROTOTYPE IF_SOCKET ("prototype", &opt_so_prototype) #endif - IF_PROXY ("proxy-authorization", &opt_proxy_authorization) IF_PROXY ("proxy-auth", &opt_proxy_authorization) + IF_PROXY ("proxy-authorization", &opt_proxy_authorization) IF_PROXY ("proxy-resolve", &opt_proxy_resolve) IF_PROXY ("proxyauth", &opt_proxy_authorization) IF_PROXY ("proxyport", &opt_proxyport) @@ -1072,6 +1111,9 @@ const struct optname optionnames[] = { IF_PTY ("pty-intervall", &opt_pty_intervall) IF_PTY ("pty-wait-slave", &opt_pty_wait_slave) #endif /* HAVE_PTY && HAVE_POLL */ +#ifdef I_PUSH + IF_ANY ("push", &opt_streams_i_push) +#endif #ifdef TCP_QUICKACK IF_TCP ("quickack", &opt_tcp_quickack) #endif @@ -1092,12 +1134,33 @@ const struct optname optionnames[] = { #if HAVE_RESOLV_H IF_IP ("recurse", &opt_res_recurse) #endif /* HAVE_RESOLV_H */ +#ifdef IP_RECVDSTADDR + IF_IP ("recvdstaddr", &opt_ip_recvdstaddr) +#endif +#ifdef IPV6_RECVDSTOPTS + IF_IP6 ("recvdstopts", &opt_ipv6_recvdstopts) +#endif #ifdef IP_RECVERR IF_IP ("recverr", &opt_ip_recverr) #endif +#ifdef IPV6_RECVHOPLIMIT + IF_IP6 ("recvhoplimit", &opt_ipv6_recvhoplimit) +#endif +#ifdef IPV6_RECVHOPOPTS + IF_IP6 ("recvhopopts", &opt_ipv6_recvhopopts) +#endif +#ifdef IP_RECVIF + IF_IP ("recvif", &opt_ip_recvif) +#endif #ifdef IP_RECVOPTS IF_IP ("recvopts", &opt_ip_recvopts) #endif +#ifdef IPV6_RECVPKTINFO + IF_IP6 ("recvpktinfo", &opt_ipv6_recvpktinfo) +#endif +#ifdef IPV6_RECVRTHDR + IF_IP6 ("recvrthdr", &opt_ipv6_recvrthdr) +#endif #ifdef IP_RECVTOS IF_IP ("recvtos", &opt_ip_recvtos) #endif @@ -1144,6 +1207,7 @@ const struct optname optionnames[] = { #ifdef O_RSYNC IF_OPEN ("rsync", &opt_o_rsync) #endif + IF_IP6 ("rthdr", &opt_ipv6_rthdr) IF_TUN ("running", &opt_iff_running) #ifdef TCP_SACK_DISABLE IF_TCP ("sack-disable", &opt_tcp_sack_disable) @@ -1152,6 +1216,13 @@ const struct optname optionnames[] = { IF_TCP ("sackena", &opt_tcp_sackena) #endif IF_TERMIOS("sane", &opt_sane) +#ifdef SCTP_MAXSEG + IF_SCTP ("sctp-maxseg", &opt_sctp_maxseg) + IF_SCTP ("sctp-maxseg-late", &opt_sctp_maxseg_late) +#endif +#ifdef SCTP_NODELAY + IF_SCTP ("sctp-nodelay", &opt_sctp_nodelay) +#endif #if WITH_EXT2 && defined(EXT2_SECRM_FL) IF_ANY ("secrm", &opt_ext2_secrm) #endif @@ -1196,6 +1267,9 @@ const struct optname optionnames[] = { #if WITH_EXEC || WITH_SYSTEM IF_EXEC ("setsid", &opt_setsid) #endif + IF_SOCKET ("setsockopt-bin", &opt_setsockopt_bin) + IF_SOCKET ("setsockopt-int", &opt_setsockopt_int) + IF_SOCKET ("setsockopt-string", &opt_setsockopt_string) IF_ANY ("setuid", &opt_setuid) IF_ANY ("setuid-early", &opt_setuid_early) IF_ANY ("shut-none", &opt_shut_none) @@ -1303,6 +1377,9 @@ const struct optname optionnames[] = { #endif #ifdef SO_SNDTIMEO IF_SOCKET ("so-sndtimeo", &opt_so_sndtimeo) +#endif +#ifdef SO_TIMESTAMP + IF_SOCKET ("so-timestamp", &opt_so_timestamp) #endif IF_SOCKET ("so-type", &opt_so_type) #ifdef SO_USE_IFBUFS @@ -1311,10 +1388,14 @@ const struct optname optionnames[] = { #ifdef SO_USELOOPBACK /* AIX433, Solaris */ IF_SOCKET ("so-useloopback", &opt_so_useloopback) #endif /* SO_USELOOPBACK */ + IF_SOCKET ("sockopt-bin", &opt_setsockopt_bin) + IF_SOCKET ("sockopt-int", &opt_setsockopt_int) + IF_SOCKET ("sockopt-string", &opt_setsockopt_string) IF_SOCKS5 ("socks5-password", &opt_socks5_password) IF_SOCKS5 ("socks5-username", &opt_socks5_username) IF_SOCKS4 ("socksport", &opt_socksport) IF_SOCKS4 ("socksuser", &opt_socksuser) + IF_SOCKET ("socktype", &opt_so_type) IF_IPAPP ("sourceport", &opt_sourceport) IF_IPAPP ("sp", &opt_sourceport) IF_TERMIOS("start", &opt_vstart) @@ -1326,6 +1407,12 @@ const struct optname optionnames[] = { IF_TCP ("stdurg", &opt_tcp_stdurg) #endif IF_TERMIOS("stop", &opt_vstop) +#ifdef I_POP + IF_ANY ("streams-i-pop-all", &opt_streams_i_pop_all) +#endif +#ifdef I_PUSH + IF_ANY ("streams-i-push", &opt_streams_i_push) +#endif IF_ANY ("su", &opt_substuser) IF_ANY ("su-d", &opt_substuser_delayed) IF_ANY ("substuser", &opt_substuser) @@ -1357,7 +1444,9 @@ const struct optname optionnames[] = { # ifdef TAB3 IF_TERMIOS("tab3", &opt_tab3) # endif +# if TABDLY_SHIFT >= 0 IF_TERMIOS("tabdly", &opt_tabdly) +# endif #endif IF_TERMIOS("tandem", &opt_ixoff) #ifdef TCP_ABORT_THRESHOLD /* HP_UX */ @@ -1452,8 +1541,11 @@ const struct optname optionnames[] = { #ifdef O_TEXT IF_ANY ("text", &opt_o_text) #endif - IF_UNIX ("tightsocklen", &opt_unix_tightsocklen) + IF_UNIX ("tightsocklen", &xioopt_unix_tightsocklen) IF_TERMIOS("time", &opt_vtime) +#ifdef SO_TIMESTAMP + IF_SOCKET ("timestamp", &opt_so_timestamp) +#endif IF_TERMIOS("tiocsctty", &opt_tiocsctty) #if WITH_EXT2 && defined(EXT2_TOPDIR_FL) IF_ANY ("topdir", &opt_ext2_topdir) @@ -1479,7 +1571,8 @@ const struct optname optionnames[] = { IF_NAMED ("uid-e", &opt_user_early) IF_ANY ("uid-l", &opt_user_late) IF_NAMED ("umask", &opt_umask) - IF_UNIX ("unix-tightsocklen", &opt_unix_tightsocklen) + IF_IP6 ("unicast-hops", &opt_ipv6_unicast_hops) + IF_UNIX ("unix-tightsocklen", &xioopt_unix_tightsocklen) IF_NAMED ("unlink", &opt_unlink) IF_NAMED ("unlink-close", &opt_unlink_close) IF_NAMED ("unlink-early", &opt_unlink_early) @@ -1723,24 +1816,22 @@ int parseopts_table(const char **a, struct opt **opts, (*opts)[i].value.u_bin.b_len = optlen; break; case TYPE_BYTE: - { + if (assign) { unsigned long ul; - if (token) { - char *rest; - ul = strtoul(token, &rest/*!*/, 0); - } else { - ul = 1; - } + char *rest; + ul = strtoul(token, &rest/*!*/, 0); if (ul > UCHAR_MAX) { Error3("parseopts(%s): byte value exceeds limit (%lu vs. %u), using max", a0, ul, UCHAR_MAX); (*opts)[i].value.u_byte = UCHAR_MAX; } else { - Info2("setting option \"%s\" to %d", ent->desc->defname, - (*opts)[i].value.u_byte); (*opts)[i].value.u_byte = ul; } + } else { + (*opts)[i].value.u_byte = 1; } + Info2("setting option \"%s\" to %d", ent->desc->defname, + (*opts)[i].value.u_byte); break; case TYPE_INT: if (assign) { @@ -1982,6 +2073,155 @@ int parseopts_table(const char **a, struct opt **opts, (*opts)[i].value.u_linger.l_linger); break; #endif /* HAVE_STRUCT_LINGER */ + case TYPE_INT_INT: + if (!assign) { + Error1("option \"%s\": values required", a0); + continue; + } + { + char *rest; + (*opts)[i].value.u_int = strtoul(token, &rest, 0); + if (*rest != ':') { + Error1("option \"%s\": 2 arguments required", + ent->desc->defname); + } + ++rest; + (*opts)[i].value2.u_int = strtoul(rest, &rest, 0); + } + Info3("setting option \"%s\" to %d:%d", ent->desc->defname, + (*opts)[i].value.u_int, (*opts)[i].value2.u_int); + break; + case TYPE_INT_BIN: + if (!assign) { + Error1("option \"%s\": values required", a0); + continue; + } + { + char *rest; + (*opts)[i].value.u_int = strtoul(token, &rest, 0); + if (*rest != ':') { + Error1("option \"%s\": 2 arguments required", + ent->desc->defname); + } + ++rest; + optlen = 0; + if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf))) != 0) { + Error1("parseopts(): problem with \"%s\" data", rest); + continue; + } + if (((*opts)[i].value2.u_bin.b_data = memdup(optbuf, optlen)) == NULL) { + Error1("memdup(, "F_Zu"): out of memory", optlen); + return -1; + } + (*opts)[i].value2.u_bin.b_len = optlen; + } + Info2("setting option \"%s\" to %d:..."/*!!!*/, ent->desc->defname, + (*opts)[i].value.u_int); + break; + case TYPE_INT_STRING: + if (!assign) { + Error1("option \"%s\": values required", a0); + continue; + } + { + char *rest; + (*opts)[i].value.u_int = strtoul(token, &rest, 0); + if (*rest != ':') { + Error1("option \"%s\": 2 arguments required", + ent->desc->defname); + } + ++rest; + if (((*opts)[i].value2.u_string = strdup(rest)) == NULL) { + Error("out of memory"); return -1; + } + } + Info3("setting option \"%s\" to %d:\"%s\"", ent->desc->defname, + (*opts)[i].value.u_int, (*opts)[i].value2.u_string); + break; + case TYPE_INT_INT_INT: + if (!assign) { + Error1("option \"%s\": values required", a0); + continue; + } + { + char *rest; + (*opts)[i].value.u_int = strtoul(token, &rest, 0); + if (*rest != ':') { + Error1("option \"%s\": 3 arguments required", + ent->desc->defname); + } + ++rest; + (*opts)[i].value2.u_int = strtoul(rest, &rest, 0); + if (*rest != ':') { + Error1("option \"%s\": 3 arguments required", + ent->desc->defname); + } + ++rest; + (*opts)[i].value3.u_int = strtoul(rest, &rest, 0); + } + Info4("setting option \"%s\" to %d:%d:%d", ent->desc->defname, + (*opts)[i].value.u_int, (*opts)[i].value2.u_int, (*opts)[i].value3.u_int); + break; + case TYPE_INT_INT_BIN: + if (!assign) { + Error1("option \"%s\": values required", a0); + continue; + } + { + char *rest; + (*opts)[i].value.u_int = strtoul(token, &rest, 0); + if (*rest != ':') { + Error1("option \"%s\": 3 arguments required", + ent->desc->defname); + } + ++rest; + (*opts)[i].value2.u_int = strtoul(rest, &rest, 0); + if (*rest != ':') { + Error1("option \"%s\": 3 arguments required", + ent->desc->defname); + } + ++rest; + optlen = 0; + if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf))) != 0) { + Error1("parseopts(): problem with \"%s\" data", rest); + continue; + } + if (((*opts)[i].value3.u_bin.b_data = memdup(optbuf, optlen)) == NULL) { + Error1("memdup(, "F_Zu"): out of memory", optlen); + return -1; + } + (*opts)[i].value3.u_bin.b_len = optlen; + } + Info3("setting option \"%s\" to %d:%d:..."/*!!!*/, ent->desc->defname, + (*opts)[i].value.u_int, (*opts)[i].value2.u_int); + break; + case TYPE_INT_INT_STRING: + if (!assign) { + Error1("option \"%s\": values required", a0); + continue; + } + { + char *rest; + (*opts)[i].value.u_int = strtoul(token, &rest, 0); + if (*rest != ':') { + Error1("option \"%s\": 3 arguments required", + ent->desc->defname); + } + ++rest; + (*opts)[i].value2.u_int = strtoul(rest, &rest, 0); + if (*rest != ':') { + Error1("option \"%s\": 3 arguments required", + ent->desc->defname); + } + ++rest; + if (((*opts)[i].value3.u_string = strdup(rest)) == NULL) { + Error("out of memory"); return -1; + } + } + Info4("setting option \"%s\" to %d:%d:\"%s\"", ent->desc->defname, + (*opts)[i].value.u_int, (*opts)[i].value2.u_int, + (*opts)[i].value3.u_string); + break; #if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) case TYPE_IP_MREQN: { @@ -2041,7 +2281,7 @@ int parseopts_table(const char **a, struct opt **opts, #if WITH_IP4 case TYPE_IP4NAME: { - struct sockaddr_in sa; size_t salen = sizeof(sa); + struct sockaddr_in sa; socklen_t salen = sizeof(sa); const char *ends[] = { NULL }; const char *nests[] = { "[","]", NULL }; char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1; @@ -2059,7 +2299,7 @@ int parseopts_table(const char **a, struct opt **opts, 0, 0/*!!!*/) != STAT_OK) { opt->desc = ODESC_ERROR; continue; } - opt->value.u_ip4addr = sa.sin_addr.s_addr; + opt->value.u_ip4addr = sa.sin_addr; } break; #endif /* defined(WITH_IP4) */ @@ -2219,7 +2459,7 @@ int _groupbits(mode_t mode) { case (S_IFIFO>>12): /* 1, FIFO */ result = GROUP_FIFO; break; case (S_IFCHR>>12): /* 2, character device */ - result = GROUP_CHR|GROUP_TERMIOS; break; + result = GROUP_TERMIOS; break; case (S_IFDIR>>12): /* 4, directory !!! not supported */ result = GROUP_NONE; break; case (S_IFBLK>>12): /* 6, block device */ @@ -2261,11 +2501,6 @@ int groupbits(int fd) { return -1; } result = _groupbits(buf.st_mode&S_IFMT); - if (result == GROUP_CHR) { - if (Isatty(fd) > 0) { - result |= GROUP_TERMIOS; - } - } return result; } @@ -2374,7 +2609,15 @@ int retropt_int(struct opt *opts, int optcode, int *result) { while (opt->desc != ODESC_END) { if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) { - *result = opt->value.u_int; + switch (opt->desc->type) { + case TYPE_INT: *result = opt->value.u_int; break; + case TYPE_STRING: *result = strtol(opt->value.u_string, NULL, 0); + break; + default: Error2("cannot convert type %d of option %s to int", + opt->desc->type, opt->desc->defname); + opt->desc = ODESC_ERROR; + return -1; + } opt->desc = ODESC_DONE; return 0; } @@ -2488,13 +2731,13 @@ int retropt_string(struct opt *opts, int optcode, char **result) { } -#if WITH_SOCKET +#if _WITH_SOCKET /* looks for an bind option and, if found, overwrites the complete contents of sa with the appropriate value(s). returns STAT_OK if option exists and could be resolved, STAT_NORETRY if option exists but had error, or STAT_NOACTION if it does not exist */ -/* currently only for IP (v4, v6) */ +/* currently only for IP (v4, v6) and raw (PF_UNSPEC) */ int retropt_bind(struct opt *opts, int af, int socktype, @@ -2516,22 +2759,26 @@ int retropt_bind(struct opt *opts, if (retropt_string(opts, OPT_BIND, &bindname) < 0) { return STAT_NOACTION; } - addrallowed = true; - portallowed = (feats>=2); bindp = bindname; - nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests, - true, true, false, false); - *hostp++ = '\0'; - if (!strncmp(bindp, portsep, strlen(portsep))) { - if (!portallowed) { - Error("port specification not allowed in this bind option"); - return STAT_NORETRY; - } else { - portp = bindp + strlen(portsep); - } - } switch (af) { + + case AF_UNSPEC: + { + size_t p = 0; + dalan(bindname, (char *)sa->sa_data, &p, *salen-sizeof(sa->sa_family)); + *salen = p + sizeof(sa->sa_family); + *salen = p + +#if HAVE_STRUCT_SOCKADDR_SALEN + sizeof(sa->sa_len) + +#endif + sizeof(sa->sa_family); +#if HAVE_STRUCT_SOCKADDR_SALEN + sa->sa_len = *salen; +#endif + } + break; + #if WITH_IP4 || WITH_IP6 #if WITH_IP4 case AF_INET: @@ -2539,6 +2786,19 @@ int retropt_bind(struct opt *opts, #if WITH_IP6 case AF_INET6: #endif /*WITH_IP6 */ + addrallowed = true; + portallowed = (feats>=2); + nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests, + true, false, false, false); + *hostp++ = '\0'; + if (!strncmp(bindp, portsep, strlen(portsep))) { + if (!portallowed) { + Error("port specification not allowed in this bind option"); + return STAT_NORETRY; + } else { + portp = bindp + strlen(portsep); + } + } if ((result = xiogetaddrinfo(hostname[0]!='\0'?hostname:NULL, portp, af, socktype, ipproto, @@ -2556,7 +2816,7 @@ int retropt_bind(struct opt *opts, { bool tight = false; struct sockaddr_un *s_un = (struct sockaddr_un *)sa; - *salen = xiosetunix(s_un, bindname, false, tight); + *salen = xiosetunix(af, s_un, bindname, false, tight); } break; #endif /* WITH_UNIX */ @@ -2567,14 +2827,14 @@ int retropt_bind(struct opt *opts, } return STAT_OK; } -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ /* applies to fd all options belonging to phase */ /* note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN) implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types), OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */ -int applyopts(int fd, struct opt *opts, unsigned int phase) { +int applyopts(int fd, struct opt *opts, enum e_phase phase) { struct opt *opt; opt = opts; while (opt && opt->desc != ODESC_END) { @@ -2645,7 +2905,49 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) { opt->desc = ODESC_ERROR; ++opt; continue; } -#if WITH_SOCKET + } else if (opt->desc->func == OFUNC_IOCTL_GENERIC) { + switch (opt->desc->type) { + case TYPE_INT: + if (Ioctl(fd, opt->value.u_int, NULL) < 0) { + Error3("ioctl(%d, 0x%x, NULL): %s", + fd, opt->value.u_int, strerror(errno)); + opt->desc = ODESC_ERROR; ++opt; continue; + } + break; + case TYPE_INT_INT: + if (Ioctl_int(fd, opt->value.u_int, opt->value2.u_int) < 0) { + Error4("ioctl(%d, 0x%x, 0x%x): %s", + fd, opt->value.u_int, opt->value2.u_int, strerror(errno)); + opt->desc = ODESC_ERROR; ++opt; continue; + } + break; + case TYPE_INT_INTP: + if (Ioctl(fd, opt->value.u_int, (void *)&opt->value2.u_int) < 0) { + Error4("ioctl(%d, 0x%x, %p): %s", + fd, opt->value.u_int, (void *)&opt->value2.u_int, strerror(errno)); + opt->desc = ODESC_ERROR; ++opt; continue; + } + break; + case TYPE_INT_BIN: + if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data) < 0) { + Error4("ioctl(%d, 0x%x, %p): %s", + fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data, strerror(errno)); + opt->desc = ODESC_ERROR; ++opt; continue; + } + break; + case TYPE_INT_STRING: + if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_string) < 0) { + Error4("ioctl(%d, 0x%x, %p): %s", + fd, opt->value.u_int, (void *)opt->value2.u_string, strerror(errno)); + opt->desc = ODESC_ERROR; ++opt; continue; + } + break; + default: + Error1("ioctl() data type %d not implemented", + opt->desc->type); + } + +#if _WITH_SOCKET } else if (opt->desc->func == OFUNC_SOCKOPT) { if (0) { ; @@ -2774,7 +3076,7 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) { &opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr)) < 0) { Error6("setsockopt(%d, %d, %d, {0x%x}, "F_Zu"): %s", fd, opt->desc->major, opt->desc->minor, - opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr), + *(uint32_t *)&opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr), strerror(errno)); } break; @@ -2822,7 +3124,39 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) { opt->desc->defname, opt->desc->type); break; } -#endif /* WITH_SOCKET */ + } else if (opt->desc->func == OFUNC_SOCKOPT_GENERIC) { + switch (opt->desc->type) { + case TYPE_INT_INT_INT: + if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, + &opt->value3.u_int, sizeof(int)) < 0) { + Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", + fd, opt->value.u_int, opt->value2.u_int, + opt->value3.u_int, sizeof(int), strerror(errno)); + } + break; + case TYPE_INT_INT_BIN: + if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, + opt->value3.u_bin.b_data, opt->value3.u_bin.b_len) < 0) { + Error5("setsockopt(%d, %d, %d, {...}, "F_Zu"): %s", + fd, opt->value.u_int, opt->value2.u_int, + opt->value3.u_bin.b_len, strerror(errno)); + } + break; + case TYPE_INT_INT_STRING: + if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, + opt->value3.u_string, + strlen(opt->value3.u_string)+1) < 0) { + Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s", + fd, opt->value.u_int, opt->value2.u_int, + opt->value3.u_string, strlen(opt->value3.u_string)+1, + strerror(errno)); + } + break; + default: + Error1("setsockopt() data type %d not implemented", + opt->desc->type); + } +#endif /* _WITH_SOCKET */ #if HAVE_FLOCK } else if (opt->desc->func == OFUNC_FLOCK) { @@ -3040,6 +3374,7 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) { } } break; + default: Error1("applyopts(): option \"%s\" not implemented", opt->desc->defname); opt->desc = ODESC_ERROR; ++opt; continue; @@ -3277,6 +3612,12 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) { #endif /* WITH_TERMIOS */ +#if WITH_STREAMS +#define ENABLE_APPLYOPT +#include "xio-streams.c" +#undef ENABLE_APPLYOPT +#endif /* WITH_STREAMS */ + } else { /*Error1("applyopts(): function %d not implemented", opt->desc->func);*/ @@ -3381,6 +3722,8 @@ static int applyopt_offset(struct single *xfd, struct opt *opt) { switch (opt->desc->type) { case TYPE_BOOL: *(bool *)ptr = opt->value.u_bool; break; + case TYPE_INT: + *(int *)ptr = opt->value.u_int; break; case TYPE_UINT: *(unsigned int *)ptr = opt->value.u_uint; break; case TYPE_DOUBLE: @@ -3492,7 +3835,7 @@ int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) { xfd->lock.intervall.tv_sec = 1; xfd->lock.intervall.tv_nsec = 0; - /*! this should be integrated into central select loop */ + /*! this should be integrated into central select()/poll() loop */ if (xiolock(&xfd->lock) < 0) { return -1; } @@ -3538,7 +3881,7 @@ int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) { } break; -#if WITH_SOCKET +#if _WITH_SOCKET case OFUNC_SOCKOPT: switch (opt->desc->optcode) { #if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) @@ -3557,9 +3900,9 @@ mc:ifname|ifind mc:addr */ union sockaddr_union sockaddr1; - size_t socklen1 = sizeof(sockaddr1.ip4); + socklen_t socklen1 = sizeof(sockaddr1.ip4); union sockaddr_union sockaddr2; - size_t socklen2 = sizeof(sockaddr2.ip4); + socklen_t socklen2 = sizeof(sockaddr2.ip4); /* first parameter is alway multicast address */ /*! result */ @@ -3581,7 +3924,7 @@ mc:addr ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr; /* third parameter is interface */ if (ifindex(opt->value.u_ip_mreq.ifindex, - (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex) + (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex, -1) < 0) { Error1("cannot resolve interface \"%s\"", opt->value.u_ip_mreq.ifindex); @@ -3594,7 +3937,8 @@ mc:addr #if HAVE_STRUCT_IP_MREQN /* there is a form with two parameters that uses mreqn */ } else if (ifindex(opt->value.u_ip_mreq.param2, - (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex) + (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex, + -1) >= 0) { /* yes, second param converts to interface */ ip4_mreqn.mreq.imr_interface.s_addr = htonl(0); @@ -3655,7 +3999,7 @@ mc:addr { struct ipv6_mreq ip6_mreq = {{{{0}}}}; union sockaddr_union sockaddr1; - size_t socklen1 = sizeof(sockaddr1.ip6); + socklen_t socklen1 = sizeof(sockaddr1.ip6); /* always two parameters */ /* first parameter is multicast address */ @@ -3666,7 +4010,8 @@ mc:addr &sockaddr1, &socklen1, 0, 0); ip6_mreq.ipv6mr_multiaddr = sockaddr1.ip6.sin6_addr; if (ifindex(opt->value.u_ip_mreq.param2, - &ip6_mreq.ipv6mr_interface) < 0) { + &ip6_mreq.ipv6mr_interface, -1) + < 0) { Error1("interface \"%s\" not found", opt->value.u_ip_mreq.param2); ip6_mreq.ipv6mr_interface = htonl(0); @@ -3689,7 +4034,7 @@ mc:addr ++opt; continue; } break; -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ default: ++opt; diff --git a/xioopts.h b/xioopts.h index 695e3bf..ac2d31e 100644 --- a/xioopts.h +++ b/xioopts.h @@ -9,6 +9,8 @@ #define ODESC_DONE ((void *)-1) /* indicates that option has been applied */ #define ODESC_ERROR ODESC_DONE /* maybe later */ +#define XIO_OFFSETOF(x) ((size_t)&((xiosingle_t *)0)->x) + /* atomic structure for use in the option search table; keep compatible with struct wordent! */ struct optname { @@ -22,39 +24,53 @@ enum e_types { TYPE_BIN, /* raw binary data, length determined by data */ TYPE_BOOL, /* value is 0 or 1 (no-value is interpreted as 1) */ TYPE_BYTE, /* unsigned char */ + TYPE_INT, /* int */ TYPE_LONG, /* long */ TYPE_STRING, /* char * */ TYPE_NAME = TYPE_STRING, TYPE_FILENAME = TYPE_STRING, TYPE_PTRDIFF, /* ptrdiff_t */ + TYPE_SHORT, /* short */ TYPE_SIZE_T, /* size_t */ TYPE_SOCKADDR, /* struct sockaddr * */ TYPE_UINT, /* unsigned int */ + TYPE_ULONG, /* unsigned long */ TYPE_USHORT, /* unsigned short */ + TYPE_2BYTE = TYPE_USHORT, TYPE_MODET, /* representation of mode_t */ TYPE_GIDT, /* representation of gid_t */ + TYPE_UIDT, /* representation of uid_t */ /*TYPE_FLAG,*/ TYPE_INT3, /* int[3] */ TYPE_TIMEVAL, /* struct timeval: {long;long;}, seconds and microsec. */ TYPE_TIMESPEC, /* struct timespec: {time_t;long;}, seconds and nanosec. */ -#if HAVE_STRUCT_LINGER - TYPE_LINGER, /* struct linger */ -#endif /* HAVE_STRUCT_LINGER */ + TYPE_DOUBLE, /* double */ TYPE_STRING_NULL, /* char *; string or NULL */ TYPE_LONGLONG, /* long long */ TYPE_OFF32, /* off_t */ + TYPE_OFF64, /* off64_t */ + TYPE_INT_INT, /* 2 parameters: first is int, second is int */ + TYPE_INT_INTP, /* 2 parameters: first is int, second is int* */ + TYPE_INT_BIN, /* 2 parameters: first is int, second is binary */ + + TYPE_INT_STRING, /* 2 parameters: first is int, second is req string */ + TYPE_INT_INT_INT, /* 3 params: first and second are int, 3rd is int */ + TYPE_INT_INT_BIN, /* 3 params: first and second are int, 3rd is binary */ + TYPE_INT_INT_STRING, /* 3 params: first and second are int, 3rd is string */ + + TYPE_IP4NAME, /* IPv4 hostname or address */ +#if HAVE_STRUCT_LINGER + TYPE_LINGER, /* struct linger */ +#endif /* HAVE_STRUCT_LINGER */ #if HAVE_STRUCT_IP_MREQ || HAVE_STRUCT_IP_MREQN TYPE_IP_MREQN, /* for struct ip_mreq or struct ip_mreqn */ #endif - TYPE_IP4NAME, /* IPv4 hostname or address */ - - TYPE_2BYTE = TYPE_USHORT } ; enum e_func { @@ -64,11 +80,14 @@ enum e_func { OFUNC_SEEK32, /* lseek(): arg1 is whence (SEEK_SET etc.) */ OFUNC_SEEK64, /* lseek64(): arg1 is whence (SEEK_SET etc.) */ OFUNC_FCNTL, /* fcntl(, ): arg1 is cmd */ - OFUNC_IOCTL, /* ioctl(): arg1 is request */ + OFUNC_IOCTL, /* ioctl(): arg1 of option description is request, arg2 + is int setrequest */ OFUNC_IOCTL_MASK_LONG, /* arg1 is getrequest, arg2 is setrequest: ioctl(arg1, ); |= arg3; ioctl(arg2, ); */ + OFUNC_IOCTL_GENERIC, /* generic ioctl() (request on cmdline) */ OFUNC_SOCKOPT, /* setsockopt() */ OFUNC_SOCKOPT_APPEND,/* getsockopt(), append data, setsockopt() */ + OFUNC_SOCKOPT_GENERIC,/* generic setsockopt() (level, optname on cmdline) */ OFUNC_FLOCK, /* flock() */ OFUNC_TERMIO, /* termio() ? */ OFUNC_SPEC, /* special, i.e. no generalizable function call */ @@ -86,7 +105,10 @@ enum e_func { OFUNC_TERMIOS_SPEC, /* termios combined modes */ OFUNC_SIGNAL, /* a signal that should be passed to child process */ OFUNC_RESOLVER, /* a bit position used on _res.options */ - OFUNC_IFFLAG /* interface flag: locical-or a 1bit mask */ + OFUNC_IFFLAG, /* interface flag: locical-or a 1bit mask */ +# define ENABLE_OFUNC +# include "xio-streams.h" /* push a POSIX STREAMS module */ +# undef ENABLE_OFUNC } ; /* for simpler handling of option-to-connection-type relations we define @@ -110,8 +132,9 @@ enum e_func { #define GROUP_FD 0x00000001 /* everything applyable to a fd */ #define GROUP_FIFO 0x00000002 -#define GROUP_CHR 0x00000004 +#define GROUP_SOCKS5 0x00000004 #define GROUP_BLK 0x00000008 +#define GROUP_CHR 0x00000000 /* currently not used */ #define GROUP_REG 0x00000010 #define GROUP_FILE GROUP_REG #define GROUP_SOCKET 0x00000020 @@ -140,14 +163,14 @@ enum e_func { #define GROUP_IP_UDP 0x01000000 #define GROUP_IP_TCP 0x02000000 -#define GROUP_IPAPP (GROUP_IP_UDP|GROUP_IP_TCP) /* true: indicates one of UDP, TCP */ +#define GROUP_IPAPP (GROUP_IP_UDP|GROUP_IP_TCP|GROUP_IP_SCTP) /* true: indicates one of UDP, TCP, SCTP */ #define GROUP_IP_SOCKS4 0x04000000 #define GROUP_OPENSSL 0x08000000 #define GROUP_PROCESS 0x10000000 /* a process related option */ #define GROUP_APPL 0x20000000 /* option handled by data loop */ #define GROUP_HTTP 0x40000000 /* any HTTP client */ -#define GROUP_SOCKS5 0x80000000 +#define GROUP_IP_SCTP 0x80000000 #define GROUP_ANY (GROUP_PROCESS|GROUP_APPL) #define GROUP_ALL 0xffffffff @@ -251,6 +274,7 @@ enum e_optcode { OPT_ECHOPRT, /* termios.c_lflag */ #endif OPT_END_CLOSE, /* xfd.stream.howtoend = END_CLOSE */ + OPT_ESCAPE, OPT_EXT2_SECRM, OPT_EXT2_UNRM, OPT_EXT2_COMPR, @@ -325,11 +349,33 @@ enum e_optcode { OPT_INLCR, /* termios.c_iflag */ OPT_INPCK, /* termios.c_iflag */ OPT_INTERVALL, + OPT_IPV6_AUTHHDR, + OPT_IPV6_DSTOPTS, + OPT_IPV6_FLOWINFO, + OPT_IPV6_HOPLIMIT, + OPT_IPV6_HOPOPTS, OPT_IPV6_JOIN_GROUP, + OPT_IPV6_PKTINFO, + OPT_IPV6_RECVDSTOPTS, + OPT_IPV6_RECVERR, + OPT_IPV6_RECVHOPLIMIT, + OPT_IPV6_RECVHOPOPTS, + OPT_IPV6_RECVPATHMTU, + OPT_IPV6_RECVPKTINFO, + OPT_IPV6_RECVRTHDR, + OPT_IPV6_RECVTCLASS, + OPT_IPV6_RTHDR, + OPT_IPV6_TCLASS, + OPT_IPV6_UNICAST_HOPS, OPT_IPV6_V6ONLY, #if 0 /* see Linux: man 7 netlink; probably not what we need yet */ OPT_IO_SIOCGIFNAME, #endif + OPT_IOCTL_BIN, /* generic ioctl with binary value (pointed to) */ + OPT_IOCTL_INT, /* generic ioctl with integer value */ + OPT_IOCTL_INTP, /* generic ioctl with integer value (pointed to) */ + OPT_IOCTL_STRING, /* generic ioctl with integer value (pointed to) */ + OPT_IOCTL_VOID, /* generic ioctl without value */ OPT_IP_ADD_MEMBERSHIP, #ifdef IP_HDRINCL OPT_IP_HDRINCL, @@ -353,9 +399,11 @@ enum e_optcode { #ifdef IP_PKTOPTIONS OPT_IP_PKTOPTIONS, #endif + OPT_IP_RECVDSTADDR, #ifdef IP_RECVERR OPT_IP_RECVERR, #endif + OPT_IP_RECVIF, #ifdef IP_RECVOPTS OPT_IP_RECVOPTS, #endif @@ -500,7 +548,8 @@ enum e_optcode { OPT_PIPES, /*OPT_PORT,*/ OPT_PROMPT, /* readline */ - OPT_PROTOCOL_FAMILY, + OPT_PROTOCOL, /* 6=TCP, 17=UDP */ + OPT_PROTOCOL_FAMILY, /* 1=PF_UNIX, 2=PF_INET, 10=PF_INET6 */ OPT_PROXYPORT, OPT_PROXY_AUTHORIZATION, OPT_PROXY_RESOLVE, @@ -524,6 +573,9 @@ enum e_optcode { OPT_RES_USEVC, /* resolver(3) */ OPT_RETRY, OPT_SANE, /* termios */ + OPT_SCTP_MAXSEG, + OPT_SCTP_MAXSEG_LATE, + OPT_SCTP_NODELAY, OPT_SEEK32_CUR, OPT_SEEK32_END, OPT_SEEK32_SET, @@ -534,6 +586,9 @@ enum e_optcode { OPT_SETGID_EARLY, OPT_SETPGID, OPT_SETSID, + OPT_SETSOCKOPT_BIN, + OPT_SETSOCKOPT_INT, + OPT_SETSOCKOPT_STRING, OPT_SETUID, OPT_SETUID_EARLY, OPT_SHUT_NONE, @@ -595,9 +650,7 @@ enum e_optcode { #ifdef SO_PRIORITY OPT_SO_PRIORITY, #endif -#ifdef SO_PROTOTYPE OPT_SO_PROTOTYPE, -#endif OPT_SO_RCVBUF, OPT_SO_RCVBUF_LATE, #ifdef SO_RCVLOWAT @@ -627,6 +680,7 @@ enum e_optcode { #ifdef SO_SNDTIMEO OPT_SO_SNDTIMEO, #endif + OPT_SO_TIMESTAMP, /* Linux */ OPT_SO_TYPE, #ifdef SO_USELOOPBACK OPT_SO_USELOOPBACK, @@ -642,6 +696,9 @@ enum e_optcode { #endif OPT_SOURCEPORT, OPT_STDERR, /* with exec, system */ +# define ENABLE_OPTCODE +# include "xio-streams.h" +# undef ENABLE_OPTCODE OPT_SUBSTUSER, OPT_SUBSTUSER_DELAYED, OPT_SYMBOLIC_LINK, /* with pty */ @@ -775,7 +832,8 @@ enum e_optcode { /* keep consistent with xiohelp.c:optionphasenames ! */ enum e_phase { - PH_ALL, /* not for options; use in apply funcs to say "all phases" */ + PH_ALL, /* not for option definitions; use in apply funcs to + say "all phases" */ PH_INIT, /* retrieving info from original state */ PH_EARLY, /* before any other processing */ PH_PREOPEN, /* before file descriptor is created/opened */ @@ -851,7 +909,7 @@ extern int retropt_bind(struct opt *opts, int feats, /* TCP etc: 1..address allowed, 3..address and port allowed */ unsigned long res_opts0, unsigned long res_opts1); -extern int applyopts(int fd, struct opt *opts, unsigned int phase); +extern int applyopts(int fd, struct opt *opts, enum e_phase phase); extern int applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to); extern int applyopts_flags(struct opt *opts, int group, flags_t *result); diff --git a/xioread.c b/xioread.c index 33faae9..7c5dc28 100644 --- a/xioread.c +++ b/xioread.c @@ -140,14 +140,27 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) { break; #endif /* WITH_OPENSSL */ -#if WITH_SOCKET +#if _WITH_SOCKET case XIOREAD_RECV: if (pipe->dtype & XIOREAD_RECV_FROM) { #if WITH_RAWIP || WITH_UDP || WITH_UNIX + struct msghdr msgh = {0}; union sockaddr_union from = {{0}}; socklen_t fromlen = sizeof(from); char infobuff[256]; + char ctrlbuff[1024]; /* ancillary messages */ + msgh.msg_name = &from; + msgh.msg_namelen = fromlen; +#if HAVE_STRUCT_MSGHDR_MSGCONTROL + msgh.msg_control = ctrlbuff; +#endif +#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN + msgh.msg_controllen = sizeof(ctrlbuff); +#endif + if (xiogetpacketsrc(pipe->fd1, &msgh) < 0) { + return -1; + } do { bytes = Recvfrom(fd, buff, bufsiz, 0, &from.soa, &fromlen); } while (bytes < 0 && errno == EINTR); @@ -161,6 +174,17 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) { errno = _errno; return -1; } + /* on packet type we also receive outgoing packets, this is not desired + */ +#if defined(PF_PACKET) && defined(PACKET_OUTGOING) + if (from.soa.sa_family == PF_PACKET) { + if ((((struct sockaddr_ll *)&from.soa)->sll_pkttype & PACKET_OUTGOING) + == 0) { + errno = EAGAIN; return -1; + } + } +#endif /* defined(PF_PACKET) && defined(PACKET_OUTGOING) */ + Notice2("received packet with "F_Zu" bytes from %s", bytes, sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff))); @@ -313,12 +337,23 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) { } else /* ~XIOREAD_RECV_FROM */ { union sockaddr_union from; socklen_t fromlen = sizeof(from); char infobuff[256]; + struct msghdr msgh = {0}; + char ctrlbuff[1024]; /* ancillary messages */ socket_init(pipe->para.socket.la.soa.sa_family, &from); /* get source address */ - if (xiogetpacketsrc(fd, &from, &fromlen) < 0) { - return STAT_RETRYNOW; + msgh.msg_name = &from; + msgh.msg_namelen = fromlen; +#if HAVE_STRUCT_MSGHDR_MSGCONTROL + msgh.msg_control = ctrlbuff; +#endif +#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN + msgh.msg_controllen = sizeof(ctrlbuff); +#endif + if (xiogetpacketsrc(pipe->fd1, &msgh) < 0) { + return -1; } + xiodopacketinfo(&msgh, true, false); if (xiocheckpeer(pipe, &from, &pipe->para.socket.la) < 0) { Recvfrom(fd, buff, bufsiz, 0, &from.soa, &fromlen); /* drop */ errno = EAGAIN; return -1; @@ -384,7 +419,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) { } break; -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ default: Error("internal: undefined read operation"); @@ -396,8 +431,8 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) { /* this function is intended only for some special address types where the - select() call cannot strictly determine if (more) read data is available. - currently this is for the OpenSSL based addresses. + select()/poll() calls cannot strictly determine if (more) read data is + available. currently this is for the OpenSSL based addresses. */ ssize_t xiopending(xiofile_t *file) { struct single *pipe; diff --git a/xioshutdown.c b/xioshutdown.c index aa68637..49c7f82 100644 --- a/xioshutdown.c +++ b/xioshutdown.c @@ -1,5 +1,5 @@ /* source: xioshutdown.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this is the source of the extended shutdown function */ @@ -61,29 +61,27 @@ int xioshutdown(xiofile_t *sock, int how) { default: break; } +#if 0 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 _WITH_SOCKET + case XIOSHUT_DOWN: if ((result = Shutdown(sock->stream.fd1, how)) < 0) { Info3("shutdown(%d, %d): %s", sock->stream.fd1, how, strerror(errno)); } break; - case END_SHUTDOWN_KILL: + case XIOSHUT_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: +#endif /* _WITH_SOCKET */ + case XIOSHUT_CLOSE: Close(sock->stream.fd1); #if WITH_TERMIOS if (sock->stream.ttyvalid) { @@ -94,13 +92,14 @@ int xioshutdown(xiofile_t *sock, int how) { } #endif /* WITH_TERMIOS */ /*PASSTHROUGH*/ - case END_NONE: + case XIOSHUT_NONE: break; default: - Error1("xioshutdown(): bad end action 0x%x", sock->stream.howtoclose); + Error1("xioshutdown(): bad shutdown action 0x%x", sock->stream.howtoshut); return -1; } -#if WITH_SOCKET + +#if 0 && _WITH_SOCKET case XIODATA_RECVFROM: if (how >= 1) { if (Close(sock->stream.fd1) < 0) { @@ -111,13 +110,9 @@ int xioshutdown(xiofile_t *sock, int how) { sock->stream.fd1 = -1; } break; -#endif /* WITH_SOCKET */ -#endif /* 0 */ - default: - Error1("xioshutdown(): bad data type specification 0x%x", sock->stream.dtype); - return -1; - } +#endif /* _WITH_SOCKET */ } +#endif if ((how+1) & 1) { /* contains SHUT_RD */ switch (sock->stream.dtype & XIODATA_READMASK) { @@ -153,19 +148,20 @@ int xioshutdown(xiofile_t *sock, int how) { case XIOSHUTWR_NONE: break; -#if WITH_SOCKET +#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 */ +#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 case XIOSHUTWR_SIGHUP: /* the child process might want to flush some data before @@ -185,7 +181,7 @@ int xioshutdown(xiofile_t *sock, int how) { default: Error1("xioshutdown(): unhandled howtoshut=0x%x during SHUT_WR", - sock->stream.howtoshut); + sock->stream.howtoshut&XIOSHUTWR_MASK); } } diff --git a/xiosocketpair.c b/xiosocketpair.c index 5ae374a..5ce69b3 100644 --- a/xiosocketpair.c +++ b/xiosocketpair.c @@ -23,7 +23,7 @@ how==2: var args (int)useptmx returns -1 on error or 0 on success */ -int xiosocketpair(xiofile_t **xfd1p, xiofile_t **xfd2p, int how, ...) { +int xiosocketpair2(xiofile_t **xfd1p, xiofile_t **xfd2p, int how, ...) { va_list ap; xiofile_t *xfd1, *xfd2; int result = 0; diff --git a/xiotransfer.c b/xiotransfer.c index dfd4f5b..1a2bbcf 100644 --- a/xiotransfer.c +++ b/xiotransfer.c @@ -1,5 +1,5 @@ -/* $Id$ */ -/* Copyright Gerhard Rieger 2007 */ +/* source: xiotransfer.c */ +/* Copyright Gerhard Rieger 2007-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this is the source file of the data transfer function */ @@ -90,8 +90,9 @@ static int /* 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 + buff must be a malloc()'ed storage and might be realloc()'ed in this + function if more space is required after 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. @@ -101,7 +102,7 @@ static int /* 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; + ssize_t bytes, writt = 0; bytes = xioread(inpipe, *buff, bufsiz); if (bytes < 0) { @@ -110,11 +111,35 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe, /*xioshutdown(inpipe, SHUT_RD);*/ return -1; } - if (bytes == 0) { - writt = 0; + if (bytes == 0 && XIO_RDSTREAM(inpipe)->ignoreeof && + !inpipe->stream.closing) { + ; + } else if (bytes == 0) { + XIO_RDSTREAM(inpipe)->eof = 2; + inpipe->stream.closing = MAX(inpipe->stream.closing, 1); } - else /* if (bytes > 0)*/ { + if (bytes > 0) { + /* handle escape char */ + if (XIO_RDSTREAM(inpipe)->escape != -1) { + /* check input data for escape char */ + unsigned char *ptr = *buff; + size_t ctr = 0; + while (ctr < bytes) { + if (*ptr == XIO_RDSTREAM(inpipe)->escape) { + /* found: set flag, truncate input data */ + XIO_RDSTREAM(inpipe)->actescape = true; + bytes = ctr; + Info("escape char found in input"); + break; + } + ++ptr; ++ctr; + } + if (ctr != bytes) { + XIO_RDSTREAM(inpipe)->eof = 2; + } + } + } if (XIO_RDSTREAM(inpipe)->lineterm != XIO_WRSTREAM(outpipe)->lineterm) { @@ -123,7 +148,8 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe, XIO_WRSTREAM(outpipe)->lineterm); } if (bytes == 0) { - errno = EAGAIN; return -1; + /*errno = EAGAIN; return -1;*/ + return bytes; } if (xioparams->verbose && xioparams->verbhex) { @@ -224,7 +250,6 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe, Info3("transferred "F_Zu" bytes from %d to %d", writt, XIO_GETRDFD(inpipe), XIO_GETWRFD(outpipe)); } - } return writt; } diff --git a/xiowrite.c b/xiowrite.c index 662b584..206e201 100644 --- a/xiowrite.c +++ b/xiowrite.c @@ -1,5 +1,5 @@ /* source: xiowrite.c */ -/* Copyright Gerhard Rieger 2001-2007 */ +/* Copyright Gerhard Rieger 2001-2008 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this is the source of the extended write function */ @@ -14,9 +14,9 @@ /* ... - note that the write() call can block even if the select() call reported the - FD writeable: in case the FD is not nonblocking and a lock defers the - operation. + note that the write() call can block even if the select()/poll() call + reported the FD writeable: in case the FD is not nonblocking and a lock + defers the operation. on return value < 0: errno reflects the value from write() */ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) { ssize_t writt; @@ -80,7 +80,7 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) { } break; -#if WITH_SOCKET +#if _WITH_SOCKET case XIOWRITE_SENDTO: /*union { char space[sizeof(struct sockaddr_un)]; @@ -121,7 +121,7 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) { sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff))); } break; -#endif /* WITH_SOCKET */ +#endif /* _WITH_SOCKET */ case XIOWRITE_PIPE: case XIOWRITE_2PIPE: