socat V1.6.0.0 (initial GIT commit)
diff --git a/BUGREPORTS b/BUGREPORTS
new file mode 100644
index 0000000..eaf9cf8
--- /dev/null
+++ b/BUGREPORTS
@@ -0,0 +1,18 @@
+
+* If you have found a bug, i.e. socat SIGSEGV'ed, terminated abnormally without
+error message, did not comply to the documentation, or behaves different from
+your expectations, please send the following infos to socat@dest-unreach.org,
+as available:
+. output of "make info" in socat.out (you may remove the hostname in the first
+line to keep your privacy)
+. config.log
+. run your example with "socat -d -d -d -d -D ..." options, and include the log
+output
+. describe what you've done, and why you think socat did wrong
+
+* If you fixed a bug:
+Please do as described in the above paragraph, and include the modified files
+(or a patch file)
+
+* If you have contributions, problems etc: send available info and a
+description to the above address.
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..8148136
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,771 @@
+
+####################### V 1.6.0.0:
+
+new features:
+ new addresses IP-DATAGRAM and UDP-DATAGRAM allow versatile broadcast
+ and multicast modes
+
+ new option ip-add-membership for control of multicast group membership
+
+ new address TUN for generation of Linux TUN/TAP pseudo network
+ interfaces (suggested by Mat Caughron); associated options tun-device,
+ tun-name, tun-type; iff-up, iff-promisc, iff-noarp, iff-no-pi etc.
+
+ new addresses ABSTRACT-CONNECT, ABSTRACT-LISTEN, ABSTRACT-SENDTO,
+ ABSTRACT-RECV, and ABSTRACT-RECVFROM for abstract UNIX domain addresses
+ on Linux (requested by Zeeshan Ali); option unix-tightsocklen controls
+ socklen parameter on system calls.
+
+ option end-close for control of connection closing allows FD sharing
+ by sub processes
+
+ range option supports form address:mask with IPv4
+
+ changed behaviour of SSL-LISTEN to require and verify client
+ certificate per default
+
+ options f-setlkw-rd, f-setlkw-wr, f-setlk-rd, f-setlk-wr allow finer
+ grained locking on regular files
+
+ uninstall target in Makefile (lack reported by Zeeshan Ali)
+
+corrections:
+ fixed bug where only first tcpwrap option was applied; fixed bug where
+ tcpwrap IPv6 check always failed (thanks to Rudolf Cejka for reporting
+ and fixing this bug)
+
+ filan (and socat -D) could hang when a socket was involved
+
+ corrected PTYs on HP-UX (and maybe others) using STREAMS (inspired by
+ Roberto Mackun)
+
+ correct bind with udp6-listen (thanks to Jan Horak for reporting this
+ bug)
+
+ corrected filan.c peekbuff[0] which did not compile with Sun Studio Pro
+ (thanks to Leo Zhadanovsky for reporting this problem)
+
+ corrected problem with read data buffered in OpenSSL layer (thanks to
+ Jon Nelson for reporting this bug)
+
+ corrected problem with option readbytes when input stream stayed idle
+ after so many bytes
+
+ fixed a bug where a datagram receiver with option fork could fork two
+ sub processes per packet
+
+further changes:
+ moved documentation to new doc/ subdir
+
+ new documents (kind of mini tutorials) are provided in doc/
+
+####################### V 1.5.0.0:
+
+new features:
+ new datagram modes for udp, rawip, unix domain sockets
+
+ socat option -T specifies inactivity timeout
+
+ rewrote lexical analysis to allow nested socat calls
+
+ addresses tcp, udp, tcp-l, udp-l, and rawip now support IPv4 and IPv6
+
+ socat options -4, -6 and environment variables SOCAT_DEFAULT_LISTEN_IP,
+ SOCAT_PREFERRED_RESOLVE_IP for control of protocol selection
+
+ addresses ssl, ssl-l, socks, proxy now support IPv4 and IPv6
+
+ option protocol-family (pf), esp. for openssl-listen
+
+ range option supports IPv6 - syntax: range=[::1/128]
+
+ option ipv6-v6only (ipv6only)
+
+ new tcp-wrappers options allow-table, deny-table, tcpwrap-etc
+
+ FIPS version of OpenSSL can be integrated - initial patch provided by
+ David Acker. See README.FIPS
+
+ support for resolver options res-debug, aaonly, usevc, primary, igntc,
+ recurse, defnames, stayopen, dnsrch
+
+ options for file attributes on advanced filesystems (ext2, ext3,
+ reiser): secrm, unrm, compr, ext2-sync, immutable, ext2-append, nodump,
+ ext2-noatime, journal-data etc.
+
+ option cool-write controls severeness of write failure (EPIPE,
+ ECONNRESET)
+
+ option o-noatime
+
+ socat option -lh for hostname in log output
+
+ traffic dumping provides packet headers
+
+ configure.in became part of distribution
+
+ socats unpack directory now has full version, e.g. socat-1.5.0.0/
+
+ corrected docu of option verify
+
+corrections:
+ fixed tcpwrappers integration - initial fix provided by Rudolf Cejka
+
+ exec with pipes,stderr produced error
+
+ setuid-early was ignored with many address types
+
+ some minor corrections
+
+####################### V 1.4.3.1:
+
+corrections:
+ PROBLEM: UNIX socket listen accepted only one (or a few) connections.
+ FIX: do not remove listening UNIX socket in child process
+
+ PROBLEM: SIGSEGV when TCP part of SSL connect failed
+ FIX: check ssl pointer before calling SSL_shutdown
+
+ In debug mode, show connect client port even when connect fails
+
+####################### V 1.4.3.0:
+
+new features:
+ socat options -L, -W for application level locking
+
+ options "lockfile", "waitlock" for address level locking
+ (Stefan Luethje)
+
+ option "readbytes" limits read length (Adam Osuchowski)
+
+ option "retry" for unix-connect, unix-listen, tcp6-listen (Dale Dude)
+
+ pty symlink, unix listen socket, and named pipe are per default removed
+ after use; option unlink-close overrides this new behaviour and also
+ controls removal of other socat generated files (Stefan Luethje)
+
+corrections:
+ option "retry" did not work with tcp-listen
+
+ EPIPE condition could result in a 100% CPU loop
+
+further changes:
+ support systems without SHUT_RD etc.
+ handle more size_t types
+ try to find makedepend options with gcc 3 (richard/OpenMacNews)
+
+####################### V 1.4.2.0:
+
+new features:
+ option "connect-timeout" limits wait time for connect operations
+ (requested by Giulio Orsero)
+
+ option "dhparam" for explicit Diffie-Hellman parameter file
+
+corrections:
+ support for OpenSSL DSA certificates (Miika Komu)
+
+ create install directories before copying files (Miika Komu)
+
+ when exiting on signal, return status 128+signum instead of 1
+
+ on EPIPE and ECONNRESET, only issue a warning (Santiago Garcia
+ Mantinan)
+
+ -lu could cause a core dump on long messages
+
+further changes:
+ modifications to simplify using socats features in applications
+
+####################### V 1.4.1.0:
+
+new features:
+ option "wait-slave" blocks open of pty master side until a client
+ connects, "pty-intervall" controls polling
+
+ option -h as synonym to -? for help (contributed by Christian
+ Lademann)
+
+ filan prints formatted time stamps and rdev (disable with -r)
+
+ redirect filan's output, so stdout is not affected (contributed by
+ Luigi Iotti)
+
+ filan option -L to follow symbolic links
+
+ filan shows termios control characters
+
+corrections:
+ proxy address no longer performs unsolicited retries
+
+ filan -f no longer needs read permission to analyze a file (but still
+ needs access permission to directory, of course)
+
+porting:
+ Option dsusp
+ FreeBSD options noopt, nopush, md5sig
+ OpenBSD options sack-disable, signature-enable
+ HP-UX, Solaris options abort-threshold, conn-abort-threshold
+ HP-UX options b900, b3600, b7200
+ Tru64/OSF1 options keepinit, paws, sackena, tsoptena
+
+further corrections:
+ address pty now uses ptmx as default if openpty is also available
+
+####################### V 1.4.0.3:
+
+corrections:
+ fix to a syslog() based format string vulnerability that can lead to
+ remote code execution. See advisory socat-adv-1.txt
+
+####################### V 1.4.0.2:
+
+corrections:
+ exec'd write-only addresses get a chance to flush before being killed
+
+ error handler: print notice on error-exit
+
+ filan printed wrong file type information
+
+####################### V 1.4.0.1:
+
+corrections:
+ socks4a constructed invalid header. Problem found, reported, and fixed
+ by Thomas Themel, by Peter Palfrader, and by rik
+
+ with nofork, don't forget to apply some process related options
+ (chroot, setsid, setpgid, ...)
+
+####################### V 1.4.0.0:
+
+new features:
+ simple openssl server (ssl-l), experimental openssl trust
+
+ new options "cafile", "capath", "key", "cert", "egd", and "pseudo" for
+ openssl
+
+ new options "retry", "forever", and "intervall"
+
+ option "fork" for address TCP improves `gender changer´
+
+ options "sigint", "sigquit", and "sighup" control passing of signals to
+ sub process (thanks to David Shea who contributed to this issue)
+
+ readline takes respect to the prompt issued by the peer address
+
+ options "prompt" and "noprompt" allow to override readline's new
+ default behaviour
+
+ readline supports invisible password with option "noecho"
+
+ socat option -lp allows to set hostname in log output
+
+ socat option -lu turns on microsecond resolution in log output
+
+
+corrections:
+ before reading available data, check if writing on other channel is
+ possible
+
+ tcp6, udp6: support hostname specification (not only IP address), and
+ map IP4 names to IP6 addresses
+
+ openssl client checks server certificate per default
+
+ support unidirectional communication with exec/system subprocess
+
+ try to restore original terminal settings when terminating
+
+ test.sh uses tmp dir /tmp/$USER/$$ instead of /tmp/$$
+
+ socks4 failed on platforms where long does not have 32 bits
+ (thanks to Peter Palfrader and Thomas Seyrat)
+
+ hstrerror substitute wrote wrong messages (HP-UX, Solaris)
+
+ proxy error message was truncated when answer contained multiple spaces
+
+
+porting:
+ compiles with AIX xlc, HP-UX cc, Tru64 cc (but might not link)
+
+####################### V 1.3.2.2:
+
+corrections:
+ PROXY CONNECT failed when the status reply from the proxy server
+ contained more than one consecutive spaces. Problem reported by
+ Alexandre Bezroutchko
+
+ do not SIGSEGV when proxy address fails to resolve server name
+
+ udp-listen failed on systems where AF_INET != SOCK_DGRAM (e.g. SunOS).
+ Problem reported by Christoph Schittel
+
+ test.sh only tests available features
+
+ added missing IP and TCP options in filan analyzer
+
+ do not apply stdio address options to both directions when in
+ unidirectional mode
+
+ on systems lacking /dev/*random and egd, provide (weak) entropy from
+ libc random()
+
+
+porting:
+ changes for HP-UX (VREPRINT, h_NETDB_INTERNAL)
+
+ compiles on True64, FreeBSD (again), NetBSD, OpenBSD
+
+ support for long long as st_ino type (Cygwin 1.5)
+
+ compile on systems where pty can not be featured
+
+####################### V 1.3.2.1:
+
+corrections:
+ "final" solution for the ENOCHLD problem
+
+ corrected "make strip"
+
+ default gcc debug/opt is "-O" again
+
+ check for /proc at runtime, even if configure found it
+
+ src.rpm accidently supported SuSE instead of RedHat
+
+####################### V 1.3.2.0:
+
+new features:
+ option "nofork" connects an exec'd script or program directly
+ to the file descriptors of the other address, circumventing the socat
+ transfer engine
+
+ support for files >2GB, using ftruncate64(), lseek64(), stat64()
+
+ filan has new "simple" output style (filan -s)
+
+
+porting:
+ options "binary" and "text" for controlling line termination on Cygwin
+ file system access (hint from Yang Wu-Zhou)
+
+ fix by Yang Wu-Zhou for the Cygwin "No Children" problem
+
+ improved support for OSR: _SVID3; no IS_SOCK, no F_GETOWN (thanks to
+ John DuBois)
+
+ minor corrections to avoid warnings with gcc 3
+
+
+further corrections and minor improvements:
+ configure script is generated with autoconf 2.57 (no longer 2.52)
+
+ configure passes CFLAGS to Makefile
+
+ option -??? for complete list of address options and their short forms
+
+ program name in syslog messages is derived from argv[0]
+
+ SIGHUP now prints notice instead of error
+
+ EIO during read of pty now gives Notice instead of Error, and
+ triggers EOF
+
+ use of hstrerror() for printing resolver error messages
+
+ setgrent() got required endgrent()
+
+####################### V 1.3.1.0:
+
+new features:
+ integration of Wietse Venema's tcpwrapper library (libwrap)
+
+ with "proxy" address, option "resolve" controls if hostname or IP
+ address is sent in request
+
+ option "lowport" establishes limited authorization for TCP and UDP
+ connections
+
+ improvement of .spec file for RPM creation (thanks to Gerd v. Egidy)
+ An accompanying change in the numbering scheme results in an
+ incompatibility with earlier socat RPMs!
+
+
+solved problems and bugs:
+ PROBLEM: socat daemon terminated when the address of a connecting
+ client did not match range option value instead of continue listening
+ SOLVED: in this case, print warning instead of error to keep daemon
+ active
+
+ PROBLEM: tcp-listen with fork sometimes left excessive number of zombie
+ processes
+ SOLVED: dont assume that each exiting child process generates SIGCHLD
+
+ when converting CRNL to CR, socat converted to NL
+
+
+further corrections:
+ configure script now disables features that depend on missing files
+ making it more robust in "unsupported" environments
+
+ server.pem permissions corrected to 600
+
+ "make install" now does not strip; use "make strip; make install"
+ if you like strip (suggested by Peter Bray)
+
+####################### V 1.3.0.1:
+
+solved problems and bugs:
+ PROBLEM: OPENSSL did not apply tcp, ip, and socket options
+ SOLVED: OPENSSL now correctly handles the options list
+
+ PROBLEM: CRNL to NL and CRNL to CR conversions failed when CRNL crossed
+ block boundary
+ SOLVED: these conversions now simply strip all CR's or NL's from input
+ stream
+
+
+porting:
+ SunOS ptys now work on x86, too (thanks to Peter Bray)
+
+ configure looks for freeware libs in /pkgs/lib/ (thanks to Peter Bray)
+
+
+further corrections:
+ added WITH_PROXY value to -V output
+
+ added compile dependencies of WITH_PTY and WITH_PROXY
+
+ -?? did not print option group of proxy options
+
+ corrected syntax for bind option in docu
+
+ corrected an issue with stdio in unidirectional mode
+
+ options socksport and proxyport support service names
+
+ ftp.sh script supports proxy address
+
+ man page no longer installed with execute permissions (thanks to Peter
+ Bray)
+
+ fixed a malloc call bug that could cause SIGSEGV or false "out of
+ memory" errors on EXEC and SYSTEM, depending on program name length and
+ libc.
+
+####################### V 1.3.0.0:
+
+new features:
+ proxy connect with optional proxy authentication
+
+ combined hex and text dump mode, credits to Gregory Margo
+
+ address pty applies options user, group, and perm to device
+
+
+solved problems and bugs:
+ PROBLEM: option reuseport was not applied (BSD, AIX)
+ SOLVED: option reuseport now in phase PASTSOCKET instead of PREBIND,
+ credits to Jean-Baptiste Marchand
+
+ PROBLEM: ignoreeof with stdio was ignored
+ SOLVED: ignoreeof now works correctly with address stdio
+
+ PROBLEM: ftp.sh did not use user supplied password
+ SOLVED: ftp.sh now correctly passes password from command line
+
+ PROBLEM: server.pem had expired
+ SOLVED: new server.pem valid for ten years
+
+ PROBLEM: socks notice printed wrong port on some platforms
+ SOLVED: socks now uses correct byte-order for port number in notice
+
+
+further corrections:
+ option name o_trunc corrected to o-trunc
+
+ combined use of -u and -U is now detected and prevented
+
+ made message system a little more robust against format string attacks
+
+
+####################### V 1.2.0.0:
+
+new features:
+ address pty for putting socat behind a new pseudo terminal that may
+ fake a serial line, modem etc.
+
+ experimental openssl integration
+ (it does not provide any trust between the peers because is does not
+ check certificates!)
+
+ options flock-ex, flock-ex-nb, flock-sh, flock-sh-nb to control all
+ locking mechanism provided by flock()
+
+ options setsid and setpgid now available with all address types
+
+ option ctty (controlling terminal) now available for all TERMIOS
+ addresses
+
+ option truncate (a hybrid of open(.., O_TRUNC) and ftruncate()) is
+ replaced by options o-trunc and ftruncate=offset
+
+ option sourceport now available with TCP and UDP listen addresses to
+ restrict incoming client connections
+
+ unidirectional mode right-to-left (-U)
+
+
+solved problems and bugs:
+ PROBLEM: addresses without required parameters but an option containing
+ a '/' were incorrectly interpreted as implicit GOPEN address
+ SOLVED: if an address does not have ':' separator but contains '/',
+ check if the slash is before the first ',' before assuming
+ implicit GOPEN.
+
+
+porting:
+ ptys under SunOS work now due to use of stream options
+
+
+further corrections:
+ with -d -d -d -d -D, don't print debug info during file analysis
+
+
+####################### V 1.1.0.1:
+
+new features:
+ .spec file for RPM generation
+
+
+solved problems and bugs:
+ PROBLEM: GOPEN on socket did not apply option unlink-late
+ SOLUTION: GOPEN for socket now applies group NAMED, phase PASTOPEN
+ options
+
+ PROBLEM: with unidirectional mode, an unnecessary close timeout was
+ applied
+ SOLUTION: in unidirectional mode, terminate without wait time
+
+ PROBLEM: using GOPEN on a unix domain socket failed for datagram
+ sockets
+ SOLUTION: when connect() fails with EPROTOTYPE, use a datagram socket
+
+
+further corrections:
+
+ open() flag options had names starting with "o_", now corrected to "o-"
+
+ in docu, *-listen addresses were called *_listen
+
+ address unix now called unix-connect because it does not handle unix
+ datagram sockets
+
+ in test.sh, apply global command line options with all tests
+
+
+####################### V 1.1.0.0:
+
+new features:
+ regular man page and html doc - thanks to kromJx for prototype
+
+ new address type "readline", utilizing GNU readline and history libs
+
+ address option "history-file" for readline
+
+ new option "dash" to "exec" address that allows to start login shells
+
+ syslog facility can be set per command line option
+
+ new address option "tcp-quickack", found in Linux 2.4
+
+ option -g prevents option group checking
+
+ filan and procan can print usage
+
+ procan prints rlimit infos
+
+
+solved problems and bugs:
+ PROBLEM: raw IP socket SIGSEGV'ed when it had been shut down.
+ SOLVED: set eof flag of channel on shutdown.
+
+ PROBLEM: if channel 2 uses a single non-socket FD in bidirectional mode
+ and has data available while channel 1 reaches EOF, the data is
+ lost.
+ SOLVED: during one loop run, first handle all data transfers and
+ _afterwards_ handle EOF.
+
+ PROBLEM: despite to option NONBLOCK, the connect() call blocked
+ SOLVED: option NONBLOCK is now applied in phase FD instead of LATE
+
+ PROBLEM: UNLINK options issued error when file did not exist,
+ terminating socat
+ SOLVED: failure of unlink() is only warning if errno==ENOENT
+
+ PROBLEM: TCP6-LISTEN required numeric port specification
+ SOLVED: now uses common TCP service resolver
+
+ PROBLEM: with PIPE, wrong FDs were shown for data transfer loop
+ SOLVED: retrieval of FDs now pays respect to PIPE pecularities
+
+ PROBLEM: using address EXEC against an address with IGNOREEOF, socat
+ never terminated
+ SOLVED: corrected EOF handling of sigchld
+
+
+porting:
+ MacOS and old AIX versions now have pty
+
+ flock() now available on Linux (configure check was wrong)
+
+ named pipe were generated using mknod(), which requires root under BSD
+ now they are generated using mkfifo
+
+
+further corrections:
+ lots of address options that were "forgotten" at runtime are now
+ available
+
+ option BINDTODEVICE now also called SO-BINDTODEVICE, IF
+
+ "make install" now installs binaries with ownership 0:0
+
+
+####################### V 1.0.4.2:
+
+solved problems and bugs:
+ PROBLEM: EOF of one stream caused close of other stream, giving it no
+ chance to go down regularly
+ SOLVED: EOF of one stream now causes shutdown of write part of other
+ stream
+
+ PROBLEM: sending mail via socks address to qmail showed that crlf
+ option does not work
+ SOLVED: socks address applies PH_LATE options
+
+ PROBLEM: in debug mode, no info about socat and platform was issued
+ SOLVED: print socat version and uname output in debug mode
+
+ PROBLEM: invoking socat with -t and no following parameters caused
+ SIGSEGV
+ SOLVED: -t and -b now check next argv entry
+
+ PROBLEM: when opening of logfile (-lf) failed, no error was reported
+ and no further messages were printed
+ SOLVED: check result of fopen and print error message if it failed
+
+new features:
+ address type UDP-LISTEN now supports option fork: it internally applies
+ socket option SO_REUSEADDR so a new UDP socket can bind to port after
+ `accepting´ a connection (child processes might live forever though)
+ (suggestion from Damjan Lango)
+
+
+####################### V 1.0.4.1:
+
+solved problems and bugs:
+ PROB: assert in libc caused an endless recursion
+ SOLVED: no longer catch SIGABRT
+
+ PROB: socat printed wrong verbose prefix for "right to left" packets
+ SOLVED: new parameter for xiotransfer() passes correct prefix
+
+new features:
+ in debug mode, socat prints its command line arguments
+ in verbose mode, escape special characters and replace unprintables
+ with '.'. Patch from Adrian Thurston.
+
+
+####################### V 1.0.4.0:
+
+solved problems and bugs:
+ Debug output for lstat and fstat said "stat"
+
+further corrections:
+ FreeBSD now includes libutil.h
+
+new features:
+ option setsid with exec/pty
+ option setpgid with exec/pty
+ option ctty with exec/pty
+ TCP V6 connect test
+ gettimeofday in sycls.c (no use yet)
+
+porting:
+ before Gethostbyname, invoke inet_aton for MacOSX
+
+
+####################### V 1.0.3.0:
+
+solved problems and bugs:
+
+ PROB: test 9 of test.sh (echo via file) failed on some platforms,
+ socat exited without error message
+ SOLVED: _xioopen_named_early(): preset statbuf.st_mode with 0
+
+ PROB: test 17 hung forever
+ REASON: child death before select loop did not result in EOF
+ SOLVED: check of existence of children before starting select loop
+
+ PROB: test 17 failed
+ REASON: child dead triggered EOF before last data was read
+ SOLVED: after child death, read last data before setting EOF
+
+ PROB: filan showed that exec processes incorrectly had fd3 open
+ REASON: inherited open fd3 from main process
+ SOLVED: set CLOEXEC flag on pty fd in main process
+
+ PROB: help printed "undef" instead of group "FORK"
+ SOLVED: added "FORK" to group name array
+
+ PROB: fatal messages did not include severity classifier
+ SOLVED: added "F" to severity classifier array
+
+ PROB: IP6 addresses where printed incorrectly
+ SOLVED: removed type casts to unsigned short *
+
+further corrections:
+ socat catches illegal -l modes
+ corrected error message on setsockopt(linger)
+ option tabdly is of type uint
+ correction for UDP over IP6
+ more cpp conditionals, esp. for IP6 situations
+ better handling of group NAMED options with listening UNIX sockets
+ applyopts2 now includes last given phase
+ corrected option group handling for most address types
+ introduce dropping of unappliable options (dropopts, dropopts2)
+ gopen now accepts socket and unix-socket options
+ exec and system now accept all socket and termios options
+ child process for exec and system addresses with option pty
+ improved descriptions and options for EXAMPLES
+ printf format for file mode changed to "0%03o" with length spec.
+ added va_end() in branch of msg()
+ changed phase of lock options from PASTOPEN to FD
+ support up to four early dying processes
+
+structural changes:
+ xiosysincludes now includes sysincludes.h for non xio files
+
+new features:
+ option umask
+ CHANGES file
+ TYPE_DOUBLE, u_double
+ OFUNC_OFFSET
+ added getsid(), setsid(), send() to sycls
+ procan prints sid (session id)
+ mail.sh gets -f (from) option
+ new EXAMPLEs for file creation
+ gatherinfo.sh now tells about failures
+ test.sh can check for much more address/option combinations
+
+porting:
+ ispeed, ospeed for termios on FreeBSD
+ getpgid() conditional for MacOS 10
+ added ranlib in Makefile.in for MacOS 10
+ disable pty option if no pty mechanism is available (MacOS 10)
+ now compiles and runs on MacOS 10 (still some tests fail)
+ setgroups() conditional for cygwin
+ sighandler_t defined conditionally
+ use gcc option -D_GNU_SOURCE
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..e77696a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/COPYING.OpenSSL b/COPYING.OpenSSL
new file mode 100644
index 0000000..7b93e0d
--- /dev/null
+++ b/COPYING.OpenSSL
@@ -0,0 +1,127 @@
+
+ LICENSE ISSUES
+ ==============
+
+ The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+ the OpenSSL License and the original SSLeay license apply to the toolkit.
+ See below for the actual license texts. Actually both licenses are BSD-style
+ Open Source licenses. In case of any license issues related to OpenSSL
+ please contact openssl-core@openssl.org.
+
+ OpenSSL License
+ ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
diff --git a/Config/Makefile.AIX-5-1 b/Config/Makefile.AIX-5-1
new file mode 100644
index 0000000..906b044
--- /dev/null
+++ b/Config/Makefile.AIX-5-1
@@ -0,0 +1,171 @@
+# $Id: Makefile.AIX-5-1,v 1.16 2006/07/13 21:29:05 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2006
+# 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
+
+MANDEST = ${prefix}/man
+
+srcdir = .
+
+
+CC = gcc
+CCOPTS = $(CCOPT) -Wall -Wno-parentheses
+
+SYSDEFS = -D__GNUC__=2 -D__GNUC_MINOR__=9 -D_IBMR2 -D_POWER -D_AIX -D_AIX32 -D_AIX41 -D_AIX43 -D_AIX51 -D_LONG_LONG -D_IBMR2 -D_POWER -D_AIX -D_AIX32 -D_AIX41 -D_AIX43 -D_AIX51 -D_LONG_LONG -D__CHAR_UNSIGNED__ -D_ARCH_COM
+CPPFLAGS = -I. -I/usr/local/include
+#0 INCLS = -I. @V_INCL@
+DEFS = -DHAVE_CONFIG_H
+LIBS = -L/usr/local/lib -lwrap -lbsd -L/opt/freeware/lib -lreadline -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-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-rawip.c \
+ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
+ xio-pty.c xio-openssl.c \
+ xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c
+XIOOBJS = $(XIOSRCS:.c=.o)
+UTLSRCS = error.c dalan.c procan.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 fdname.c
+OFILES = $(CFILES:.c=.o)
+PROGS = socat procan filan
+
+HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.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-system.h xio-termios.h xio-readline.h \
+ xio-pty.h xio-openssl.h \
+ xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h
+
+
+DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT socat.1 socat.html xio.help FAQ BUGREPORTS COPYING COPYING.OpenSSL
+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-4-20 Config/config.Linux-2-4-20.h \
+ Config/Makefile.AIX-5-1 Config/config.AIX-5-1.h \
+ Config/Makefile.MacOS-10-2 Config/config.MacOS-10-2.h \
+ Config/Makefile.SunOS-5-9 Config/config.SunOS-5-9.h \
+ Config/Makefile.HP-UX-B-11-11 Config/config.HP-UX-B-11-11.h \
+ Config/Makefile.FreeBSD-4-10 Config/config.FreeBSD-4-10.h \
+ Config/Makefile.FreeBSD-5-4 Config/config.FreeBSD-5-4.h \
+ Config/Makefile.OpenBSD-3-4 Config/config.OpenBSD-3-4.h \
+ Config/Makefile.Tru64-5-1B Config/config.Tru64-5-1B.h
+
+
+all: progs
+
+progs: $(PROGS)
+
+depend: $(CFILES) $(HFILES)
+ makedepend $(SYSDEFS) $(CFILES)
+
+socat: socat.o libxio.a
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS)
+
+procan: procan_main.o procan.o error.o sycls.o sysutils.o utils.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ procan_main.o procan.o error.o sycls.o sysutils.o utils.o $(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: xio.help
+#
+
+strip: progs
+ strip $(PROGS)
+
+install: progs 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 socat.1 $(DESTDIR)$(MANDEST)/man1/
+
+# 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 >socat.tar.gz
+
+socat.tar.bz2: socat.tar
+ bzip2 -9 <socat.tar >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
new file mode 100644
index 0000000..e54007e
--- /dev/null
+++ b/Config/Makefile.FreeBSD-6-1
@@ -0,0 +1,177 @@
+# $Id: Makefile.FreeBSD-6-1,v 1.2 2007/03/06 21:44:34 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2006
+# 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
+
+MANDEST = ${prefix}/man
+
+srcdir = .
+
+
+CC = gcc
+CCOPTS = $(CCOPT) -Wall -Wno-parentheses
+
+SYSDEFS = -D_LONGLONG
+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-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-rawip.c \
+ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
+ xio-pty.c xio-openssl.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
+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-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-system.h xio-termios.h xio-readline.h \
+ xio-pty.h xio-openssl.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
+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
+
+
+all: progs
+
+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 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 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/
+
+uninstall:
+ rm -f $(DESTDIR)$(BINDEST)/socat
+ rm -f $(DESTDIR)$(BINDEST)/procat
+ 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 >socat.tar.gz
+
+socat.tar.bz2: socat.tar
+ bzip2 -9 <socat.tar >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.HP-UX-B-11-11 b/Config/Makefile.HP-UX-B-11-11
new file mode 100644
index 0000000..31605b3
--- /dev/null
+++ b/Config/Makefile.HP-UX-B-11-11
@@ -0,0 +1,177 @@
+# $Id: Makefile.HP-UX-B-11-11,v 1.7 2007/03/06 21:44:34 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2006
+# 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
+
+MANDEST = ${prefix}/man
+
+srcdir = .
+
+
+CC = gcc
+CCOPTS = $(CCOPT) -Wall -Wno-parentheses
+
+SYSDEFS =
+CPPFLAGS = -I.
+#0 INCLS = -I. @V_INCL@
+DEFS = -DHAVE_CONFIG_H
+LIBS = -lssl
+LDFLAGS =
+
+INSTALL = /opt/imake/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-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-rawip.c \
+ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
+ xio-pty.c xio-openssl.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
+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-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-system.h xio-termios.h xio-readline.h \
+ xio-pty.h xio-openssl.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
+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
+
+
+all: progs
+
+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 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 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/
+
+uninstall:
+ rm -f $(DESTDIR)$(BINDEST)/socat
+ rm -f $(DESTDIR)$(BINDEST)/procat
+ 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 >socat.tar.gz
+
+socat.tar.bz2: socat.tar
+ bzip2 -9 <socat.tar >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.Linux-2-6-16 b/Config/Makefile.Linux-2-6-16
new file mode 100644
index 0000000..bdb3e60
--- /dev/null
+++ b/Config/Makefile.Linux-2-6-16
@@ -0,0 +1,177 @@
+# $Id: Makefile.Linux-2-6-16,v 1.1 2007/03/06 21:51:57 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2006
+# 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
+
+MANDEST = ${prefix}/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-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-rawip.c \
+ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
+ xio-pty.c xio-openssl.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
+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-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-system.h xio-termios.h xio-readline.h \
+ xio-pty.h xio-openssl.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
+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
+
+
+all: progs
+
+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 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 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/
+
+uninstall:
+ rm -f $(DESTDIR)$(BINDEST)/socat
+ rm -f $(DESTDIR)$(BINDEST)/procat
+ 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 >socat.tar.gz
+
+socat.tar.bz2: socat.tar
+ bzip2 -9 <socat.tar >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-2-0-2 b/Config/Makefile.NetBSD-2-0-2
new file mode 100644
index 0000000..52a888a
--- /dev/null
+++ b/Config/Makefile.NetBSD-2-0-2
@@ -0,0 +1,171 @@
+# $Id: Makefile.NetBSD-2-0-2,v 1.1 2006/07/13 21:40:28 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2006
+# 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
+
+MANDEST = ${prefix}/man
+
+srcdir = .
+
+
+CC = gcc
+CCOPTS = $(CCOPT) -Wall -Wno-parentheses
+
+SYSDEFS = -D__GNUC__=3 -D__GNUC_MINOR__=3 -D__GNUC_PATCHLEVEL__=3
+CPPFLAGS = -I.
+#0 INCLS = -I. @V_INCL@
+DEFS = -DHAVE_CONFIG_H
+LIBS = -lwrap -lutil -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-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-rawip.c \
+ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
+ xio-pty.c xio-openssl.c \
+ xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c
+XIOOBJS = $(XIOSRCS:.c=.o)
+UTLSRCS = error.c dalan.c procan.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 fdname.c
+OFILES = $(CFILES:.c=.o)
+PROGS = socat procan filan
+
+HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.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-system.h xio-termios.h xio-readline.h \
+ xio-pty.h xio-openssl.h \
+ xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h
+
+
+DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT socat.1 socat.html xio.help FAQ BUGREPORTS COPYING COPYING.OpenSSL
+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-4-20 Config/config.Linux-2-4-20.h \
+ Config/Makefile.AIX-5-1 Config/config.AIX-5-1.h \
+ Config/Makefile.MacOS-10-2 Config/config.MacOS-10-2.h \
+ Config/Makefile.SunOS-5-9 Config/config.SunOS-5-9.h \
+ Config/Makefile.HP-UX-B-11-11 Config/config.HP-UX-B-11-11.h \
+ Config/Makefile.FreeBSD-4-10 Config/config.FreeBSD-4-10.h \
+ Config/Makefile.FreeBSD-5-4 Config/config.FreeBSD-5-4.h \
+ Config/Makefile.OpenBSD-3-4 Config/config.OpenBSD-3-4.h \
+ Config/Makefile.Tru64-5-1B Config/config.Tru64-5-1B.h
+
+
+all: progs
+
+progs: $(PROGS)
+
+depend: $(CFILES) $(HFILES)
+ makedepend $(SYSDEFS) $(CFILES)
+
+socat: socat.o libxio.a
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS)
+
+procan: procan_main.o procan.o error.o sycls.o sysutils.o utils.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ procan_main.o procan.o error.o sycls.o sysutils.o utils.o $(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: xio.help
+#
+
+strip: progs
+ strip $(PROGS)
+
+install: progs 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 socat.1 $(DESTDIR)$(MANDEST)/man1/
+
+# 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 >socat.tar.gz
+
+socat.tar.bz2: socat.tar
+ bzip2 -9 <socat.tar >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-3-8 b/Config/Makefile.OpenBSD-3-8
new file mode 100644
index 0000000..5863bec
--- /dev/null
+++ b/Config/Makefile.OpenBSD-3-8
@@ -0,0 +1,171 @@
+# $Id: Makefile.OpenBSD-3-8,v 1.1 2006/07/13 21:40:31 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2006
+# 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
+
+MANDEST = ${prefix}/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-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-rawip.c \
+ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
+ xio-pty.c xio-openssl.c \
+ xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c
+XIOOBJS = $(XIOSRCS:.c=.o)
+UTLSRCS = error.c dalan.c procan.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 fdname.c
+OFILES = $(CFILES:.c=.o)
+PROGS = socat procan filan
+
+HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.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-system.h xio-termios.h xio-readline.h \
+ xio-pty.h xio-openssl.h \
+ xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h
+
+
+DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT socat.1 socat.html xio.help FAQ BUGREPORTS COPYING COPYING.OpenSSL
+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-4-20 Config/config.Linux-2-4-20.h \
+ Config/Makefile.AIX-5-1 Config/config.AIX-5-1.h \
+ Config/Makefile.MacOS-10-2 Config/config.MacOS-10-2.h \
+ Config/Makefile.SunOS-5-9 Config/config.SunOS-5-9.h \
+ Config/Makefile.HP-UX-B-11-11 Config/config.HP-UX-B-11-11.h \
+ Config/Makefile.FreeBSD-4-10 Config/config.FreeBSD-4-10.h \
+ Config/Makefile.FreeBSD-5-4 Config/config.FreeBSD-5-4.h \
+ Config/Makefile.OpenBSD-3-4 Config/config.OpenBSD-3-4.h \
+ Config/Makefile.Tru64-5-1B Config/config.Tru64-5-1B.h
+
+
+all: progs
+
+progs: $(PROGS)
+
+depend: $(CFILES) $(HFILES)
+ makedepend $(SYSDEFS) $(CFILES)
+
+socat: socat.o libxio.a
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS)
+
+procan: procan_main.o procan.o error.o sycls.o sysutils.o utils.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ procan_main.o procan.o error.o sycls.o sysutils.o utils.o $(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: xio.help
+#
+
+strip: progs
+ strip $(PROGS)
+
+install: progs 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 socat.1 $(DESTDIR)$(MANDEST)/man1/
+
+# 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 >socat.tar.gz
+
+socat.tar.bz2: socat.tar
+ bzip2 -9 <socat.tar >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-8 b/Config/Makefile.SunOS-5-8
new file mode 100644
index 0000000..82cf882
--- /dev/null
+++ b/Config/Makefile.SunOS-5-8
@@ -0,0 +1,177 @@
+# $Id: Makefile.SunOS-5-8,v 1.24 2007/03/06 21:44:34 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2006
+# 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
+
+MANDEST = ${prefix}/man
+
+srcdir = .
+
+
+CC = gcc
+CCOPTS = $(CCOPT) -Wall -Wno-parentheses
+
+SYSDEFS =
+CPPFLAGS = -I. -I/usr/local/ssl/include
+#0 INCLS = -I. @V_INCL@
+DEFS = -DHAVE_CONFIG_H
+LIBS = -lwrap -lrt -lsocket -lnsl -lresolv -lreadline -lcurses -L/usr/local/ssl/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-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-rawip.c \
+ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
+ xio-pty.c xio-openssl.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
+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-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-system.h xio-termios.h xio-readline.h \
+ xio-pty.h xio-openssl.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
+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
+
+
+all: progs
+
+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 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 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/
+
+uninstall:
+ rm -f $(DESTDIR)$(BINDEST)/socat
+ rm -f $(DESTDIR)$(BINDEST)/procat
+ 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 >socat.tar.gz
+
+socat.tar.bz2: socat.tar
+ bzip2 -9 <socat.tar >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.Tru64-5-1B b/Config/Makefile.Tru64-5-1B
new file mode 100644
index 0000000..67dac46
--- /dev/null
+++ b/Config/Makefile.Tru64-5-1B
@@ -0,0 +1,171 @@
+# $Id: Makefile.Tru64-5-1B,v 1.6 2006/07/13 21:30:05 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2006
+# 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
+
+MANDEST = ${prefix}/man
+
+srcdir = .
+
+
+CC = gcc
+CCOPTS = $(CCOPT) -Wall -Wno-parentheses
+
+SYSDEFS = -D__GNUC__=2 -D__GNUC_MINOR__=9 -Dunix -D__osf__ -D_LONGLONG -DSYSTYPE_BSD -D_SYSTYPE_BSD -D__unix__ -D__osf__ -D_LONGLONG -D__SYSTYPE_BSD__ -D_SYSTYPE_BSD -D__unix -D__SYSTYPE_BSD -D__LANGUAGE_C__ -D__LANGUAGE_C -DLANGUAGE_C -D__alpha -D__alpha__ -D__alpha_ev4__
+CPPFLAGS = -I.
+#0 INCLS = -I. @V_INCL@
+DEFS = -DHAVE_CONFIG_H
+LIBS = -lutil -lbsd -lrt -lreadline -lcurses -lssl -lcrypto
+LDFLAGS =
+
+INSTALL = /usr/local/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-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-rawip.c \
+ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
+ xio-pty.c xio-openssl.c \
+ xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c
+XIOOBJS = $(XIOSRCS:.c=.o)
+UTLSRCS = error.c dalan.c procan.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 fdname.c
+OFILES = $(CFILES:.c=.o)
+PROGS = socat procan filan
+
+HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.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-system.h xio-termios.h xio-readline.h \
+ xio-pty.h xio-openssl.h \
+ xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h
+
+
+DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT socat.1 socat.html xio.help FAQ BUGREPORTS COPYING COPYING.OpenSSL
+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-4-20 Config/config.Linux-2-4-20.h \
+ Config/Makefile.AIX-5-1 Config/config.AIX-5-1.h \
+ Config/Makefile.MacOS-10-2 Config/config.MacOS-10-2.h \
+ Config/Makefile.SunOS-5-9 Config/config.SunOS-5-9.h \
+ Config/Makefile.HP-UX-B-11-11 Config/config.HP-UX-B-11-11.h \
+ Config/Makefile.FreeBSD-4-10 Config/config.FreeBSD-4-10.h \
+ Config/Makefile.FreeBSD-5-4 Config/config.FreeBSD-5-4.h \
+ Config/Makefile.OpenBSD-3-4 Config/config.OpenBSD-3-4.h \
+ Config/Makefile.Tru64-5-1B Config/config.Tru64-5-1B.h
+
+
+all: progs
+
+progs: $(PROGS)
+
+depend: $(CFILES) $(HFILES)
+ makedepend $(SYSDEFS) $(CFILES)
+
+socat: socat.o libxio.a
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS)
+
+procan: procan_main.o procan.o error.o sycls.o sysutils.o utils.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ procan_main.o procan.o error.o sycls.o sysutils.o utils.o $(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: xio.help
+#
+
+strip: progs
+ strip $(PROGS)
+
+install: progs 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 socat.1 $(DESTDIR)$(MANDEST)/man1/
+
+# 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 >socat.tar.gz
+
+socat.tar.bz2: socat.tar
+ bzip2 -9 <socat.tar >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-1.h b/Config/config.AIX-5-1.h
new file mode 100644
index 0000000..33cf69b
--- /dev/null
+++ b/Config/config.AIX-5-1.h
@@ -0,0 +1,450 @@
+/* config.h. Generated by configure. */
+/* $Id: config.AIX-5-1.h,v 1.14 2006/07/13 21:33:50 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* 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 <sys/types.h> 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 <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> 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 <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> 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 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 hstrerror prototype */
+/* #undef HAVE_PROTOTYPE_HSTRERROR */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define if you have the <pty.h> header file. */
+/* #undef HAVE_PTY_H */
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define if you have the <netinet/ip.h> header file. */
+#define HAVE_NETINET_IP_H 1
+
+/* Define if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define if you have the <netinet/ip6.h> header file. */
+#define HAVE_NETINET_IP6_H 1
+
+/* Define if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define if you have the <sys/select.h> header file. (AIX) */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/file.h> header file. (AIX) */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <util.h> header file. (NetBSD, OpenBSD: openpty()) */
+/* #undef HAVE_UTIL_H */
+
+/* Define if you have the <libutil.h> header file. (FreeBSD: openpty()) */
+/* #undef HAVE_LIBUTIL_H */
+
+/* Define if you have the <sys/stropts.h> header file. (stream opts on SunOS)*/
+#define HAVE_SYS_STROPTS_H 1
+
+/* Define if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define if you have the <linux/ext2_fs.h> header file. */
+/* #undef HAVE_LINUX_EXT2_FS_H */
+
+/* Define if you have the <readline/readline.h> header file. */
+#define HAVE_READLINE_READLINE_H 1
+
+/* Define if you have the <readline/history.h> 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 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 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 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 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 */
+/* #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
+
+/* 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 */
+#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 7 /* long long */
+
+#define HAVE_BASIC_SOCKLEN_T 6 /* unsigned long */
+
+#define HAVE_TYPEOF_ST_DEV 4 /* unsigned int */
+#define HAVE_TYPEOF_ST_INO 4 /* unsigned int */
+#define HAVE_TYPEOF_ST_NLINK 1 /* short */
+#define HAVE_TYPEOF_ST_SIZE 5 /* long */
+#define HAVE_TYPEOF_ST_BLKSIZE 3 /* int */
+#define HAVE_TYPEOF_ST_BLOCKS 3 /* int */
+
+#define HAVE_TYPEOF_ST64_DEV 4 /* unsigned int */
+#define HAVE_TYPEOF_ST64_INO 4 /* unsigned int */
+#define HAVE_TYPEOF_ST64_NLINK 1 /* short */
+#define HAVE_TYPEOF_ST64_SIZE 7 /* long long */
+#define HAVE_TYPEOF_ST64_BLKSIZE 3 /* int */
+#define HAVE_TYPEOF_ST64_BLOCKS 3 /* int */
+
+/* #undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC */
+
+#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 */
+/* #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
+#define WITH_IP4 1
+#define WITH_IP6 1
+#define WITH_RAWIP 1
+#define WITH_TCP 1
+#define WITH_UDP 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_PTY 1
+#define WITH_EXT2 1
+#define WITH_OPENSSL 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
new file mode 100644
index 0000000..881807c
--- /dev/null
+++ b/Config/config.FreeBSD-6-1.h
@@ -0,0 +1,485 @@
+/* config.h. Generated by configure. */
+/* $Id: config.FreeBSD-6-1.h,v 1.2 2007/03/06 21:44:34 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* 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 <sys/types.h> 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 <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> 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 <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> 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 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 <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define if you have the <pty.h> header file. */
+/* #undef HAVE_PTY_H */
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define if you have the <netinet/ip.h> header file. */
+#define HAVE_NETINET_IP_H 1
+
+/* Define if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define if you have the <netinet/ip6.h> header file. */
+#define HAVE_NETINET_IP6_H 1
+
+/* Define if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
+
+/* Define if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define if you have the <linux/if_tun.h> header file. */
+/* #undef HAVE_LINUX_IF_TUN_H */
+
+/* Define if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define if you have the <sys/select.h> header file. (AIX) */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/file.h> header file. (AIX) */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <util.h> header file. (NetBSD, OpenBSD: openpty()) */
+/* #undef HAVE_UTIL_H */
+
+/* Define if you have the <libutil.h> header file. (FreeBSD: openpty()) */
+#define HAVE_LIBUTIL_H 1
+
+/* Define if you have the <sys/stropts.h> header file. (stream opts on SunOS)*/
+/* #undef HAVE_SYS_STROPTS_H */
+
+/* Define if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define if you have the <linux/fs.h> header file. */
+/* #undef HAVE_LINUX_FS_H */
+
+/* Define if you have the <linux/ext2_fs.h> header file. */
+/* #undef HAVE_LINUX_EXT2_FS_H */
+
+/* Define if you have the <readline/readline.h> header file. */
+#define HAVE_READLINE_READLINE_H 1
+
+/* Define if you have the <readline/history.h> 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 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 */
+#define HAVE_STRUCT_IFREQ_IFR_INDEX 1
+
+/* Define if you have struct ifreq.ifr_ifindex */
+/* #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 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 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 */
+/* #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 4 /* unsigned int */
+#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 3 /* int */
+#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 4 /* unsigned int */
+#define HAVE_TYPEOF_ST_NLINK 2 /* unsigned short */
+#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 */
+
+/* #undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC */
+
+#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_TCP 1
+#define WITH_UDP 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
+/* #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.HP-UX-B-11-11.h b/Config/config.HP-UX-B-11-11.h
new file mode 100644
index 0000000..a83b248
--- /dev/null
+++ b/Config/config.HP-UX-B-11-11.h
@@ -0,0 +1,485 @@
+/* config.h. Generated by configure. */
+/* $Id: config.HP-UX-B-11-11.h,v 1.7 2007/03/06 21:44:34 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* 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 <sys/types.h> 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 <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> 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 <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> 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 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 */
+/* #undef HAVE_STRTOLL */
+
+/* Define if you have the hstrerror function */
+/* #undef HAVE_HSTRERROR */
+
+/* Define if you have the inet_ntop function */
+#define HAVE_INET_NTOP 1
+
+/* Define if you have the hstrerror prototype */
+/* #undef HAVE_PROTOTYPE_HSTRERROR */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define if you have the <pty.h> header file. */
+/* #undef HAVE_PTY_H */
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define if you have the <netinet/ip.h> header file. */
+#define HAVE_NETINET_IP_H 1
+
+/* Define if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define if you have the <netinet/ip6.h> header file. */
+#define HAVE_NETINET_IP6_H 1
+
+/* Define if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
+
+/* Define if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define if you have the <linux/if_tun.h> header file. */
+/* #undef HAVE_LINUX_IF_TUN_H */
+
+/* Define if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define if you have the <sys/select.h> header file. (AIX) */
+/* #undef HAVE_SYS_SELECT_H */
+
+/* Define if you have the <sys/file.h> header file. (AIX) */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <util.h> header file. (NetBSD, OpenBSD: openpty()) */
+/* #undef HAVE_UTIL_H */
+
+/* Define if you have the <libutil.h> header file. (FreeBSD: openpty()) */
+/* #undef HAVE_LIBUTIL_H */
+
+/* Define if you have the <sys/stropts.h> header file. (stream opts on SunOS)*/
+#define HAVE_SYS_STROPTS_H 1
+
+/* Define if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define if you have the <linux/fs.h> header file. */
+/* #undef HAVE_LINUX_FS_H */
+
+/* Define if you have the <linux/ext2_fs.h> header file. */
+/* #undef HAVE_LINUX_EXT2_FS_H */
+
+/* Define if you have the <readline/readline.h> header file. */
+/* #undef HAVE_READLINE_READLINE_H */
+
+/* Define if you have the <readline/history.h> 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 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 */
+/* #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 your struct ip has ip_hl; otherwise assume ip_vhl */
+#define HAVE_STRUCT_IP_IP_HL 1
+
+/* Define if you have the setenv function */
+/* #undef HAVE_SETENV */
+
+/* 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 */
+/* #undef HAVE_TYPE_STAT64 */
+
+/* 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 5
+
+/* 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 6 /* unsigned long */
+#define HAVE_BASIC_MODE_T 2 /* unsigned short */
+#define HAVE_BASIC_PID_T 3 /* int */
+#define HAVE_BASIC_UID_T 3 /* int */
+#define HAVE_BASIC_GID_T 3 /* int */
+#define HAVE_BASIC_TIME_T 5 /* long */
+#define HAVE_BASIC_OFF64_T 7 /* long long */
+
+#define HAVE_BASIC_SOCKLEN_T 6 /* unsigned long */
+
+#define HAVE_TYPEOF_ST_DEV 3 /* int */
+#define HAVE_TYPEOF_ST_INO 6 /* unsigned long */
+#define HAVE_TYPEOF_ST_NLINK 2 /* unsigned short */
+#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 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 */
+
+/* #undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC */
+
+#define HAVE_TYPEOF_RLIM_MAX 6 /* unsigned 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_TCP 1
+#define WITH_UDP 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
+/* #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.Linux-2-6-16.h b/Config/config.Linux-2-6-16.h
new file mode 100644
index 0000000..15b8717
--- /dev/null
+++ b/Config/config.Linux-2-6-16.h
@@ -0,0 +1,485 @@
+/* config.h. Generated by configure. */
+/* $Id: config.Linux-2-6-16.h,v 1.1 2007/03/06 21:51:57 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* 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 <sys/types.h> 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 <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> 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 <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> 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 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 <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define if you have the <pty.h> header file. */
+#define HAVE_PTY_H 1
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define if you have the <netinet/ip.h> header file. */
+#define HAVE_NETINET_IP_H 1
+
+/* Define if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define if you have the <netinet/ip6.h> header file. */
+#define HAVE_NETINET_IP6_H 1
+
+/* Define if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
+
+/* Define if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define if you have the <linux/if_tun.h> header file. */
+#define HAVE_LINUX_IF_TUN_H 1
+
+/* Define if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define if you have the <sys/select.h> header file. (AIX) */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/file.h> header file. (AIX) */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <util.h> header file. (NetBSD, OpenBSD: openpty()) */
+/* #undef HAVE_UTIL_H */
+
+/* Define if you have the <libutil.h> header file. (FreeBSD: openpty()) */
+/* #undef HAVE_LIBUTIL_H */
+
+/* Define if you have the <sys/stropts.h> header file. (stream opts on SunOS)*/
+#define HAVE_SYS_STROPTS_H 1
+
+/* Define if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define if you have the <linux/fs.h> header file. */
+#define HAVE_LINUX_FS_H 1
+
+/* Define if you have the <linux/ext2_fs.h> header file. */
+#define HAVE_LINUX_EXT2_FS_H 1
+
+/* Define if you have the <readline/readline.h> header file. */
+#define HAVE_READLINE_READLINE_H 1
+
+/* Define if you have the <readline/history.h> 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 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 */
+#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 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 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 */
+
+/* #undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC */
+
+#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_TCP 1
+#define WITH_UDP 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
+/* #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-2-0-2.h b/Config/config.NetBSD-2-0-2.h
new file mode 100644
index 0000000..8b82877
--- /dev/null
+++ b/Config/config.NetBSD-2-0-2.h
@@ -0,0 +1,450 @@
+/* config.h. Generated by configure. */
+/* $Id: config.NetBSD-2-0-2.h,v 1.1 2006/07/13 21:44:07 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* 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 <sys/types.h> 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 <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> 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 <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> 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 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 hstrerror prototype */
+#define HAVE_PROTOTYPE_HSTRERROR 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define if you have the <pty.h> header file. */
+/* #undef HAVE_PTY_H */
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define if you have the <netinet/ip.h> header file. */
+#define HAVE_NETINET_IP_H 1
+
+/* Define if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define if you have the <netinet/ip6.h> header file. */
+#define HAVE_NETINET_IP6_H 1
+
+/* Define if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define if you have the <sys/select.h> header file. (AIX) */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/file.h> header file. (AIX) */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <util.h> header file. (NetBSD, OpenBSD: openpty()) */
+#define HAVE_UTIL_H 1
+
+/* Define if you have the <libutil.h> header file. (FreeBSD: openpty()) */
+/* #undef HAVE_LIBUTIL_H */
+
+/* Define if you have the <sys/stropts.h> header file. (stream opts on SunOS)*/
+/* #undef HAVE_SYS_STROPTS_H */
+
+/* Define if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define if you have the <linux/ext2_fs.h> header file. */
+/* #undef HAVE_LINUX_EXT2_FS_H */
+
+/* Define if you have the <readline/readline.h> header file. */
+#define HAVE_READLINE_READLINE_H 1
+
+/* Define if you have the <readline/history.h> header file. */
+#define HAVE_READLINE_HISTORY_H 1
+
+/* 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 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 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 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 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
+
+/* 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 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 */
+
+/* #undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC */
+
+#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
+#define WITH_IP4 1
+#define WITH_IP6 1
+#define WITH_RAWIP 1
+#define WITH_TCP 1
+#define WITH_UDP 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 */
+#define WITH_PTY 1
+#define WITH_EXT2 1
+#define WITH_OPENSSL 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-3-8.h b/Config/config.OpenBSD-3-8.h
new file mode 100644
index 0000000..14b32a8
--- /dev/null
+++ b/Config/config.OpenBSD-3-8.h
@@ -0,0 +1,450 @@
+/* config.h. Generated by configure. */
+/* $Id: config.OpenBSD-3-8.h,v 1.1 2006/07/13 21:44:11 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* 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 <sys/types.h> 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 <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> 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 <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> 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 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 hstrerror prototype */
+#define HAVE_PROTOTYPE_HSTRERROR 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define if you have the <pty.h> header file. */
+/* #undef HAVE_PTY_H */
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define if you have the <netinet/ip.h> header file. */
+#define HAVE_NETINET_IP_H 1
+
+/* Define if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define if you have the <netinet/ip6.h> header file. */
+#define HAVE_NETINET_IP6_H 1
+
+/* Define if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define if you have the <sys/select.h> header file. (AIX) */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/file.h> header file. (AIX) */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <util.h> header file. (NetBSD, OpenBSD: openpty()) */
+#define HAVE_UTIL_H 1
+
+/* Define if you have the <libutil.h> header file. (FreeBSD: openpty()) */
+/* #undef HAVE_LIBUTIL_H */
+
+/* Define if you have the <sys/stropts.h> header file. (stream opts on SunOS)*/
+/* #undef HAVE_SYS_STROPTS_H */
+
+/* Define if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define if you have the <linux/ext2_fs.h> header file. */
+/* #undef HAVE_LINUX_EXT2_FS_H */
+
+/* Define if you have the <readline/readline.h> header file. */
+#define HAVE_READLINE_READLINE_H 1
+
+/* Define if you have the <readline/history.h> 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 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 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 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 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
+
+/* 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 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 */
+
+/* #undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC */
+
+#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
+#define WITH_IP4 1
+#define WITH_IP6 1
+#define WITH_RAWIP 1
+#define WITH_TCP 1
+#define WITH_UDP 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_PTY 1
+#define WITH_EXT2 1
+#define WITH_OPENSSL 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-8.h b/Config/config.SunOS-5-8.h
new file mode 100644
index 0000000..ce9790b
--- /dev/null
+++ b/Config/config.SunOS-5-8.h
@@ -0,0 +1,485 @@
+/* config.h. Generated by configure. */
+/* $Id: config.SunOS-5-8.h,v 1.18 2007/03/06 21:44:34 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* 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 <sys/types.h> 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 <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> 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 <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> 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 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 <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define if you have the <pty.h> header file. */
+/* #undef HAVE_PTY_H */
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define if you have the <netinet/ip.h> header file. */
+#define HAVE_NETINET_IP_H 1
+
+/* Define if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define if you have the <netinet/ip6.h> header file. */
+#define HAVE_NETINET_IP6_H 1
+
+/* Define if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
+
+/* Define if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define if you have the <linux/if_tun.h> header file. */
+/* #undef HAVE_LINUX_IF_TUN_H */
+
+/* Define if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define if you have the <sys/select.h> header file. (AIX) */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/file.h> header file. (AIX) */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <util.h> header file. (NetBSD, OpenBSD: openpty()) */
+/* #undef HAVE_UTIL_H */
+
+/* Define if you have the <libutil.h> header file. (FreeBSD: openpty()) */
+/* #undef HAVE_LIBUTIL_H */
+
+/* Define if you have the <sys/stropts.h> header file. (stream opts on SunOS)*/
+#define HAVE_SYS_STROPTS_H 1
+
+/* Define if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define if you have the <linux/fs.h> header file. */
+/* #undef HAVE_LINUX_FS_H */
+
+/* Define if you have the <linux/ext2_fs.h> header file. */
+/* #undef HAVE_LINUX_EXT2_FS_H */
+
+/* Define if you have the <readline/readline.h> header file. */
+#define HAVE_READLINE_READLINE_H 1
+
+/* Define if you have the <readline/history.h> 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 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 */
+/* #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 your struct ip has ip_hl; otherwise assume ip_vhl */
+#define HAVE_STRUCT_IP_IP_HL 1
+
+/* Define if you have the setenv function */
+/* #undef HAVE_SETENV */
+
+/* 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 */
+
+/* #undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC */
+
+#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_TCP 1
+#define WITH_UDP 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
+/* #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.Tru64-5-1B.h b/Config/config.Tru64-5-1B.h
new file mode 100644
index 0000000..9d0a516
--- /dev/null
+++ b/Config/config.Tru64-5-1B.h
@@ -0,0 +1,450 @@
+/* config.h. Generated by configure. */
+/* $Id: config.Tru64-5-1B.h,v 1.5 2006/07/13 21:35:43 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* 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 <sys/types.h> 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 <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> 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 <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> 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 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 */
+/* #undef HAVE_STRTOLL */
+
+/* Define if you have the hstrerror function */
+#define HAVE_HSTRERROR 1
+
+/* Define if you have the hstrerror prototype */
+/* #undef HAVE_PROTOTYPE_HSTRERROR */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define if you have the <pty.h> header file. */
+#define HAVE_PTY_H 1
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define if you have the <netinet/ip.h> header file. */
+#define HAVE_NETINET_IP_H 1
+
+/* Define if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define if you have the <netinet/ip6.h> header file. */
+#define HAVE_NETINET_IP6_H 1
+
+/* Define if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define if you have the <sys/select.h> header file. (AIX) */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/file.h> header file. (AIX) */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <util.h> header file. (NetBSD, OpenBSD: openpty()) */
+/* #undef HAVE_UTIL_H */
+
+/* Define if you have the <libutil.h> header file. (FreeBSD: openpty()) */
+/* #undef HAVE_LIBUTIL_H */
+
+/* Define if you have the <sys/stropts.h> header file. (stream opts on SunOS)*/
+#define HAVE_SYS_STROPTS_H 1
+
+/* Define if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define if you have the <linux/ext2_fs.h> header file. */
+/* #undef HAVE_LINUX_EXT2_FS_H */
+
+/* Define if you have the <readline/readline.h> header file. */
+#define HAVE_READLINE_READLINE_H 1
+
+/* Define if you have the <readline/history.h> 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 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 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 your struct ip has ip_hl; otherwise assume ip_vhl */
+/* #undef HAVE_STRUCT_IP_IP_HL */
+
+/* Define if you have the setenv function */
+#define HAVE_SETENV 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? */
+/* #undef HAVE_TYPE_SOCKLEN */
+
+/* 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
+
+/* 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 10
+
+/* 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 */
+/* #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 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 0 /* unknown, taking default */
+
+#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 5 /* long */
+#define HAVE_TYPEOF_ST_BLKSIZE 5 /* long */
+#define HAVE_TYPEOF_ST_BLOCKS 5 /* 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 */
+
+/* #undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC */
+
+#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 */
+/* #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
+#define WITH_IP4 1
+#define WITH_IP6 1
+#define WITH_RAWIP 1
+#define WITH_TCP 1
+#define WITH_UDP 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_PTY 1
+#define WITH_EXT2 1
+#define WITH_OPENSSL 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/DEVELOPMENT b/DEVELOPMENT
new file mode 100644
index 0000000..3564ed8
--- /dev/null
+++ b/DEVELOPMENT
@@ -0,0 +1,205 @@
+
+This file should help you to add new address types and address options to
+socat.
+
+NOTE:
+socat will in future releases be split into a library "libxio" containing all
+the address stuff, useful also for many other purposes, and the socat main()
+and data shuffler. If you intend to perform major changes to the xio part and
+to publish them, please contact me before!
+
+
+ADDING A NEW ADDRESS TYPE:
+
+* Create new files xio-newaddr.c and xio-newaddr.h
+
+* Create a new record of struct addrdesc in xio-newaddr.c, with declaration in xio-newaddr.h.
+
+* Make a new entry to addressnames[] in xioopen.c with the addresses main name
+and maybe with alias names. Keep this array ASCII sorted, without uppercase
+chars.
+
+* config.h.in: #undef WITH_NEWADDR
+
+* configure.in: Copy the disable part of, e.g., WITH_SOCKS4 and adapt it to
+NEWADDR
+
+* In socat.c, add to socat_version
+
+* Write a function xioopen_newaddr() in xio-newaddr.c, declaration in
+xio-newaddr.h
+Do not forget the following option processing calls:
+All groups: _xio_openlate()
+Group FD: applyopts_cloexec()
+Group NAMED: applyopts_file() for phases PREOPEN, OPEN, and FD
+
+* Describe a tested example in file EXAMPLES, and maybe in the socat manpage
+source.
+
+* Try to define a test for this address type in test.sh
+
+* Update file CHANGES
+
+
+ADDING A NEW ADDRESS OPTION:
+
+xioopen.c:
+
+* If this option depends on a #define that is probably not available on all
+platforms, make all new code for this option dependent on the existence of this
+C header define:
+#ifdef PREFIX_NEWOPTION
+...
+#endif
+
+* Add an OPT_NEWOPTION to enum e_optcode in xioopts.h, preferably keeping
+alphabetic order
+
+* Add a struct optdesc opt_newoption record in xio-newaddr.c and its
+declaration in xio-newaddr.h. The complete structure definition must be in one
+line without breaks for automatic docu extraction.
+Build the record from the following components:
+. A canonical default name (e.g. "newoption")
+. A short, preferable name (e.g. "newopt") or NULL
+. OPT_NEWOPTION (from enum e_optcode, see above)
+. A group membership that restricts appliance of the new option to matching
+address types (e.g., one of GROUP_ANY, GROUP_IP_TCP, GROUP_EXEC)
+. A phase specification that positions this option within address processing.
+Note that the function code can override this value.
+. A representation type for option arguments (e.g., TYPE_INT, TYPE_STRING etc.;
+use TYPE_BOOL if this option just triggers an action)
+. A function or action definition for applying this option. If it does not use
+one of the standard functions (open(), ioctl(), setsockopt()...), then use
+OFUNC_SPEC (specific).
+
+* For the canonical name and all its aliases and abbreviations, add entries to
+the array optionnames in xioopts.c. KEEP STRICT ALPHABETIC (ASCII) ORDER!
+The entries must be embedded in an IF_... macro of their group for conditional
+compiling.
+
+* For options using some predefined action (see OFUNC above), this might be
+enough - test the option and document it in xio.help!
+For OFUNC_SPEC, it might suffice to add another "case" to the OFUNC_SPEC branch
+in applyopts() in xioopts.c. If you need more special handling, you should try
+to understand the address specific functions and add your code there.
+
+* If you use system or low level C library calls or library calls that might
+hang or induce problems, please invoke them with capitalized name; if no such
+name is defined, add an appropriate debug function to sycls.c, and a header
+entry and a wrapper "define" to sycls.h
+
+* Update file CHANGES
+
+
+INFO ABOUT ADDRESS PHASES:
+
+Each option entry has a field specifying a default phase for its application.
+Of course, the code that analyses and applies an address may override this
+default phase.
+
+Depending on the type of address there are several major phase sequences:
+
+
+OPEN addresses:
+
+PH_INIT retrieving info from original state
+PH_EARLY before any other processing
+PH_PREOPEN before file creation/opening (not UNIX sockets)
+PH_OPEN during file creation/opening (not UNIX sockets)
+PH_PASTOPEN past file creation/opening (not UNIX sockets)
+PH_FD soon after FD creation or identification
+PH_LATE FD is ready, before start of data loop
+PH_LATE2 FD is ready, dropping privileges
+
+
+SOCKET addresses:
+
+PH_INIT retrieving info from original state
+PH_EARLY before any other processing
+PH_PRESOCKET before socket call
+PH_SOCKET for socket call
+PH_PASTSOCKET after socket call
+PH_FD soon after FD creation or identification
+PH_PREBIND before socket bind()
+PH_BIND during socket bind()
+PH_PASTBIND past socket bind()
+PH_PRECONNECT before connect()
+PH_CONNECT during connect()
+PH_PASTCONNECT after connect()
+PH_CONNECTED phase common with listen
+PH_LATE FD is ready, before start of data loop
+PH_LATE2 FD is ready, dropping privileges
+
+
+SOCKET with LISTEN and FORK:
+
+PH_INIT retrieving info from original state
+PH_EARLY before any other processing
+PH_PRESOCKET before socket call
+PH_SOCKET for socket call
+PH_PASTSOCKET after socket call
+PH_PREBIND before socket bind()
+PH_BIND during socket bind()
+PH_PASTBIND past socket bind()
+PH_PRELISTEN before listen()
+PH_LISTEN during listen()
+PH_PASTLISTEN after listen()
+PH_PREACCEPT before accept()
+PH_ACCEPT during accept()
+PH_PASTACCEPT after accept()
+PH_FD soon after FD creation or identification
+PH_CONNECTED phase common with connect
+PH_PREFORK before forking
+PH_FORK during fork()
+PH_PASTFORK after fork()
+PH_LATE FD is ready, before start of data loop
+PH_LATE2 FD is ready, dropping privileges
+
+
+FD addresses:
+
+PH_INIT retrieving info from original state
+PH_EARLY before any other processing
+PH_FD soon after FD identification
+PH_LATE FD is ready, before start of data loop
+PH_LATE2 FD is ready, dropping privileges
+
+
+EXEC addresses:
+
+PH_INIT retrieving info from original state
+PH_EARLY before any other processing
+PH_PREBIGEN before socketpair() pipe() openpty()
+PH_BIGEN during socketpair() pipe() openpty()
+PH_PASTBIGEN past socketpair() pipe() openpty()
+PH_PASTSOCKET for socketpair()
+PH_FD soon after FD creation or identification
+PH_PREFORK before forking
+PH_FORK during fork()
+PH_PASTFORK after fork()
+PH_LATE FD is ready, before start of data loop
+PH_LATE2 FD is ready, dropping privileges
+PH_PREEXEC before exec() or system()
+PH_EXEC during exec() or system()
+
+
+There are lots of semantic relations between group, phase, and func fields of
+an option.
+
+
+There exists something like an overall phase sequence:
+PH_INIT # su-d.1
+PH_EARLY # chroot-early
+PH_PREOPEN, PH_OPEN, PH_PASTOPEN # (chroot before/after?)
+PH_PRESOCKET, PH_SOCKET, PH_PASTSOCKET # (su after (root for raw)?)
+PH_PREBIGEN, PH_BIGEN, PH_PASTBIGEN # (chroot before/after (/dev..)?)
+PH_FD
+PH_PREBIND, PH_BIND, PH_PASTBIND # (su after(before?))
+PH_PRELISTEN, PH_LISTEN, PH_PASTLISTEN
+PH_PRECONNECT, PH_CONNECT, PH_PASTCONNECT # (chroot before/after (AF_UNIX)?)
+PH_PREACCEPT, PH_ACCEPT, PH_PASTACCEPT
+PH_CONNECTED
+PH_PREFORK, PH_FORK, PH_PASTFORK # (all before/after?)
+PH_LATE # chroot
+PH_LATE2 # su, su-d.2
+PH_PREEXEC, PH_EXEC # (all before)
diff --git a/EXAMPLES b/EXAMPLES
new file mode 100644
index 0000000..57286ea
--- /dev/null
+++ b/EXAMPLES
@@ -0,0 +1,326 @@
+
+// Examples for using socat (and filan)
+
+
+//"$" means normal user, "#" requires privileges, "//" starts a comment
+
+///////////////////////////////////////////////////////////////////////////////
+// similar to netcat
+
+// connect to 10.1.1.1 on port 80 and relay to and from stdio
+$ socat - TCP:10.1.1.1:80 # similar to "netcat 10.1.1.1 80"
+
+// listen on port 25, wait for an incoming connection, use CR+NL on this
+// connection, relay data to and from stdio;
+// then emulate a mailserver by hand :-)
+# socat - TCP-LISTEN:25,crlf
+
+// listen on port 25, wait for an incoming connection, use CR+NL on this
+// connection, relay data to and from stdio, but have line editing and history;
+// then emulate a mailserver by hand :-)
+# socat readline TCP-LISTEN:25,crlf
+
+// provide a transient history enabled front end to stupid line based
+// interactive programs
+$ socat readline exec:"nslookup",pty,ctty,setsid,echo=0
+// same works for ftp (but password is not hidden)
+
+// you may also use a file based history list
+$ socat readline,history=.nslookup_hist exec:"nslookup",pty,ctty,setsid,echo=0
+// using ~ as abbreviation for $HOME does not work!
+
+// poor mans 'telnetd' replacement
+# socat tcp-l:2023,reuseaddr,fork exec:/bin/login,pty,setsid,setpgid,stderr,ctty
+// and here an appropriate client:
+$ socat -,raw,echo=0 tcp:172.16.181.130:2023
+// use ssl with client and server certificate for improved security;
+// replace /bin/login by /bin/bash when using SSL client authentication, can be
+// run without root then
+
+///////////////////////////////////////////////////////////////////////////////
+// a very primitive HTTP/1.0 echo server (problems: sends reply headers before
+// request; hangs if client does not shutdown - HTTP keep-alive)
+// wait for a connection on port 8000; do not wait for request, but immediately
+// start a shell that sends reply headers and an empty line; then echo all
+// incoming data back to client
+$ socat TCP-LISTEN:8000,crlf SYSTEM:"echo HTTP/1.0 200; echo Content-Type: text/plain; echo; cat"
+
+///////////////////////////////////////////////////////////////////////////////
+// for communicating with an attached modem, I had reasonable results with
+// following command line. Required privileges depend on device mode.
+// after leaving socat, type "sane".
+// replace /dev/ttyS0 by the correct serial line or with /dev/modem
+$ socat readline /dev/ttyS0,raw,echo=0,crlf
+// or
+$ socat readline /dev/ttyS0,raw,echo=0,crlf,nonblock
+// then enter "at$"
+
+///////////////////////////////////////////////////////////////////////////////
+// relay TCP port 80 from everywhere (internet, intranet, dmz) through your
+// firewall to your DMZ webserver (like plug-gw)
+// listen on port 80; whenever a connection is made, fork a new process (parent
+// process keeps accepting connections), su to nobody, and connect to
+// www.dmz.mydomain.org on port 80.
+// attention: this is a substitute for a reverse proxy without providing
+// application level security.
+# socat TCP-LISTEN:80,reuseaddr,fork,su=nobody TCP:www.dmz.mydomain.org:80
+// Note: parent process keeps running as root, su after forking
+
+///////////////////////////////////////////////////////////////////////////////
+// relay mail from your DMZ server through your firewall.
+// accept connections only on dmz interface and allow connections only from
+// smtp.dmz.mydomain.org.
+// the advantages over plug-gw and other relays are:
+// * you can bind to an IP address (even an alias), therefore enhance security
+// * in your OS you can create several IP aliases and bind another socat daemon
+// to each, making several application servers addressable
+// * lots of options, like switching user, chroot, IP performance tuning
+// * no need for inetd
+# socat -lm -d -d TCP-LISTEN:25,bind=fw.dmz.mydomain.org,fork,su=nobody,range=smtp.dmz.mydomain.org/32 TCP:smtp.intra.mydomain.org:25
+
+///////////////////////////////////////////////////////////////////////////////
+// convert line terminator in ascii streams, stdin to stdout
+// use unidirectional mode, convert nl to crnl
+$ socat -u - -,crlf
+// or cr to nl
+$ socat -u -,cr -
+
+// save piped data similar to 'tee':
+// copies stdin to stdout, but writes everything to the file too
+$ socat -,echo=0 open:/tmp/myfile,create,trunc,ignoreeof!!/tmp/myfile
+
+///////////////////////////////////////////////////////////////////////////////
+// intrusion testing
+
+// found an XWindow Server behind IP filters with FTP data hole? (you are
+// lucky!)
+// prepare your host:
+# rm -f /tmp/.X11-unix/X1
+// relay a pseudo display :1 on your machine to victim:0
+# socat UNIX-LISTEN:/tmp/.X11-unix/X1,fork TCP:host.victim.org:6000,sp=20 &
+// and try to take a screendump (must be very lucky - when server has not even
+// host based authentication!)
+# xwd -root -display :1 -silent >victim.xwd
+
+// you sit behind a socks firewall that has IP filters but lazily allows socks
+// connections to loopback and has only host based X11 security.
+// like above, but from your inside client:
+# socat UNIX-LISTEN:/tmp/.X11-unix/X1,fork SOCKS4:firewall:loopback:6000
+// or for the HTTP proxy:
+# socat UNIX-LISTEN:/tmp/.X11-unix/X1,fork PROXY:firewall:loopback:6000
+
+///////////////////////////////////////////////////////////////////////////////
+// forms of stdin with stdout, all equivalent
+$ socat echo -
+$ socat echo STDIO
+$ socat echo STDIN!!STDOUT
+$ socat echo STDIO!!STDIO
+$ socat echo -!!-
+$ socat echo FD:0!!FD:1
+$ socat echo 0!!1
+$ socat echo /dev/stdin!!/dev/stdout // if your OS provides these
+
+///////////////////////////////////////////////////////////////////////////////
+// some echo address examples
+$ socat - PIPE
+$ socat - PIPE:/tmp/pipi // other version of echo
+$ socat - PIPE:/tmp/pipi,nonblock!!/tmp/pipi // other version of echo
+$ socat - EXEC:/bin/cat // another echo
+$ socat - SYSTEM:/bin/cat // another echo
+$ socat - TCP:loopback:7 // if inetd echo/TCP service activated
+$ socat - UDP:loopback:7 // if inetd echo/UDP service activated
+$ socat - /tmp/hugo,trunc,ignoreeof!!/tmp/hugo // with delay
+$ socat - UDP:loopback:2000,bind=:2000 // self "connection"
+$ socat - TCP:loopback:2000,bind=:2000 // Linux bug?
+# socat - IP:loopback:222 // raw protocol, self "connected" (attention,
+// Linux might drop packets with less than 8 bytes payload)
+
+///////////////////////////////////////////////////////////////////////////////
+// unidirectional data transfer
+$ socat -u - -
+// like "tail -f", but start with showing all file contents
+$ socat -u FILE:/var/log/syslog.debug,ignoreeof -
+// like "tail -f", but do not show existing file contents
+$ socat -u FILE:/var/log/syslog.debug,ignoreeof,seek-end -
+// write to new file, create with given permission and group (must be member) - race condition with group!!!
+$ socat -u - CREATE:/tmp/outfile1,group=floppy,perm=0640
+//
+// for an existing file /tmp/outfile1
+# socat -u - FILE:/tmp/outfile1,group=floppy,perm=0700,user=4321
+
+
+///////////////////////////////////////////////////////////////////////////////
+// file handling
+$ socat - FILE:/tmp/outfile1,ignoreeof!!FILE:/tmp/outfile1,append // prints outfile1, then echoes input and protocols into file (appends to old data)
+
+///////////////////////////////////////////////////////////////////////////////
+// unix socket handling
+
+// create a listening unix socket
+$ rm -f /tmp/mysocket; socat UNIX-LISTEN:/tmp/mysocket -
+// from another terminal, connect to this socket
+$ socat UNIX:/tmp/mysocket -
+// then transfer data bidirectionally
+
+
+///////////////////////////////////////////////////////////////////////////////
+// transport examples
+
+// socks relay (externally socksify applications);
+// your ssh client and OS are not socksified, but you want to pass a socks
+// server with ssh:
+$ socat TCP-LISTEN:10022,fork SOCKS4:socks.mydomain.org:ssh-serv:22
+$ ssh -p 10022 loopback
+// or better define a ProxyCommand in ~/.ssh/config:
+ProxyCommand socat - SOCKS:socks.mydomain.org:%h:%p
+// and with proxy:
+ProxyCommand socat - PROXY:proxy.mydomain.org:%h:%p,proxyport=8000
+
+///////////////////////////////////////////////////////////////////////////////
+// application examples
+
+// run sendmail daemon with your favorite network options
+# socat TCP-LISTEN:25,fork,ip-ttl=4,ip-tos=7,tcp-maxseg=576 EXEC:"/usr/sbin/sendmail -bs",nofork
+
+// local mail delivery over UNIX socket - no SUID program required
+# socat UNIX-LISTEN:/tmp/postoffice,fork,perm-early=0666 EXEC:"/usr/sbin/sendmail -bs"
+$ socat - /tmp/postoffice
+
+///////////////////////////////////////////////////////////////////////////////
+// uses of filan
+// see what your operating system opens for you
+$ filan
+// or if that was too detailled
+$ filan -s
+// see what file descriptors are passed via exec function
+$ socat - EXEC:filan,nofork
+$ socat - EXEC:filan
+$ socat - EXEC:filan,pipes,stderr
+$ socat - EXEC:filan,pipes
+$ socat - EXEC:filan,pty
+// see what's done by your shell and with option "pipes"
+$ socat - SYSTEM:filan,pipes
+// see if gdb gives you an equivalent environment or opens some files for your program
+$ gdb ./filan
+(gdb) r
+(gdb) r -s
+
+///////////////////////////////////////////////////////////////////////////////
+// want to use chat from the ppp package?
+// note: some OS's do not need "-e" for echo to print control characters
+// note: chat might send bytes one by one
+// with AIX, a similar program is available under the name "pppdial"
+$ socat -d -d system:'/usr/sbin/chat "220 " "HELO loopback" "250 " "MAIL FROM: <hugo@localhost>" "250 " "RCPT TO: root" "250 " "DATA" "354 " "test1'$(echo -e "\r.")'" "250 " "QUIT"',pty,echo=0,cr tcp:localhost:25,crlf,nodelay
+
+//////////////////////////////////////////////////////////////////////////////
+// IP6
+
+# socat readline TCP6:::1:21 # if your inetd/ftp is listening on ip6
+
+
+///////////////////////////////////////////////////////////////////////////////
+// application server solutions
+// run a program (here: /bin/sh) chrooted, unprivileged;
+// parent process stays in real / running as root
+# socat -d -d - EXEC:/bin/sh,chroot=/home/sandbox,su=sandbox,pty
+
+// make a program available on the network chrooted, unprivileged;
+// parent process stays in / running as root
+// script path is already chrooted
+# ./socat -lm -d -d TCP-LISTEN:5555,fork EXEC:/bin/myscript,chroot=/home/sandbox,su=sandbox,pty,stderr
+// to avoid terminal problems, you might - instead of telnet - connect using
+$ socat -,icanon=0,echo=0 tcp:target:5555; reset
+
+
+// access local display from ssh server, when ssh port forwarding is disabled
+// socat must be installed on ssh server host
+// might have to use xauth...
+// this example is one-shot, because ',' cannot be passed to remote socat
+xterm1$ socat -d -d exec:"ssh target ~/bin/socat -d -d unix-l:/tmp/.X11-unix/X1 -" unix:/tmp/.X11-unix/X0
+xterm2$ ssh target
+target$ DISPLAY=:1 myxapplication
+
+// touch with perms:
+// no race condition for perms (applied with creat() call)
+$ socat -u /dev/null creat:/tmp/tempfile,perm=0600
+
+// touch with owner and perms:
+// race condition before changing owner, but who cares - only root may access
+# socat -u /dev/null creat:/tmp/tempfile,user=user1,perm=0600
+
+// invoke an interactive ssh with exec
+// first example passes control chars (^C etc.) to remote server as usual
+socat -,echo=0,raw exec:'ssh server',pty,setsid,ctty
+// second example interprets control chars on local command line
+socat -,echo=0,icanon=0 exec:'ssh server',pty,setsid,ctty
+// afterwards, type "reset"!
+
+// convince ssh to provide an "interactive" shell to your script
+// three main versions for entering password:
+// 1) from your TTY; have 10 seconds to enter password:
+(sleep 10; echo "ls"; sleep 1) |socat - exec:'ssh server',pty
+// 2) from XWindows (DISPLAY !); again 10 seconds
+(sleep 10; echo "ls"; sleep 1) |socat - exec:'ssh server',pty,setsid
+// 3) from script
+(echo PASSWORD; echo ls; sleep 1) |./socat - exec:'ssh server',pty,setsid,ctty
+
+
+// download with proxy CONNECT
+// use echo -e if required for \n
+$ (echo -e "CONNECT 128.129.130.131:80 HTTP/1.0\n"; sleep 5; echo -e "GET
+/download/file HTTP/1.0\n"; sleep 10) |socat -d -d -t 3600 - tcp:proxy:8080,crlf
+
+// retrieve a file from an sshd site with sourceforge style entry menu;
+// fill in your personal values; cat lets you enter your password (will be
+// visible on screen)
+$ (sleep 10; read pass; echo $pass; sleep 10; echo M; sleep 5; echo cat FILENAME; sleep 10) |./socat -d -d -ly - EXEC:'ssh -c 3des -l USER cf.sourceforge.net',pty,setsid,ctty |tee FILENAME
+
+// multicast community on local network: start the following command on all
+// participating hosts; like a conference call:
+# socat -d -d -d -d - udp-datagram:224.0.0.2:6666,bind=:6666,ip-add-membership=224.0.0.2:eth0,bindtodevice=eth0
+// or
+$ socat -d -d -d -d - udp-datagram:224.0.0.2:6666,bind=:6666,ip-add-membership=224.0.0.2:eth0
+// possible reasons for failure:
+// iptables or other filters (open your filters as required)
+// packets leave via wrong interface (set route: ...)
+// socket bound to specific address
+
+===============================================================================
+
+// not tested, just ideas, or have problems
+
+
+// traverse firewall for making internal telnet server accessible for outside
+// telnet client, when only outbound traffic (syn-filter) is allowed:
+// on external client run "double server". this process waits for a
+// connection from localhost on port 10023, and, when it is established, waits
+// for a connection from anywhere to port 20023:
+ext$ socat -d TCP-LISTEN:10023,range=localhost TCP-LISTEN:20023
+// on internal server run double client:
+int$ socat -d TCP:localhost:23 TCP:extclient:10023
+// or, with socks firewall:
+int$ socat -d TCP:localhost:23 SOCKS:socksserver:extclient:10023
+// login with:
+ext$ telnet localhost 20023
+
+// you can make a double server capable of handling multiple instances:
+ext$ socat -d TCP-LISTEN:10023,range=localhost,fork TCP-LISTEN:20023,reuseaddr
+
+// access remote display via ssh, when ssh port forwarding is disabled
+$ socat -d -d EXEC:"ssh target socat - UNIX:/tmp/.X11-unix/X0" TCP-LISTEN:6030
+$ xclock -display localhost:30
+
+// relay multiple webserver addresses through your firewall into your DMZ:
+// make IP aliases on your firewall, and then:
+# socat -d -d TCP-L:80,bind=fw-addr1,fork TCP:dmz-www1:80
+# socat -d -d TCP-L:80,bind=fw-addr2,fork TCP:dmz-www2:80
+// and for improved security:
+# socat -d -d TCP-L:80,bind=fw-addr3,su=nobody,fork TCP:dmz-www3:80
+
+// pass an arbitrary IP protocol through your firewall (answers won't work)
+# socat -d -d IP:0.0.0.0:150,bind=fwnonsec IP:sec-host:150,bind=fwsec
+
+// pass an unsupported IP protocol through your firewall, point to point
+// end points see firewall interfaces as IP peers!
+# socat -d -d IP:nonsec-host:150,bind=fwnonsec IP:sec-host:150,bind=fwsec
+// note that, for IPsec, you might face problems that are known with NAT
diff --git a/FAQ b/FAQ
new file mode 100644
index 0000000..66f2009
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,85 @@
+
+Q: What is the clue of socat?
+
+A: socat probably doesn't have any clue. It is more an attempt to smoothly
+integrate similar I/O features that are usually handled differently under
+UNIX.
+
+
+Q: What does the prefix XIO mean?
+
+A: XIO means "extended input/output". It is a library/API that provides a
+common way for handling files, sockets and other forms of I/O. Its advantage is
+that the application may reduce its I/O to open / read+write / close calls,
+while the user controls all I/O details (and even basic process properties) by
+packing options into the filename string. This is the basic part of socat.
+
+
+Q: Is there a Windows port of socat available?
+
+A: Try with Cygwin from http://www.cygwin.com/, or upgrade to Linux.
+
+
+Q: I succeeded to configure and make socat, but ./test.sh says something
+like:
+./test.sh: No such file or directory
+
+A: You need a bash shell, and its location must be correctly specified in the
+first line of test.sh, e.g. /usr/local/bin/bash instead of /bin/bash.
+
+
+Q: configure disables readline / openssl / libwrap support because it does not
+find an include file / the library. How can I tell configure where these files
+are?
+
+A: For include locations, use the environment variable CPPFLAGS, for library
+locations use LIBS, e.g.:
+ export CPPFLAGS="-I/home/user/ssl/include"
+ export LIBS="-L/home/user/ssl/lib"
+On some systems (SunOS), you might also need to set LD_LIBRARY_PATH:
+ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/user/ssl/lib"
+Then try again:
+ make distclean; ./configure; make
+
+
+Q: I succeeded to make socat, but the test.sh script fails for many tests.
+Is my socat build corrupt?
+
+A: Probably your socat program is ok; the tests have been developed on Linux
+2.4, and there they usually succeed.
+But the following OS differences result in errors on non Linux systems:
+ * Linux allows to bind a socket to any address of range 127.0.0.0/8, not
+ only 127.0.0.1. Some tests are built on this feature, but they might fail on
+ other systems.
+ * Your OS might have no IP6 implementation
+ * MacOS X has some difficulties, e.g. distinguishing sockets and pipes.
+ * the OpenSSL tests require OpenSSL support by socat, must have openssl in
+ $PATH, and "openssl s_server ..." needs enough entropy to generate a key.
+
+
+Q: When I specify a dual address (two partial addresses linked with "!!") on
+the command line, I get some message "event not found", and my shell history
+has the line truncated. Not even protecting the '!'s with '\' helps.
+
+A: '!' is appearently used by your shell as history expansion character. Say
+"set +H" and add this line to your (bash) profile.
+
+
+Q: On Solaris, socat was built successfully, but when started, it gets killed
+with something like "ld.so.1: ./socat: fatal: libreadline.so.4: open failed: no
+such file or directory"
+
+A: The configure script finds your libreadline, but the runtime loader
+doesn't. Add the directory where the library resides to your LD_LIBRARY_PATH
+variable, e.g.:
+ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/sfw/lib/
+ make distclean; ./configure; make
+
+
+Q: On Solaris, socat was built successfully, but when started, an assertion
+fails: "xioinitialize.c:25: failed assertion `3 << opt_crdly.arg3 == CRDLY'
+
+A: Probably, in a second attempt you set the correct LD_LIBARY_PATH for socat,
+but it had not been set during the ./configure run, or you did not "make clean"
+before running configure. Try it again:
+ make distclean; ./configure; make
diff --git a/FILES b/FILES
new file mode 100644
index 0000000..247e738
--- /dev/null
+++ b/FILES
@@ -0,0 +1,82 @@
+
+The socat distribution contains the following files:
+
+* README: an introduction to socat
+
+* FILES: a navigator through the socat distribution (this file)
+
+* EXAMPLES: a collection of simple examples how to use socat.
+
+* COPYING: what you and others are allowed to do with socat.
+
+* PORTING: instructions and tips if you want to try socat on a new platform.
+
+* BUGREPORTS: instructions what to do with problems and contributions.
+
+* SECURITY: tips if you want to use socat in a security relevant environment.
+
+* DEVELOPMENT: infos for programmers
+
+* VERSION: the version of the socat distribution, for inclusion during
+compilation
+
+* CHANGES: what happened since first public release
+
+* socat.1: man page of socat
+* socat.html: html version of man page
+* xio.help: reference manual of the address definitions (xioopen function)
+
+* daemon.sh: example shell script for running socat as TCP relay daemon
+* ftp.sh: example shell based ftp client, using socat for transport
+* mail.sh: example shell based smtp client, for execution by socat
+
+* gatherinfo.sh: shell script for gathering info about platform and socat
+implementation
+
+* server.pem: a self signed test cerificate, for self test only
+
+
+The source code system:
+
+* configure: the autoconf generated configurator script
+
+* Makefile.in: the Makefile source input to configure
+
+* config.h.in: the config.h source input to configure
+
+* Config/config.<platform>.h: sample config.h for platform.
+* Config/Makefile.<platform>: sample Makefile for platform.
+Copy the appropriate files to ./config.h and ./Makefile if configure fails
+
+* socat.c: the main C source, including option parsing, general control, and
+the data shuffler
+
+* xio-*.c, xio-*.h: the source of the different address type implementations
+with all their modes and options
+
+* xio*.c, xio*.h: the source of the xio API and xio utilities
+
+* filan.c, filan.h: file descriptor analyzer function
+
+* dalan.c, dalan.h: data language, a most primitive subset of what should
+become a language for describing/generating all kinds of binary data.
+
+* error.c, error.h: the logging subsystem
+
+* sycls.c, sycls.h: explicit system call and C library trace functions
+* sslcls.c, sslcls.h: explicit openssl call trace functions
+
+* xioconfig.h: ensures some dependencies between configure WITH defines; to be
+included immediately after config.h
+
+* sysutils.c, sysutils.h: some more general system (socket, IP) related
+functions, e.g. converting socket addresses to human readable form
+
+* utils.c, utils.h: useful additions to C library; currently memdup, binary
+search, and setenv.
+
+* mytypes.h: some types and macros I miss in C89
+
+* test.sh: an incomplete attempt to automate tests of socat
+
+* compat.h: ensure some features that might be missing on some platforms
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..4d76144
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,177 @@
+# $Id: Makefile.in,v 1.114 2007/03/06 21:52:34 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2007
+# 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 = @prefix@
+exec_prefix = @exec_prefix@
+
+BINDEST = @bindir@
+
+MANDEST = @mandir@
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+CC = @CC@
+CCOPTS = $(CCOPT) -Wall -Wno-parentheses
+
+SYSDEFS = @SYSDEFS@
+CPPFLAGS = -I. @CPPFLAGS@
+#0 INCLS = -I. @V_INCL@
+DEFS = @DEFS@
+LIBS = @LIBS@
+LDFLAGS = @LDFLAGS@
+
+INSTALL = @INSTALL@
+
+#OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) @LIBOBJS@
+
+
+#0 CFLAGS = @CFLAGS@ $(CCOPTS) $(DEFS) $(INCLS)
+CFLAGS = @CFLAGS@ $(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-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-rawip.c \
+ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
+ xio-pty.c xio-openssl.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@ @SYCLS@ @SSLCLS@
+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-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-system.h xio-termios.h xio-readline.h \
+ xio-pty.h xio-openssl.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
+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
+
+
+all: progs
+
+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 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 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/
+
+uninstall:
+ rm -f $(DESTDIR)$(BINDEST)/socat
+ rm -f $(DESTDIR)$(BINDEST)/procat
+ 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 >socat.tar.gz
+
+socat.tar.bz2: socat.tar
+ bzip2 -9 <socat.tar >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/PORTING b/PORTING
new file mode 100644
index 0000000..549df69
--- /dev/null
+++ b/PORTING
@@ -0,0 +1,72 @@
+
+DEVELOPMENT PLATFORMS
+
+Primary development platform for socat is currently SuSE Linux 8.2 with
+a 2.4.20 kernel. New features are then ported to the non-Linux platforms on the
+Sourceforge compile farm (per July 2003: SunOS 5.8 with gcc, and MacOS X 10.2),
+and AIX 5.1 with gcc. But due to limited time resources and restricted
+(non-root) access to these systems I cannot extensively test socat there.
+
+
+PORTING STEPS
+
+If you want to port socat to another operating system you will typically go
+through two phases: First, you might just try to compile and run the actual
+socat distribution (passive phase). Then, you should see if your platform
+has some nice features that are not yet used in socat, and add code for
+supporting them (active phase). At last, I encourage you to send me your
+changes so I can integrate them into the main socat distribution.
+
+
+PASSIVE PHASE:
+
+* Generate Makefile and config.h:
+ . If you have gcc, then just invoke "./configure".
+ . If you use another C compiler, configure might not work properly;
+ You will have to adapt config.h and Makefile manually.
+ Change compiler options or defines to use all features of the operating
+ system (not only ANSI-C; e.g. HP-UX: -Ae!)
+ Some practical config.<platform>.h examples have been included in the
+ Config directory of the source that might serve as starting point.
+
+* Try to "make" socat; correct the errors. If some constants are undefined,
+ please disable these parts option-dependent, not platform-dependent (use
+ #ifdef TCP_OPTION instead of #if MY_OS)
+
+* If you have big troubles compiling socat then try configure with options
+ --disable-filan --disable-sycls; this excludes some of the most system
+ dependent parts.
+
+* After successful compilation and linking, run "make test" and try some
+ examples.
+
+
+ACTIVE PHASE:
+
+* Check the man pages of your operating system for open(2), fcntl(2),
+ setsockopt(2), ioctl(2), socket(7), ip(7), tcp(7), termios etc. and the
+ include files where you find the definitions of existing options, for new
+ options and implement them - again option-dependent.
+ Places to add code for the new options:
+ . xioopts.h: enum e_optcode (sorted numerically/alphabetically by name)
+ . xio-*.c: select the appropriate address file (e.g., xio-tcp.c for
+ TCP-options) and make a record of type struct optdesc: opt_newoption
+ . xio-*.h: the declation of struct optdesc
+ . xioopts.c: add records to struct optname optionnames for all appropriate
+ names (sorted strictly ASCII for binary search)
+ . filan.c: add the option to the appropriate array (sockopts, ipopts,
+ tcpopts)
+ . socat.html, socat.1, xio.help: write a short documentation and tell which
+ platform and version implements this option
+
+* problems may occur especially:
+ . with 16 or 64 bit systems
+ . if snprintf() etc. is missing
+ . on UNIX emulations, e.g. Cygwin
+
+
+INTEGRATION
+
+* If you ported socat to another platform:
+ To let other people participate please send the modified files or a patch
+ file and the files generated by ./gatherinfo.sh to socat@dest-unreach.org.
diff --git a/README b/README
new file mode 100644
index 0000000..a30bf66
--- /dev/null
+++ b/README
@@ -0,0 +1,272 @@
+
+about
+-----
+
+socat is a relay for bidirectional data transfer between two independent data
+channels. Each of these data channels may be a file, pipe, device (serial line
+etc. or a pseudo terminal), a socket (UNIX, IP4, IP6 - raw, UDP, TCP), an
+SSL socket, proxy CONNECT connection, a file descriptor (stdin etc.), the GNU
+line editor (readline), a program, or a combination of two of these.
+These modes include generation of "listening" sockets, named pipes, and pseudo
+terminals.
+
+socat can be used, e.g., as TCP port forwarder (one-shot or daemon), as an
+external socksifier, for attacking weak firewalls, as a shell interface to UNIX
+sockets, IP6 relay, for redirecting TCP oriented programs to a serial line, to
+logically connect serial lines on different computers, or to establish a
+relatively secure environment (su and chroot) for running client or server
+shell scripts with network connections.
+
+Many options are available to refine socats behaviour:
+terminal parameters, open() options, file permissions, file and process owners,
+basic socket options like bind address, advanced socket options like IP source
+routing, linger, TTL, TOS (type of service), or TCP performance tuning.
+
+More capabilities, like daemon mode with forking, client address check,
+"tail -f" mode, some stream data processing (line terminator conversion),
+choosing sockets, pipes, or ptys for interprocess communication, debug and
+trace options, logging to syslog, stderr or file, and last but not least
+precise error messages make it a versatile tool for many different purposes.
+
+In fact, many of these features already exist in specialized tools; but until
+now, there does not seem to exists another tool that provides such a generic,
+flexible, simple and almost comprehensive (UNIX) byte stream connector.
+
+
+packages
+--------
+
+before bothering with compilers, dependencies and include files, you might
+try to get a binary distribution that matches your platform. Have a look at
+the projects home page for actual information regarding socat binary
+distributions.
+
+
+platforms
+---------
+
+socat 1.6.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
+FreeBSD 6.1 on x86
+HP-UX B 11.11 on PA-RISC with gcc
+
+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.
+
+It might well compile and run under other UNIX like operating systems.
+
+
+install
+-------
+
+Get the tarball and extract it:
+ gtar xzf socat.tar.gz
+ cd socat-1.6.0.0
+ ./configure
+ make
+ su
+ make install # installs socat, filan, and procan in /usr/local/bin
+
+For compiling socat, gcc (or egc) is recommended.
+If gcc is not available, the configure script will fail to determine
+some features; then you'd better begin with one of the Makefiles and config.h's
+from the Config directory.
+
+If you have problems with the OpenSSL library, you can apply the option
+"--disable-openssl" to configure.
+
+If you have problems with the readline library or (n)curses, you can apply the
+option "--disable-readline" to configure.
+
+If you have problems with the tcp wrappers library, you can apply the option
+"--disable-libwrap" to configure.
+
+If you still get errors or a tremendous amount of warnings you can exclude
+the features for system call tracing and file descriptor analyzing by
+applying the options "--disable-sycls --disable-filan" to configure.
+
+You still need the functions vsnprintf and snprintf that are in the GNU libc,
+but might not be available with some proprietary libc's.
+
+The configure script looks for headers and libraries of openssl, readline, and
+tcp wrappers in the OS'es standard places and in the subdirectories include/
+and lib/ of the following places:
+ /sw/
+ /usr/local/
+ /opt/freeware/
+ /usr/sfw/
+and for openssl also in:
+ /usr/local/ssl/
+In case of unexpected behaviour it is important to understand that configure
+first searches for the appropriate include file and then expects to find the
+library in the associated lib directory. That means, when e.g. a OpenSSL
+installation resides under /usr/local and there is a symbolic link from
+/usr/include/ssl/ssl.h to /usr/local/ssl/include/ssl/ssl.h, configure will find
+the /usr/include/... header and will therefore expect libssl in /usr/lib
+instead of /usr/local/...
+
+If configure does not find a header file or library but you know where it is,
+you can specify additional search locations, e.g.:
+ export LIBS="-L$HOME/lib"
+ export CPPFLAGS="-I$HOME/include"
+before running configure and make.
+
+For other operating systems, if socat does not compile without errors, refer to
+the file PORTING.
+
+
+platform specifics - redhat
+---------------------------
+
+On RedHat Linux 9.0, including openssl/ssl.h might fail due to problems with
+the krb5-devel package. configure reacts with disabling openssl integration.
+To solve this issue, help cpp to find the krb5.h include file:
+CPPFLAGS="-I/usr/kerberos/include" ./configure
+
+
+platform specifics - aix
+------------------------
+
+The flock() prototype is not available but the function is. Thus, to enable the
+socat flock options, run configure and then change in config.h the line
+/* #undef HAVE_FLOCK */
+to
+#define HAVE_FLOCK 1
+and continue the build process.
+
+When using the OpenSSL rpm provided by IBM, configure might need the
+environment variable setting:
+LIBS="-L/opt/freeware/lib"
+
+When using the OpenSSL bundle provided by IBM, egd needs to be installed too
+to get enough entropy.
+
+socat compiles not only with gcc, but also with xlc. Just adapt the Makefile:
+replace gcc by /usr/vac/bin/xlc and remove gcc specific options
+"-Wall -Wno-parentheses".
+
+When linking with the OpenSSL library provided by IBM, errors may occur:
+ld: 0711-317 ERROR: Undefined symbol: .__umoddi3
+In this case, you need to link with libgcc or compile libcrypt yourself using
+xlc, or disable SSL (in config.h, undefine WITH_OPENSSL and recompile)
+
+The score of test.sh can be improved by uncommenting MISCDELAY=1 in this
+script.
+
+
+platform specifics - solaris
+----------------------------
+
+If libreadline or libssl are in a directory not searched by the loader per
+default, e.g. /opt/sfw/lib, you must add this directory to $LD_LIBRARY_PATH,
+for running both configure and the socat executables, e.g.:
+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.
+
+
+platform specifics - hp-ux
+--------------------------
+
+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
+system addresses.
+
+This OS provides the type "long long", but not the strtoll() function to read
+data into a long long variable.
+
+UNIX domain sockets are only supported with SOCK_STREAM, not with datagrams
+(see man 7 unix).
+
+With UDP sockets it seems to happen that the select() call reports available
+data (or EOF) but a subsequent read() call hangs.
+
+
+platform specifics - tru64
+--------------------------
+
+When the use of the readline address fails with an error like:
+socat: /sbin/loader: Fatal Error: Reference to unresolvable symbol "tgetent" in ".../libreadline.so.4"
+and you still want to use shared libraries, try the following workaround:
+$ make distclean; LIBS="-static" ./configure
+remove the "-static" occurrence in Makefile
+$ make
+
+
+documentation
+-------------
+
+These files reside in the doc subdirectory:
+
+socat.1 is the man page, socat.html is the HTML based man page. It is actual,
+but describes only the more useful options.
+
+xio.help is an older, but more exact description in text form; with socat
+version 1.6.0 it is outdated.
+
+doc/socat-openssltunnel.html is a simple tutorial for a private SSL connection.
+doc/socat-multicast.html is a short tutorial for multicast and broadcast
+communications.
+doc/socat-tun shows how to build a virtual network between two hosts.
+
+
+license
+-------
+
+socat is distributed under the terms of the GNU GPL;
+except for install-sh, which is copyright MIT, with its own license;
+
+In addition, as a special exception, the copyright holder
+gives permission to link the code of this program with
+any version of the OpenSSL library which is distributed
+under a license identical to that listed in the included
+COPYING.OpenSSL file, and distribute linked combinations
+including the two. You must obey the GNU General Public
+License in all respects for all of the code used other
+than OpenSSL. If you modify this file, you may extend this
+exception to your version of the file, but you are not
+obligated to do so. If you do not wish to do so, delete
+this exception statement from your version.
+
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, version 2 of the License
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+contact
+-------
+
+For questions, bug reports, ideas, contributions etc. please contact
+socat@dest-unreach.org
+
+For socat source distribution, bug fixes, and latest news see
+ http://www.dest-unreach.org/socat/
+
+www.socat.org is an alternate site providing the same contents.
+
diff --git a/README.FIPS b/README.FIPS
new file mode 100644
index 0000000..0452844
--- /dev/null
+++ b/README.FIPS
@@ -0,0 +1,67 @@
+
+David Acker has patched socat to add OpenSSL FIPS.
+See http://oss-institute.org/fips-faq.html and
+http://linuxdevices.com/news/NS4742716157.html for more information.
+
+The patch that is integrated into socat 1.5 does the following:
+
+Add support for LDFLAGS in Makefile. LDFLAGS can be specified on the
+configure command line and then will be carried over into the make.
+
+Add fips support. Requires OpenSSL 0.9.7j-fips-dev from
+http://www.openssl.org/source/OpenSSL-fips-1.0.tar.gz built with fips
+support turned on. use ./Configure fips [os-arc], for example
+./Configure fips linux-pentium
+
+The LDFLAGS is needed to point a build against a library
+located in a non-standard location. For example, if you download and
+build openssl manually, it gets installed in /usr/local/ssl by default.
+
+The FIPS support patches involve adding an option to enable/disable fips
+in configure (enabled by default), checking the system for FIPS support
+during configure, and then adding a fips option to socats openssl address
+to turn on fips mode. The openssl binary uses an environment variable
+instead of a command line flag.
+FIPS mode requires both a compile time flag of OPENSSL_FIPS and a
+runtime call of FIPS_mode_set(1). Fips mode requires building with the
+fipsld script provided by OpenSSL. FIPS tracks the pid of the process that
+initializes things so after a fork, the child must reinitialize. When the
+ssl code detects a forks occur and if FIPS mode was enabled, it reinitializes
+FIPS by disabling and then enabling it again.
+
+To produce Davids enviroment, do the following:
+To build openssl
+download OpenSSL 0.9.7j-fips-dev from
+http://www.openssl.org/source/OpenSSL-fips-1.0.tar.gz
+tar xzf OpenSSL-fips-1.0.tar.gz
+cd openssl
+./Configure fips linux-pentium
+make
+make test
+(become root)
+make install
+This leaves an install in /usr/local/ssl
+
+To build socat:
+setup directory with socat 1.5 or higher.
+cd socat-1.5.0.0
+./configure CPPFLAGS=-I/usr/local/ssl/include/ LDFLAGS=-L/usr/local/ssl/lib/ FIPSLD=/usr/local/ssl/bin/fipsld
+make
+(become root)
+make install
+
+To run tests we make sure the new openssl is used:
+
+export PATH=/usr/local/ssl/bin:$PATH
+./test.sh fips
+
+There are two tests in test.sh that depend on fips:
+
+OPENSSL_FIPS_BOTHAUTH performs a SSL client to server connection with
+certificate based authentication in both directions. If it works FIPS mode
+seems to be ok.
+
+OPENSSL_FIPS_SECURITY generates a certificaet/key pair without fips support. It
+then tries a SSL connection in "normal" mode which is expected to work. In the
+second phase it uses fips mode with these credentials which is expected to
+fail. If so, the test succeeded.
diff --git a/SECURITY b/SECURITY
new file mode 100644
index 0000000..0e10075
--- /dev/null
+++ b/SECURITY
@@ -0,0 +1,41 @@
+
+Tips for using socat in secured environments:
+
+* Configure socat to only enable the required features, e.g. to protect your
+ filesystem from any accesses through socat:
+ make distclean
+ ./configure --disable-file --disable-creat --disable-gopen \
+ --disable-pipe --disable-unix --disable-exec --disable-system
+ use "socat -V" to see what features are still enabled; see
+ ./configure --help for more options to disable
+
+* Do NOT install socat SUID root or so when you have untrusted users or
+unprivileged daemons on your machine, because the full install of socat can
+override arbitrary files and execute arbitrary programs!
+
+* Set logging to "-d -d" (in special cases even higher)
+
+* With files, protect against symlink attacks with nofollow (Linux), and
+avoid accessing files in world-writable directories like /tmp
+
+* When listening, use bind option (except UNIX domain sockets)
+
+* When listening, use range option (currently only for IP4 sockets)
+
+* When using socat with system, exec, or in a shell script, know what you do
+
+* With system and exec, use absolute pathes or set the path option
+
+* When starting programs with socat, consider using the chroot option (this
+requires root, so use the substuser option too).
+
+* Start socat as root only if required; if so, use substuser option
+Note: starting a SUID program after applying substuser or setuid gives the
+process the SUID owner, which might give root privileges again.
+
+* Socat, like netcat, is what intruders like to have on their victims machine:
+once they have gained a toehold they try to establish a versatile connection
+back to their attack base, and they want to attack other systems. For both
+purposes, socat could be helpful. Therefore, it might be useful to install
+socat with owner/permissions root:socatgrp/750, and to make all trusted users
+members of group socatgrp.
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..32c65da
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+"1.6.0.0"
diff --git a/compat.h b/compat.h
new file mode 100644
index 0000000..21f4200
--- /dev/null
+++ b/compat.h
@@ -0,0 +1,640 @@
+/* $Id: compat.h,v 1.32 2006/06/19 20:28:52 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __compat_h_included
+#define __compat_h_included 1
+
+/*****************************************************************************/
+/* I dont like this system dependent part, but it would be quit a challenge for
+ configure */
+
+/* define if the following does not work:
+ socket()
+ connect() -> Connection refused
+ connect() -> ok
+ instead, it needs close() and socket() between the two connect() attmpts: */
+#if __FreeBSD__ || __APPLE__ || _AIX || __hpux__ || __osf__
+# undef SOCKET_CAN_RECOVER
+#else
+# define SOCKET_CAN_RECOVER 1
+#endif
+
+/* define if stat() says that pipes are sockets */
+#if __APPLE__
+# define PIPE_STATES_SOCKET 1
+#else
+# undef PIPE_STATES_SOCKET
+#endif
+
+/*****************************************************************************/
+
+/* substitute some features that might be missing on some platforms */
+
+#ifndef SHUT_RD
+# define SHUT_RD 0
+#endif
+#ifndef SHUT_WR
+# define SHUT_WR 1
+#endif
+#ifndef SHUT_RDWR
+# define SHUT_RDWR 2
+#endif
+
+#ifndef MIN
+# define MIN(x,y) ((x)<=(y)?(x):(y))
+#endif
+
+#ifndef MAX
+# define MAX(x,y) ((x)>=(y)?(x):(y))
+#endif
+
+/* O_ASYNC: Linux 2.2.10 */
+#if !defined(O_ASYNC) && defined(FASYNC)
+# define O_ASYNC FASYNC
+#endif
+
+/* NGROUPS not defined on Solaris */
+#if !defined(NGROUPS) && defined(NGROUPS_MAX)
+# define NGROUPS NGROUPS_MAX
+#endif
+
+/* UNIX_PATH_MAX: AIX 4.3.3 */
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX 104 /*! why 104? Linux: 108 ! */
+#endif
+
+
+/* SOL_IP: AIX 4.3.3 */
+#ifndef SOL_IP
+# define SOL_IP 0
+#endif
+
+/* SOL_TCP: AIX 4.3.3 */
+#ifndef SOL_TCP
+# define SOL_TCP IPPROTO_TCP
+#endif
+
+/* POSIX.1 doesn't seem to know sockets */
+#ifndef S_ISSOCK
+# define S_ISSOCK(fmode) 0
+#endif
+
+#if defined(IPPROTO_IPV6) && !defined(SOL_IPV6)
+# define SOL_IPV6 IPPROTO_IPV6
+#endif
+
+/* all unsigned */
+#if !defined(HAVE_BASIC_SIZE_T) || !HAVE_BASIC_SIZE_T
+# undef HAVE_BASIC_SIZE_T
+# define HAVE_BASIC_SIZE_T 6
+#endif
+#if HAVE_BASIC_SIZE_T==2
+# define SIZET_MAX USHRT_MAX
+# define SSIZET_MIN SHRT_MIN
+# define SSIZET_MAX SHRT_MAX
+# define F_Zd "%hd"
+# define F_Zu "%hu"
+#elif HAVE_BASIC_SIZE_T==4
+# define SIZET_MAX UINT_MAX
+# define SSIZET_MIN INT_MIN
+# define SSIZET_MAX INT_MAX
+# define F_Zd "%d"
+# define F_Zu "%u"
+#elif HAVE_BASIC_SIZE_T==6
+# define SIZET_MAX ULONG_MAX
+# define SSIZET_MIN LONG_MIN
+# define SSIZET_MAX LONG_MAX
+# define F_Zd "%ld"
+# define F_Zu "%lu"
+#elif HAVE_BASIC_SIZE_T==8
+# define SIZET_MAX ULLONG_MAX
+# define SSIZET_MIN LLONG_MIN
+# define SSIZET_MAX LLONG_MAX
+# define F_Zd "%Ld"
+# define F_Zu "%Lu"
+#else
+# error "HAVE_BASIC_SIZE_T is out of range:" HAVE_BASIC_SIZE_T
+#endif
+#if HAVE_FORMAT_Z
+# undef F_Zd
+# undef F_Zu
+# define F_Zd "%Zd"
+# define F_Zu "%Zu"
+#endif
+
+
+/* mode_t is always unsigned; default: unsigned int */
+#if !defined(HAVE_BASIC_MODE_T) || !HAVE_BASIC_MODE_T
+# undef HAVE_BASIC_MODE_T
+# define HAVE_BASIC_MODE_T 4
+#endif
+#ifndef F_mode
+# if HAVE_BASIC_MODE_T==1 || HAVE_BASIC_MODE_T==2
+#define F_mode "0%03ho"
+# elif HAVE_BASIC_MODE_T==3 || HAVE_BASIC_MODE_T==4
+#define F_mode "0%03o"
+# elif HAVE_BASIC_MODE_T==5 || HAVE_BASIC_MODE_T==6
+#define F_mode "0%03lo"
+# else
+#error "HAVE_BASIC_MODE_T is out of range:" HAVE_BASIC_MODE_T
+# endif
+#endif
+
+
+/* default: unsigned int */
+#if !defined(HAVE_BASIC_PID_T) || !HAVE_BASIC_PID_T
+# undef HAVE_BASIC_PID_T
+# define HAVE_BASIC_PID_T 4
+#endif
+#ifndef F_pid
+# if HAVE_BASIC_PID_T==1
+#define F_pid "%hd"
+# elif HAVE_BASIC_PID_T==2
+#define F_pid "%hu"
+# elif HAVE_BASIC_PID_T==3
+#define F_pid "%d"
+# elif HAVE_BASIC_PID_T==4
+#define F_pid "%u"
+# elif HAVE_BASIC_PID_T==5
+#define F_pid "%ld"
+# elif HAVE_BASIC_PID_T==6
+#define F_pid "%lu"
+# else
+#error "HAVE_BASIC_PID_T is out of range:" HAVE_BASIC_PID_T
+# endif
+#endif
+
+
+/* default: unsigned int */
+#if !defined(HAVE_BASIC_UID_T) || !HAVE_BASIC_UID_T
+# undef HAVE_BASIC_UID_T
+# define HAVE_BASIC_UID_T 4
+#endif
+#ifndef F_uid
+# if HAVE_BASIC_UID_T==1
+#define F_uid "%hd"
+# elif HAVE_BASIC_UID_T==2
+#define F_uid "%hu"
+# elif HAVE_BASIC_UID_T==3
+#define F_uid "%d"
+# elif HAVE_BASIC_UID_T==4
+#define F_uid "%u"
+# elif HAVE_BASIC_UID_T==5
+#define F_uid "%ld"
+# elif HAVE_BASIC_UID_T==6
+#define F_uid "%lu"
+# else
+#error "HAVE_BASIC_UID_T is out of range:" HAVE_BASIC_UID_T
+# endif
+#endif
+
+
+/* default: unsigned int */
+#if !defined(HAVE_BASIC_GID_T) || !HAVE_BASIC_GID_T
+# undef HAVE_BASIC_GID_T
+# define HAVE_BASIC_GID_T 4
+#endif
+#ifndef F_gid
+# if HAVE_BASIC_GID_T==1
+#define F_gid "%hd"
+# elif HAVE_BASIC_GID_T==2
+#define F_gid "%hu"
+# elif HAVE_BASIC_GID_T==3
+#define F_gid "%d"
+# elif HAVE_BASIC_GID_T==4
+#define F_gid "%u"
+# elif HAVE_BASIC_GID_T==5
+#define F_gid "%ld"
+# elif HAVE_BASIC_GID_T==6
+#define F_gid "%lu"
+# else
+#error "HAVE_BASIC_GID_T is out of range:" HAVE_BASIC_GID_T
+# endif
+#endif
+
+
+/* all signed; default: long */
+#if !defined(HAVE_BASIC_TIME_T) || !HAVE_BASIC_TIME_T
+# undef HAVE_BASIC_TIME_T
+# define HAVE_BASIC_TIME_T 5
+#endif
+#ifndef F_time
+# if HAVE_BASIC_TIME_T==1
+#define F_time "%hd"
+# elif HAVE_BASIC_TIME_T==2
+#define F_time "%hu"
+# elif HAVE_BASIC_TIME_T==3
+#define F_time "%d"
+# elif HAVE_BASIC_TIME_T==4
+#define F_time "%u"
+# elif HAVE_BASIC_TIME_T==5
+#define F_time "%ld"
+# elif HAVE_BASIC_TIME_T==6
+#define F_time "%lu"
+# else
+#error "HAVE_BASIC_TIME_T is out of range:" HAVE_BASIC_TIME_T
+# endif
+#endif
+
+
+/* default: int */
+#if !defined(HAVE_BASIC_SOCKLEN_T) || !HAVE_BASIC_SOCKLEN_T
+# undef HAVE_BASIC_SOCKLEN_T
+# define HAVE_BASIC_SOCKLEN_T 3
+#endif
+#ifndef F_socklen
+# if HAVE_BASIC_SOCKLEN_T==1
+#define F_socklen "%hd"
+# elif HAVE_BASIC_SOCKLEN_T==2
+#define F_socklen "%hu"
+# elif HAVE_BASIC_SOCKLEN_T==3
+#define F_socklen "%d"
+# elif HAVE_BASIC_SOCKLEN_T==4
+#define F_socklen "%u"
+# elif HAVE_BASIC_SOCKLEN_T==5
+#define F_socklen "%ld"
+# elif HAVE_BASIC_SOCKLEN_T==6
+#define F_socklen "%lu"
+# else
+#error "HAVE_BASIC_SOCKLEN_T is out of range:" HAVE_BASIC_SOCKLEN_T
+# endif
+#endif
+
+/* might be checked in later versions */
+#ifndef F_off
+#define F_off "%ld"
+#endif
+
+/* default: long long */
+#if !defined(HAVE_BASIC_OFF64_T) || !HAVE_BASIC_OFF64_T
+# undef HAVE_BASIC_OFF64_T
+# define HAVE_BASIC_OFF64_T 7
+#endif
+#ifndef F_off64
+# if HAVE_BASIC_OFF64_T==1
+#define F_off64 "%hd"
+# elif HAVE_BASIC_OFF64_T==2
+#define F_off64 "%hu"
+# elif HAVE_BASIC_OFF64_T==3
+#define F_off64 "%d"
+# elif HAVE_BASIC_OFF64_T==4
+#define F_off64 "%u"
+# elif HAVE_BASIC_OFF64_T==5
+#define F_off64 "%ld"
+# elif HAVE_BASIC_OFF64_T==6
+#define F_off64 "%lu"
+# elif HAVE_BASIC_OFF64_T==7
+#define F_off64 "%Ld"
+# elif HAVE_BASIC_OFF64_T==8
+#define F_off64 "%Lu"
+# else
+#error "HAVE_BASIC_OFF64_T is out of range:" HAVE_BASIC_OFF64_T
+# endif
+#endif
+
+
+/* all unsigned; default: unsigned long */
+#if !defined(HAVE_TYPEOF_ST_DEV) || !HAVE_TYPEOF_ST_DEV
+# undef HAVE_TYPEOF_ST_DEV
+# define HAVE_TYPEOF_ST_DEV 6
+#endif
+#ifndef F_st_dev
+# if HAVE_TYPEOF_ST_DEV==1
+#define F_st_dev "%hd"
+# elif HAVE_TYPEOF_ST_DEV==2
+#define F_st_dev "%hu"
+# elif HAVE_TYPEOF_ST_DEV==3
+#define F_st_dev "%d"
+# elif HAVE_TYPEOF_ST_DEV==4
+#define F_st_dev "%u"
+# elif HAVE_TYPEOF_ST_DEV==5
+#define F_st_dev "%ld"
+# elif HAVE_TYPEOF_ST_DEV==6
+#define F_st_dev "%lu"
+# elif HAVE_TYPEOF_ST_DEV==7
+#define F_st_dev "%Ld"
+# elif HAVE_TYPEOF_ST_DEV==8
+#define F_st_dev "%Lu"
+# else
+#error "HAVE_TYPEOF_ST_DEV is out of range:" HAVE_TYPEOF_ST_DEV
+# endif
+#endif
+
+/* all unsigned; default; unsigned long */
+#if !defined(HAVE_TYPEOF_ST_INO) || !HAVE_TYPEOF_ST_INO
+# undef HAVE_TYPEOF_ST_INO
+# define HAVE_TYPEOF_ST_INO 6
+#endif
+#ifndef F_st_ino
+# if HAVE_TYPEOF_ST_INO==1
+#define F_st_ino "%hd"
+# elif HAVE_TYPEOF_ST_INO==2
+#define F_st_ino "%hu"
+# elif HAVE_TYPEOF_ST_INO==3
+#define F_st_ino "%d"
+# elif HAVE_TYPEOF_ST_INO==4
+#define F_st_ino "%u"
+# elif HAVE_TYPEOF_ST_INO==5
+#define F_st_ino "%ld"
+# elif HAVE_TYPEOF_ST_INO==6
+#define F_st_ino "%lu"
+# elif HAVE_TYPEOF_ST_INO==7 /* Cygwin 1.5 */
+#define F_st_ino "%Ld"
+# elif HAVE_TYPEOF_ST_INO==8
+#define F_st_ino "%Lu"
+# else
+#error "HAVE_TYPEOF_ST_INO is out of range:" HAVE_TYPEOF_ST_INO
+# endif
+#endif
+
+/* all unsigned; default; unsigned long long */
+#if !defined(HAVE_TYPEOF_ST64_INO) || !HAVE_TYPEOF_ST64_INO
+# undef HAVE_TYPEOF_ST64_INO
+# define HAVE_TYPEOF_ST64_INO 8
+#endif
+#ifndef F_st64_ino
+# if HAVE_TYPEOF_ST64_INO==1
+#define F_st64_ino "%hd"
+# elif HAVE_TYPEOF_ST64_INO==2
+#define F_st64_ino "%hu"
+# elif HAVE_TYPEOF_ST64_INO==3
+#define F_st64_ino "%d"
+# elif HAVE_TYPEOF_ST64_INO==4
+#define F_st64_ino "%u"
+# elif HAVE_TYPEOF_ST64_INO==5
+#define F_st64_ino "%ld"
+# elif HAVE_TYPEOF_ST64_INO==6
+#define F_st64_ino "%lu"
+# elif HAVE_TYPEOF_ST64_INO==7
+#define F_st64_ino "%Ld"
+# elif HAVE_TYPEOF_ST64_INO==8
+#define F_st64_ino "%Lu"
+# else
+#error "HAVE_TYPEOF_ST64_INO is out of range:" HAVE_TYPEOF_ST64_INO
+# endif
+#endif
+
+/* default: unsigned short */
+#if !defined(HAVE_TYPEOF_ST_NLINK) || !HAVE_TYPEOF_ST_NLINK
+# undef HAVE_TYPEOF_ST_NLINK
+# define HAVE_TYPEOF_ST_NLINK 2
+#endif
+#ifndef F_st_nlink
+# if HAVE_TYPEOF_ST_NLINK==1
+#define F_st_nlink "%hd"
+# elif HAVE_TYPEOF_ST_NLINK==2
+#define F_st_nlink "%hu"
+# elif HAVE_TYPEOF_ST_NLINK==3
+#define F_st_nlink "%d"
+# elif HAVE_TYPEOF_ST_NLINK==4
+#define F_st_nlink "%u"
+# elif HAVE_TYPEOF_ST_NLINK==5
+#define F_st_nlink "%ld"
+# elif HAVE_TYPEOF_ST_NLINK==6
+#define F_st_nlink "%lu"
+# else
+#error "HAVE_TYPEOF_ST_NLINK is out of range:" HAVE_TYPEOF_ST_NLINK
+# endif
+#endif
+
+/* all signed; default: long */
+#if !defined(HAVE_TYPEOF_ST_SIZE) || !HAVE_TYPEOF_ST_SIZE
+# undef HAVE_TYPEOF_ST_SIZE
+# define HAVE_TYPEOF_ST_SIZE 5
+#endif
+#ifndef F_st_size
+# if HAVE_TYPEOF_ST_SIZE==1
+#define F_st_size "%hd"
+# elif HAVE_TYPEOF_ST_SIZE==2
+#define F_st_size "%hu"
+# elif HAVE_TYPEOF_ST_SIZE==3
+#define F_st_size "%d"
+# elif HAVE_TYPEOF_ST_SIZE==4
+#define F_st_size "%u"
+# elif HAVE_TYPEOF_ST_SIZE==5
+#define F_st_size "%ld"
+# elif HAVE_TYPEOF_ST_SIZE==6
+#define F_st_size "%lu"
+# elif HAVE_TYPEOF_ST_SIZE==7
+#define F_st_size "%Ld"
+# elif HAVE_TYPEOF_ST_SIZE==8
+#define F_st_size "%Lu"
+# else
+#error "HAVE_TYPEOF_ST_SIZE is out of range:" HAVE_TYPEOF_ST_SIZE
+# endif
+#endif
+
+/* all signed; default: long long */
+#if !defined(HAVE_TYPEOF_ST64_SIZE) || !HAVE_TYPEOF_ST64_SIZE
+# undef HAVE_TYPEOF_ST64_SIZE
+# define HAVE_TYPEOF_ST64_SIZE 7
+#endif
+#ifndef F_st64_size
+# if HAVE_TYPEOF_ST64_SIZE==1
+#define F_st64_size "%hd"
+# elif HAVE_TYPEOF_ST64_SIZE==2
+#define F_st64_size "%hu"
+# elif HAVE_TYPEOF_ST64_SIZE==3
+#define F_st64_size "%d"
+# elif HAVE_TYPEOF_ST64_SIZE==4
+#define F_st64_size "%u"
+# elif HAVE_TYPEOF_ST64_SIZE==5
+#define F_st64_size "%ld"
+# elif HAVE_TYPEOF_ST64_SIZE==6
+#define F_st64_size "%lu"
+# elif HAVE_TYPEOF_ST64_SIZE==7
+#define F_st64_size "%Ld"
+# elif HAVE_TYPEOF_ST64_SIZE==8
+#define F_st64_size "%Lu"
+# else
+#error "HAVE_TYPEOF_ST64_SIZE is out of range:" HAVE_TYPEOF_ST64_SIZE
+# endif
+#endif
+
+/* very different results; default: long */
+#if !defined(HAVE_TYPEOF_ST_BLKSIZE) || !HAVE_TYPEOF_ST_BLKSIZE
+# undef HAVE_TYPEOF_ST_BLKSIZE
+# define HAVE_TYPEOF_ST_BLKSIZE 5
+#endif
+#ifndef F_st_blksize
+# if HAVE_TYPEOF_ST_BLKSIZE==1
+#define F_st_blksize "%hd"
+# elif HAVE_TYPEOF_ST_BLKSIZE==2
+#define F_st_blksize "%hu"
+# elif HAVE_TYPEOF_ST_BLKSIZE==3
+#define F_st_blksize "%d"
+# elif HAVE_TYPEOF_ST_BLKSIZE==4
+#define F_st_blksize "%u"
+# elif HAVE_TYPEOF_ST_BLKSIZE==5
+#define F_st_blksize "%ld"
+# elif HAVE_TYPEOF_ST_BLKSIZE==6
+#define F_st_blksize "%lu"
+# else
+#error "HAVE_TYPEOF_ST_BLKSIZE is out of range:" HAVE_TYPEOF_ST_BLKSIZE
+# endif
+#endif
+
+/* default: long */
+#if !defined(HAVE_TYPEOF_ST_BLOCKS) || !HAVE_TYPEOF_ST_BLOCKS
+# undef HAVE_TYPEOF_ST_BLOCKS
+# define HAVE_TYPEOF_ST_BLOCKS 5
+#endif
+#ifndef F_st_blocks
+# if HAVE_TYPEOF_ST_BLOCKS==1
+#define F_st_blocks "%hd"
+# elif HAVE_TYPEOF_ST_BLOCKS==2
+#define F_st_blocks "%hu"
+# elif HAVE_TYPEOF_ST_BLOCKS==3
+#define F_st_blocks "%d"
+# elif HAVE_TYPEOF_ST_BLOCKS==4
+#define F_st_blocks "%u"
+# elif HAVE_TYPEOF_ST_BLOCKS==5
+#define F_st_blocks "%ld"
+# elif HAVE_TYPEOF_ST_BLOCKS==6
+#define F_st_blocks "%lu"
+# elif HAVE_TYPEOF_ST_BLOCKS==7
+#define F_st_blocks "%Ld"
+# elif HAVE_TYPEOF_ST_BLOCKS==8
+#define F_st_blocks "%Lu"
+# else
+#error "HAVE_TYPEOF_ST_BLOCKS is out of range:" HAVE_TYPEOF_ST_BLOCKS
+# endif
+#endif
+
+/* default: long long */
+#if !defined(HAVE_TYPEOF_ST64_BLOCKS) || !HAVE_TYPEOF_ST64_BLOCKS
+# undef HAVE_TYPEOF_ST64_BLOCKS
+# define HAVE_TYPEOF_ST64_BLOCKS 7
+#endif
+#ifndef F_st64_blocks
+# if HAVE_TYPEOF_ST64_BLOCKS==1
+#define F_st64_blocks "%hd"
+# elif HAVE_TYPEOF_ST64_BLOCKS==2
+#define F_st64_blocks "%hu"
+# elif HAVE_TYPEOF_ST64_BLOCKS==3
+#define F_st64_blocks "%d"
+# elif HAVE_TYPEOF_ST64_BLOCKS==4
+#define F_st64_blocks "%u"
+# elif HAVE_TYPEOF_ST64_BLOCKS==5
+#define F_st64_blocks "%ld"
+# elif HAVE_TYPEOF_ST64_BLOCKS==6
+#define F_st64_blocks "%lu"
+# elif HAVE_TYPEOF_ST64_BLOCKS==7
+#define F_st64_blocks "%Ld"
+# elif HAVE_TYPEOF_ST64_BLOCKS==8
+#define F_st64_blocks "%Lu"
+# else
+#error "HAVE_TYPEOF_ST64_BLOCKS is out of range:" HAVE_TYPEOF_ST64_BLOCKS
+# endif
+#endif
+
+
+/* at least for Linux */
+#define F_tv_sec "%ld"
+
+/* default: long */
+#if !defined(HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC) || !HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC
+# undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC
+# define HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC 5
+#endif
+#ifndef F_tv_usec
+# if HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==1
+#define F_tv_usec "%06hd"
+# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==2
+#define F_tv_usec "%06hu"
+# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==3
+#define F_tv_usec "%06d"
+# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==4
+#define F_tv_usec "%06u"
+# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==5
+#define F_tv_usec "%06ld"
+# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==6
+#define F_tv_usec "%06lu"
+# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==7
+#define F_tv_usec "%06Ld"
+# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==8
+#define F_tv_usec "%06Lu"
+# else
+#error "HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC is out of range:" HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC
+# endif
+#endif
+
+/* default: long */
+#if !defined(HAVE_TYPEOF_RLIM_MAX) || !HAVE_TYPEOF_RLIM_MAX
+# undef HAVE_TYPEOF_RLIM_MAX
+# define HAVE_TYPEOF_RLIM_MAX 5
+#endif
+#ifndef F_rlim_max
+# if HAVE_TYPEOF_RLIM_MAX==1
+#define F_rlim_max "hd"
+# elif HAVE_TYPEOF_RLIM_MAX==2
+#define F_rlim_max "hu"
+# elif HAVE_TYPEOF_RLIM_MAX==3
+#define F_rlim_max "d"
+# elif HAVE_TYPEOF_RLIM_MAX==4
+#define F_rlim_max "u"
+# elif HAVE_TYPEOF_RLIM_MAX==5
+#define F_rlim_max "ld"
+# elif HAVE_TYPEOF_RLIM_MAX==6
+#define F_rlim_max "lu"
+# elif HAVE_TYPEOF_RLIM_MAX==7
+#define F_rlim_max "Ld"
+# elif HAVE_TYPEOF_RLIM_MAX==8
+#define F_rlim_max "Lu"
+# else
+#error "HAVE_TYPEOF_RLIM_MAX is out of range:" HAVE_TYPEOF_RLIM_MAX
+# endif
+#endif
+
+/* Cygwin 1.3.22 has the prototypes, but not the type... */
+#ifndef HAVE_TYPE_STAT64
+# undef HAVE_STAT64
+# undef HAVE_FSTAT64
+# undef HAVE_LSTAT64
+#endif
+#ifndef HAVE_TYPE_OFF64
+# undef HAVE_LSEEK64
+# undef HAVE_FTRUNCATE64
+#endif
+
+#if !defined(NETDB_INTERNAL) && defined(h_NETDB_INTERNAL)
+# define NETDB_INTERNAL h_NETDB_INTERNAL
+#endif
+
+#if !HAVE_PROTOTYPE_HSTRERROR
+/* with MacOSX this is char * */
+extern const char *hstrerror(int);
+#endif
+
+/*****************************************************************************/
+/* here are the declarations of compat.c */
+
+#if !HAVE_SIGACTION
+struct sigaction {
+ void (*sa_handler)(int);
+ void (*sa_sigaction)(int, siginfo_t *, void *);
+ sigset_t sa_mask;
+ int sa_flags;
+} ;
+struct siginfo {
+ int si_signo;
+ int si_errno;
+ int si_code;
+ pid_t si_pid;
+ uid_t si_uid;
+ int si_status;
+ /*clock_t si_utime;*/
+ /*clock_t si_stime;*/
+ sigval_t si_value;
+ int si_int;
+ void *si_ptr;
+ void *si_addr;
+ /*int si_band;*/
+ /*int si_fd;*/
+} ;
+extern int sigaction(int signum, const struct sigaction *act,
+ struct sigaction *oldact);
+#endif /* !HAVE_SIGACTION */
+
+#endif /* !defined(__compat_h_included) */
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..1dabea2
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,484 @@
+/* $Id: config.h.in,v 1.63 2007/03/06 21:00:16 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* 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 <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define if your struct stat has st_blksize. */
+#undef HAVE_ST_BLKSIZE
+
+/* Define if your struct stat has st_blocks. */
+#undef HAVE_ST_BLOCKS
+
+/* Define if your struct stat has st_rdev. */
+#undef HAVE_ST_RDEV
+
+/* Define if you have the strftime function. */
+#undef HAVE_STRFTIME
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef mode_t
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef pid_t
+
+/* Define as the return type of signal handlers (int or void). */
+#undef RETSIGTYPE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define if you have the putenv function. */
+#undef HAVE_PUTENV
+
+/* Define if you have the select function. */
+#undef HAVE_SELECT
+
+/* Define if you have the poll function. */
+#undef HAVE_POLL
+
+/* Define if you have the socket function. */
+#undef HAVE_SOCKET
+
+/* Define if you have the strdup function. */
+#undef HAVE_STRDUP
+
+/* Define if you have the strerror function. */
+#undef HAVE_STRERROR
+
+/* Define if you have the strstr function. */
+#undef HAVE_STRSTR
+
+/* Define if you have the strtod function. */
+#undef HAVE_STRTOD
+
+/* Define if you have the strtol function. */
+#undef HAVE_STRTOL
+
+/* Define if you have the strtoul function. */
+#undef HAVE_STRTOUL
+
+/* Define if you have the uname function. */
+#undef HAVE_UNAME
+
+/* Define if you have the getpgid function. */
+#undef HAVE_GETPGID
+
+/* Define if you have the getsid function. */
+#undef HAVE_GETSID
+
+/* Define if you have the nanosleep function. */
+#undef HAVE_NANOSLEEP
+
+/* 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. */
+#undef HAVE_SETGROUPS
+
+/* Define if you have the inet_aton function. */
+#undef HAVE_INET_ATON
+
+/* Define if you have the memrchr function. */
+#undef HAVE_MEMRCHR
+
+/* Define if you have the sigaction function */
+#undef HAVE_SIGACTION
+
+/* 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 */
+#undef HAVE_STRTOLL
+
+/* Define if you have the hstrerror function */
+#undef HAVE_HSTRERROR
+
+/* Define if you have the inet_ntop function */
+#undef HAVE_INET_NTOP
+
+/* Define if you have the hstrerror prototype */
+#undef HAVE_PROTOTYPE_HSTRERROR
+
+/* Define if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
+/* Define if you have the <grp.h> header file. */
+#undef HAVE_GRP_H
+
+/* Define if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define if you have the <sys/poll.h> header file. */
+#undef HAVE_SYS_POLL_H
+
+/* Define if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define if you have the <sys/uio.h> header file. */
+#undef HAVE_SYS_UIO_H
+
+/* Define if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
+/* Define if you have the <pty.h> header file. */
+#undef HAVE_PTY_H
+
+/* Define if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define if you have the <netinet/in_systm.h> header file. */
+#undef HAVE_NETINET_IN_SYSTM_H
+
+/* Define if you have the <netinet/ip.h> header file. */
+#undef HAVE_NETINET_IP_H
+
+/* Define if you have the <netinet/tcp.h> header file. */
+#undef HAVE_NETINET_TCP_H
+
+/* Define if you have the <netinet/ip6.h> header file. */
+#undef HAVE_NETINET_IP6_H
+
+/* Define if you have the <arpa/nameser.h> header file. */
+#undef HAVE_ARPA_NAMESER_H
+
+/* Define if you have the <resolv.h> header file. */
+#undef HAVE_RESOLV_H
+
+/* Define if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
+
+/* Define if you have the <linux/if_tun.h> header file. */
+#undef HAVE_LINUX_IF_TUN_H
+
+/* Define if you have the <sys/utsname.h> header file. */
+#undef HAVE_SYS_UTSNAME_H
+
+/* Define if you have the <sys/select.h> header file. (AIX) */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the <sys/file.h> header file. (AIX) */
+#undef HAVE_SYS_FILE_H
+
+/* Define if you have the <util.h> header file. (NetBSD, OpenBSD: openpty()) */
+#undef HAVE_UTIL_H
+
+/* Define if you have the <libutil.h> header file. (FreeBSD: openpty()) */
+#undef HAVE_LIBUTIL_H
+
+/* Define if you have the <sys/stropts.h> header file. (stream opts on SunOS)*/
+#undef HAVE_SYS_STROPTS_H
+
+/* Define if you have the <regex.h> header file. */
+#undef HAVE_REGEX_H
+
+/* Define if you have the <linux/fs.h> header file. */
+#undef HAVE_LINUX_FS_H
+
+/* Define if you have the <linux/ext2_fs.h> header file. */
+#undef HAVE_LINUX_EXT2_FS_H
+
+/* Define if you have the <readline/readline.h> header file. */
+#undef HAVE_READLINE_READLINE_H
+
+/* Define if you have the <readline/history.h> 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 */
+#undef HAVE_FDS_BITS
+
+/* 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) */
+#undef HAVE_STRUCT_TIMESPEC
+
+/* Define if you have struct linger */
+#undef HAVE_STRUCT_LINGER
+
+/* Define if you have struct ip_mreq */
+#undef HAVE_STRUCT_IP_MREQ
+
+/* 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 */
+#undef HAVE_STRUCT_IFREQ
+
+/* Define if you have struct ifreq.ifr_index */
+#undef HAVE_STRUCT_IFREQ_IFR_INDEX
+
+/* Define if you have struct ifreq.ifr_ifindex */
+#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 */
+#undef HAVE_STRUCT_IOVEC
+
+/* 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 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 flock function */
+#undef HAVE_FLOCK
+
+/* Define if you have the openpty function */
+#undef HAVE_OPENPTY
+
+/* 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 */
+#undef HAVE_TYPE_LONGLONG
+
+/* is socklen_t already typedef'd? */
+#undef HAVE_TYPE_SOCKLEN
+
+/* 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? */
+#undef HAVE_TYPE_UINT8
+
+/* is uint16_t already defined? */
+#undef HAVE_TYPE_UINT16
+
+/* is uint32_t already defined? */
+#undef HAVE_TYPE_UINT32
+
+/* is uint64_t already defined? */
+#undef HAVE_TYPE_UINT64
+
+/* Define if you have the printf "Z" modifier */
+#undef HAVE_FORMAT_Z
+
+/* Define the shift offset of the CRDLY mask */
+#undef CRDLY_SHIFT
+
+/* Define the shift offset of the TABDLY mask */
+#undef TABDLY_SHIFT
+
+/* Define the shift offset of the CSIZE mask */
+#undef CSIZE_SHIFT
+
+/* 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 */
+#undef HAVE_BASIC_SIZE_T
+#undef HAVE_BASIC_MODE_T
+#undef HAVE_BASIC_PID_T
+#undef HAVE_BASIC_UID_T
+#undef HAVE_BASIC_GID_T
+#undef HAVE_BASIC_TIME_T
+#undef HAVE_BASIC_OFF64_T
+
+#undef HAVE_BASIC_SOCKLEN_T
+
+#undef HAVE_TYPEOF_ST_DEV
+#undef HAVE_TYPEOF_ST_INO
+#undef HAVE_TYPEOF_ST_NLINK
+#undef HAVE_TYPEOF_ST_SIZE
+#undef HAVE_TYPEOF_ST_BLKSIZE
+#undef HAVE_TYPEOF_ST_BLOCKS
+
+#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
+
+#undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC
+
+#undef HAVE_TYPEOF_RLIM_MAX
+
+/* Define if you have the /proc filesystem */
+#undef HAVE_PROC_DIR
+
+/* Define if you have the /proc/$$/fd directories */
+#undef HAVE_PROC_DIR_FD
+
+#undef WITH_HELP
+#undef WITH_STDIO
+#undef WITH_FDNUM
+#undef WITH_FILE
+#undef WITH_CREAT
+#undef WITH_GOPEN
+#undef WITH_TERMIOS
+#undef WITH_PIPE
+#undef WITH_UNIX
+#undef WITH_ABSTRACT_UNIXSOCKET
+#undef WITH_IP4
+#undef WITH_IP6
+#undef WITH_RAWIP
+#undef WITH_TCP
+#undef WITH_UDP
+#undef WITH_LISTEN
+#undef WITH_SOCKS4
+#undef WITH_SOCKS4A
+#undef WITH_PROXY
+#undef WITH_EXEC
+#undef WITH_SYSTEM
+#undef WITH_READLINE
+#undef WITH_TUN
+#undef WITH_PTY
+#undef WITH_EXT2
+#undef WITH_OPENSSL
+#undef WITH_FIPS
+#undef OPENSSL_FIPS
+#undef WITH_LIBWRAP
+#undef HAVE_TCPD_H
+#undef HAVE_LIBWRAP
+
+#undef WITH_SYCLS
+#undef WITH_FILAN
+#undef WITH_RETRY
+
+#undef WITH_MSGLEVEL
+
+#endif /* !defined(__config_h_included) */
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..bf51c6a
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,1459 @@
+nl $Id: configure.in,v 1.108 2007/03/06 21:00:28 gerhard Exp $
+dnl Copyright Gerhard Rieger 2001-2007
+dnl Published under the GNU General Public License V.2, see file COPYING
+
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(socat.c)
+
+AC_CONFIG_HEADER(config.h)
+
+if test -f /usr/xpg4/bin/fgrep; then
+ FGREP=/usr/xpg4/bin/fgrep # Solaris
+else
+ FGREP=fgrep
+fi
+
+# find out which defines gcc passes to cpp, so makedepend does not run into
+# (harmless) "error architecture not supported"
+AC_MSG_CHECKING(which defines needed for makedepend)
+__cpp_defs=`gcc -v -E - </dev/null 2>&1 |$FGREP -e '/cpp ' -e '/cc1 '`
+SYSDEFS=`aa=; for a in $__cpp_defs
+ do case "$a" in -D*) aa="$aa $a";; esac; done; echo "$aa"`
+AC_SUBST(SYSDEFS)
+AC_MSG_RESULT($SYSDEFS)
+
+
+# this must come before AC_PROG_CC
+if test -z "$CFLAGS"; then
+ # if CFLAGS is not set, we preset it to -O
+ # with this setting, we prevent autoconf from defaulting to "-g -O2"
+ export CFLAGS=-O
+fi
+
+dnl Checks for programs.
+AC_PROG_INSTALL(install)
+AC_PROG_CC
+AC_PROG_RANLIB
+AC_SUBST(AR)
+AC_CHECK_PROG(AR, ar, ar, gar)
+#
+# we need to explicitely call this here; otherwise, with --disable-libwrap we
+# fail
+AC_LANG_COMPILER_REQUIRE()
+
+if test "$GCC" = yes; then
+ CFLAGS="$CFLAGS -D_GNU_SOURCE"
+fi
+export CFLAGS
+
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(fcntl.h limits.h strings.h sys/param.h sys/ioctl.h sys/time.h syslog.h unistd.h)
+AC_CHECK_HEADERS(pwd.h grp.h stdint.h sys/types.h sys/poll.h sys/socket.h sys/uio.h sys/stat.h netdb.h sys/un.h)
+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(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 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))
+AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt))
+
+
+dnl Check for hstrerror prototype
+AC_MSG_CHECKING(for hstrerror prototype)
+AC_CACHE_VAL(sc_cv_have_prototype_hstrerror,
+[CFLAGS1="$CFLAGS"; CFLAGS="-Werror -O0 $CFLAGS1";
+ AC_TRY_COMPILE([#include <netdb.h>],[hstrerror();],
+ [sc_cv_have_prototype_hstrerror=no],
+ [sc_cv_have_prototype_hstrerror=yes]);
+ CFLAGS="$CFLAGS1"])
+if test $sc_cv_have_prototype_hstrerror = yes; then
+ AC_DEFINE(HAVE_PROTOTYPE_HSTRERROR)
+fi
+AC_MSG_RESULT($sc_cv_have_prototype_hstrerror)
+
+
+AC_MSG_CHECKING(whether to include help)
+AC_ARG_ENABLE(help, [ --disable-help disable help],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_HELP) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_HELP) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include STDIO support)
+AC_ARG_ENABLE(stdio, [ --disable-stdio disable STDIO support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_STDIO) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_STDIO) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include FD-number support)
+AC_ARG_ENABLE(fdnum, [ --disable-fdnum disable FD-number support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_FDNUM) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_FDNUM) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include direct file support)
+AC_ARG_ENABLE(file, [ --disable-file disable direct file support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_FILE) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_FILE) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include direct create support)
+AC_ARG_ENABLE(creat, [ --disable-creat disable direct create support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_CREAT) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_CREAT) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include gopen support)
+AC_ARG_ENABLE(gopen, [ --disable-gopen disable open for UNIX socket support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_GOPEN) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_GOPEN) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include explicit pipe support)
+AC_ARG_ENABLE(pipe, [ --disable-pipe disable pipe support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_PIPE) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_PIPE) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include explicit termios support)
+AC_ARG_ENABLE(termios, [ --disable-termios disable termios support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_TERMIOS) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_TERMIOS) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include UNIX socket support)
+AC_ARG_ENABLE(unix, [ --disable-unix disable UNIX domain socket support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_UNIX) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_UNIX) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include abstract UNIX socket support)
+AC_ARG_ENABLE(abstract_unixsocket, [ --disable-abstract-unixsocket disable abstract UNIX domain socket support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_ABSTRACT_UNIXSOCKET) AC_MSG_RESULT(yes);;
+ esac],
+ [ case "`uname`" in
+ Linux)
+ AC_DEFINE(WITH_ABSTRACT_UNIXSOCKET) AC_MSG_RESULT(yes);;
+ *)
+ AC_MSG_RESULT(no);;
+ esac])
+
+AC_MSG_CHECKING(whether to include IPv4 support)
+AC_ARG_ENABLE(ip4, [ --disable-ip4 disable IPv4 support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_IP4) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_IP4) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include IPv6 support)
+AC_ARG_ENABLE(ip6, [ --disable-ip6 disable IPv6 support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no); WITH_IP6= ;;
+ *) AC_MSG_RESULT(yes); WITH_IP6=1 ;;
+ esac],
+ [ AC_MSG_RESULT(yes); WITH_IP6=1 ])
+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])])
+fi
+
+AC_MSG_CHECKING(whether to include raw IP support)
+AC_ARG_ENABLE(rawip, [ --disable-rawip disable raw IP support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_RAWIP) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_RAWIP) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include TCP support)
+AC_ARG_ENABLE(tcp, [ --disable-tcp disable TCP support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_TCP) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_TCP) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include UDP support)
+AC_ARG_ENABLE(udp, [ --disable-udp disable UDP support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_UDP) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_UDP) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include listen support)
+AC_ARG_ENABLE(listen, [ --disable-listen disable listen support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_LISTEN) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_LISTEN) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include socks4 support)
+AC_ARG_ENABLE(socks4, [ --disable-socks4 disable socks4 support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_SOCKS4) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_SOCKS4) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include socks4a support)
+AC_ARG_ENABLE(socks4a, [ --disable-socks4a disable socks4a support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_SOCKS4A) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_SOCKS4A) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include proxy connect support)
+AC_ARG_ENABLE(proxy, [ --disable-proxy disable proxy connect support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_PROXY) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_PROXY) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include exec support)
+AC_ARG_ENABLE(exec, [ --disable-exec disable exec support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_EXEC) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_EXEC) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING([whether to include system (shell) support])
+AC_ARG_ENABLE(system, [ --disable-system disable system (shell) support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_SYSTEM) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_SYSTEM) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include pty address support)
+AC_ARG_ENABLE(pty, [ --disable-pty disable pty support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_PTY) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_PTY) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include ext2 fs attributes support)
+AC_ARG_ENABLE(ext2, [ --disable-ext2 disable ext2 fs attributes support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_EXT2) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_EXT2) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(whether to include readline support)
+AC_ARG_ENABLE(readline, [ --disable-readline disable readline support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no); WITH_READLINE= ;;
+ *) AC_MSG_RESULT(yes); WITH_READLINE=1 ;;
+ 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 <readline.h>
+ 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 <stdio.h> /* FreeBSD needs "FILE *" */
+#include <readline/readline.h>
+#include <readline/history.h>],[;],
+ [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 <stdio.h> /* FreeBSD needs FILE * */
+#include <readline/readline.h>
+#include <readline/history.h>],
+ [readline(NULL)],
+ [sc_cv_have_libreadline='yes'],
+ [sc_cv_have_libreadline='no'
+ LIBS1="$LIBS"
+ LIBS="$LIBS -lcurses"
+ AC_TRY_LINK([#include <stdio.h> /* FreeBSD needs FILE * */
+#include <readline/readline.h>
+#include <readline/history.h>],
+ [readline(NULL)],
+ [sc_cv_have_libreadline='yes'],
+ [sc_cv_have_libreadline='no'
+ LIBS="$LIBS1 -lncurses" # eg for SuSE52
+ AC_TRY_LINK([#include <stdio.h> /* FreeBSD needs FILE * */
+#include <readline/readline.h>
+#include <readline/history.h>],
+ [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]);
+ fi
+fi
+
+AC_MSG_CHECKING(whether to include openssl support)
+AC_ARG_ENABLE(openssl, [ --disable-openssl disable OpenSSL support],
+ [ case "$enableval" in
+ no) AC_MSG_RESULT(no); WITH_OPENSSL= ;;
+ *) AC_MSG_RESULT(yes); WITH_OPENSSL=1 ;;
+ esac],
+ [ AC_MSG_RESULT(yes); WITH_OPENSSL=1 ])
+#
+if test -n "$WITH_OPENSSL"; then
+ AC_MSG_NOTICE(checking for components of OpenSSL)
+ # first, we need to find the include file <openssl/ssl.h>
+ AC_CACHE_VAL(sc_cv_have_openssl_ssl_h,
+ [AC_TRY_COMPILE([#include <openssl/ssl.h>],[;],
+ [sc_cv_have_openssl_ssl_h=yes; OPENSSL_ROOT=""; ],
+ [sc_cv_have_openssl_ssl_h=no
+ for D in "/sw" "/usr/local" "/opt/freeware" "/usr/sfw" "/usr/local/ssl"; do
+ I="$D/include"
+ i="$I/openssl/ssl.h"
+ if test -r "$i"; then
+ #V_INCL="$V_INCL -I$I"
+ CPPFLAGS="$CPPFLAGS -I$I"
+ AC_MSG_NOTICE(found $i)
+ sc_cv_have_openssl_ssl_h=yes; OPENSSL_ROOT="$D"
+ break;
+ fi
+ done])
+ ])
+ if test "$sc_cv_have_openssl_ssl_h" = "yes"; then
+ AC_DEFINE(HAVE_OPENSSL_SSL_H)
+ fi
+ AC_MSG_NOTICE(checked for openssl/ssl.h... $sc_cv_have_openssl_ssl_h)
+fi # end checking for openssl/ssl.h
+#
+if test -n "$WITH_OPENSSL" -a "$sc_cv_have_openssl_ssl_h" = 'yes'; then
+ # next, we search for the openssl library (libssl.*)
+ # interesting: Linux only requires -lssl, FreeBSD requires -lssl -lcrypto
+ # Note, version OpenSSL 0.9.7j requires -lcrypto even on Linux.
+ AC_MSG_CHECKING(for libssl)
+ AC_CACHE_VAL(sc_cv_have_libssl,
+ [ LIBS0="$LIBS"
+ if test -n "$OPENSSL_ROOT"; then
+ L="$OPENSSL_ROOT/lib"; LIBS="$LIBS -L$L -lssl"
+ else
+ LIBS="$LIBS -lssl"
+ fi
+ AC_TRY_LINK([#include <openssl/ssl.h>],
+ [SSL_library_init();ERR_error_string()],
+ [sc_cv_have_libssl='yes'],
+ [ LIBS="$LIBS -lcrypto"
+ AC_TRY_LINK([#include <openssl/ssl.h>],
+ [SSL_library_init()],
+ [sc_cv_have_libssl='yes'],
+ [sc_cv_have_libssl='no'])
+ ])
+ if test "$sc_cv_have_libssl" != 'yes'; then
+ LIBS="$LIBS0"
+ fi
+ ]
+ )
+ if test "$sc_cv_have_libssl" = 'yes'; then
+ AC_DEFINE(HAVE_LIBSSL)
+ fi
+ AC_MSG_RESULT($sc_cv_have_libssl)
+fi
+#
+# # a possible location for openssl (on Sourceforge/Solaris)
+# AC_CHECK_FILE(/usr/local/ssl/lib, LIBS="$LIBS -L/usr/local/ssl/lib/")
+# # sometimes on Solaris:
+# AC_CHECK_FILE(/pkgs/lib, LIBS="$LIBS -L/pkgs/lib/")
+# # for AIX 5.1 with Linux toolbox:
+# AC_CHECK_FILE(/opt/freeware/lib, LIBS="$LIBS -L/opt/freeware/lib/")
+#
+# AC_CHECK_LIB(crypto, main)
+# AC_CHECK_LIB(ssl, main)
+#
+# # MacOSX has openssl includes in another directory
+# if test -d /sw/include/; then
+# V_INCL="$V_INCL -I/sw/include"
+# # and Solaris at sourceforge here:
+# elif test -d /usr/local/ssl/include/; then
+# V_INCL="$V_INCL -I/usr/local/ssl/include"
+# # and AIX 5.1 with Linux toolbox:
+# elif test -d /opt/freeware/include; then
+# V_INCL="$V_INCL -I/opt/freeware/include"
+# fi
+#fi
+if test -n "$WITH_OPENSSL"; then
+ if test "$sc_cv_have_openssl_ssl_h" = "yes" -a "$sc_cv_have_libssl" = "yes"; then
+ AC_DEFINE(WITH_OPENSSL)
+ else
+ AC_MSG_WARN([not all components of OpenSSL found, disabling it]);
+ fi
+fi
+
+# check for fips support
+AC_MSG_CHECKING(whether to include openssl fips support)
+AC_ARG_ENABLE(fips, [ --disable-fips disable OpenSSL FIPS support],
+ [ case "$enableval" in
+ no) AC_MSG_RESULT(no); WITH_FIPS= ;;
+ *) AC_MSG_RESULT(yes); WITH_FIPS=1 ;;
+ esac],
+ [ AC_MSG_RESULT(yes); WITH_FIPS=1 ])
+
+if test -n "$WITH_FIPS"; then
+ if test -n "$WITH_OPENSSL"; then
+ if test "$sc_cv_have_openssl_ssl_h" != "yes" -o "$sc_cv_have_libssl" != "yes"; then
+ AC_MSG_WARN([not all components of OpenSSL found, disabling FIPS]);
+ WITH_FIPS=
+ fi
+ else
+ AC_MSG_WARN([must enable OpenSSL to enable FIPS; use --enable-openssl]);
+ fi
+fi
+
+if test -n "$WITH_FIPS"; then
+ AC_MSG_NOTICE(checking for components of OpenSSL FIPS)
+ # first, we need to find the include file <openssl/fips.h>
+ AC_CACHE_VAL(sc_cv_have_openssl_fips_h,
+ [AC_TRY_COMPILE([#define OPENSSL_FIPS
+#include <openssl/fips.h>],[;],
+ [sc_cv_have_openssl_fips_h=yes; ],
+ [sv_cv_have_openssl_fips_h=no
+ if test -n "$OPENSSL_ROOT"; then
+ I="$OPENSSL_ROOT/include"
+ i="$I/openssl/fips.h"
+ if test -r "$i"; then
+ AC_MSG_NOTICE(found $i)
+ sc_cv_have_openssl_fips_h=yes;
+ fi
+ fi
+ ]
+ )]
+ )
+ if test "$sv_cv_have_openssl_fips_h" = "yes"; then
+ AC_DEFINE(HAVE_OPENSSL_FIPS_H)
+ fi
+ AC_MSG_NOTICE(checked for openssl/fips.h... $sc_cv_have_openssl_ssl_h)
+fi
+
+if test -n "$WITH_FIPS" -a "$sc_cv_have_openssl_fips_h" = 'yes'; then
+ # check for the libcrypto library with fips support
+ AC_MSG_CHECKING(for libcrypto with FIPS support)
+ AC_CACHE_VAL(sc_cv_have_libcrypto,
+ [ LIBS0="$LIBS"
+ echo $LIBS | grep -q "\-lcrypto"
+ if test $? -ne 0; then
+ if test -n "$OPENSSL_ROOT"; then
+ L="$OPENSSL_ROOT/lib"; LIBS="$LIBS -L$L -lcrypto"
+ else
+ LIBS="$LIBS -lcrypto"
+ fi
+ fi
+ AC_TRY_LINK([#define OPENSSL_FIPS
+#include <openssl/ssl.h>
+#include <openssl/fips.h>],
+ [int res = FIPS_mode_set(1);],
+ [sc_cv_have_libcrypto='yes'],
+ [sc_cv_have_libcrypto='no']
+ )
+ if test "$sc_cv_have_libcrypto" != 'yes'; then
+ LIBS="$LIBS0"
+ fi
+ ]
+ )
+ if test "$sc_cv_have_libcrypto" = 'yes'; then
+ AC_DEFINE(HAVE_LIBCRYPTO)
+ fi
+ AC_MSG_RESULT($sc_cv_have_libcrypto)
+fi
+
+if test -n "$WITH_FIPS"; then
+ if test "$sc_cv_have_openssl_fips_h" = 'yes' -a "$sc_cv_have_libcrypto" = 'yes'; then
+ AC_DEFINE(WITH_FIPS)
+ AC_DEFINE(OPENSSL_FIPS)
+ else
+ AC_MSG_WARN([not all components of OpenSSL FIPS found, disabling it]);
+ fi
+fi
+
+AC_MSG_CHECKING(whether to include tun/tap address support)
+AC_ARG_ENABLE(tun, [ --disable-tun disable TUN/TAP support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no); WITH_TUN= ;;
+ *) AC_MSG_RESULT(yes); WITH_TUN=1 ;;
+ esac],
+ [AC_MSG_RESULT(yes); WITH_TUN=1 ])
+
+#
+if test -n "$WITH_TUN"; then
+ if test `uname` != Linux; then
+ AC_MSG_NOTICE(only on Linux)
+ else
+ AC_DEFINE(WITH_TUN)
+ fi
+fi
+
+AC_MSG_CHECKING(whether to include system call tracing)
+AC_ARG_ENABLE(sycls, [ --disable-sycls disable system call tracing],
+ [case "$enableval" in
+ no) SYCLS=""; SSLCLS=""; AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_SYCLS)
+ SYCLS="sycls.c"; SSLCLS="sslcls.c"; AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_SYCLS)
+ SYCLS="sycls.c"; SSLCLS="sslcls.c"; AC_MSG_RESULT(yes)])
+AC_SUBST(SYCLS)
+AC_SUBST(SSLCLS)
+
+AC_MSG_CHECKING(whether to include file descriptor analyzer)
+AC_ARG_ENABLE(filan, [ --disable-filan disable file descriptor analyzer],
+ [case "$enableval" in
+ no) FILAN=""; AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_FILAN) FILAN="filan.c"; AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_FILAN) FILAN="filan.c"; AC_MSG_RESULT(yes)])
+AC_SUBST(FILAN)
+
+AC_MSG_CHECKING(whether to include retry support)
+AC_ARG_ENABLE(retry, [ --disable-retry disable retry support],
+ [case "$enableval" in
+ no) AC_MSG_RESULT(no);;
+ *) AC_DEFINE(WITH_RETRY) AC_MSG_RESULT(yes);;
+ esac],
+ [AC_DEFINE(WITH_RETRY) AC_MSG_RESULT(yes)])
+
+AC_MSG_CHECKING(included message level)
+AC_ARG_ENABLE(msglevel, [ --enable-msglevel=N set max verbosity to debug,info,notice,warn,error,fatal],
+ [case "$enableval" in
+ debug) AC_DEFINE(WITH_MSGLEVEL,0) AC_MSG_RESULT(debug);;
+ info) AC_DEFINE(WITH_MSGLEVEL,1) AC_MSG_RESULT(info);;
+ notice) AC_DEFINE(WITH_MSGLEVEL,2) AC_MSG_RESULT(notice);;
+ warn) AC_DEFINE(WITH_MSGLEVEL,3) AC_MSG_RESULT(warn);;
+ error) AC_DEFINE(WITH_MSGLEVEL,4) AC_MSG_RESULT(error);;
+ fatal) AC_DEFINE(WITH_MSGLEVEL,5) AC_MSG_RESULT(fatal);;
+ *) AC_DEFINE(WITH_MSGLEVEL,0) AC_MSG_RESULT(debug);;
+ esac],
+ [AC_DEFINE(WITH_MSGLEVEL,0) AC_MSG_RESULT(debug)])
+
+#AC_SUBST(V_INCL)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_UID_T
+AC_TYPE_MODE_T
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_STRUCT_ST_BLKSIZE
+AC_STRUCT_ST_BLOCKS
+AC_STRUCT_ST_RDEV
+AC_HEADER_TIME
+
+dnl Check for extra realtime library (for Solaris)
+AC_CHECK_FUNC(nanosleep, AC_DEFINE(HAVE_NANOSLEEP), AC_CHECK_LIB(rt, nanosleep, [LIBS="-lrt $LIBS"; AC_DEFINE(HAVE_NANOSLEEP)]))
+#AC_CHECK_FUNC(nanosleep, , AC_CHECK_LIB(rt, nanosleep))
+
+dnl Checks for library functions.
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_MEMCMP
+AC_TYPE_SIGNAL
+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(grantpt unlockpt ptsname)
+
+
+AC_MSG_CHECKING(for long long)
+AC_CACHE_VAL(sc_cv_type_longlong,
+[AC_TRY_COMPILE([],[long long s;],
+[sc_cv_type_longlong=yes],
+[sc_cv_type_longlong=no])])
+if test $sc_cv_type_longlong = yes; then
+ AC_DEFINE(HAVE_TYPE_LONGLONG)
+fi
+AC_MSG_RESULT($sc_cv_type_longlong)
+
+# following builtin macro does not check unistd.h and sys/socket.h where
+# socklen_t might be defined
+#AC_CHECK_TYPE(socklen_t, int)
+#
+AC_MSG_CHECKING(for socklen_t)
+AC_CACHE_VAL(sc_cv_type_socklen,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>],[socklen_t s;],
+[sc_cv_type_socklen=yes],
+[sc_cv_type_socklen=no])])
+if test $sc_cv_type_socklen = yes; then
+ AC_DEFINE(HAVE_TYPE_SOCKLEN)
+fi
+AC_MSG_RESULT($sc_cv_type_socklen)
+
+AC_MSG_CHECKING(for struct stat64)
+AC_CACHE_VAL(sc_cv_type_stat64,
+[AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 s;],
+[sc_cv_type_stat64=yes],
+[sc_cv_type_stat64=no])])
+if test $sc_cv_type_stat64 = yes; then
+ AC_DEFINE(HAVE_TYPE_STAT64)
+fi
+AC_MSG_RESULT($sc_cv_type_stat64)
+
+AC_MSG_CHECKING(for off64_t)
+AC_CACHE_VAL(sc_cv_type_off64,
+[AC_TRY_COMPILE([#include <unistd.h>],[off64_t s;],
+[sc_cv_type_off64=yes],
+[sc_cv_type_off64=no])])
+if test $sc_cv_type_off64 = yes; then
+ AC_DEFINE(HAVE_TYPE_OFF64)
+fi
+AC_MSG_RESULT($sc_cv_type_off64)
+
+AC_MSG_CHECKING(for sighandler_t)
+AC_CACHE_VAL(sc_cv_type_sighandler,
+[AC_TRY_COMPILE([#include <signal.h>],[sighandler_t s;],
+[sc_cv_type_sighandler=yes],
+[sc_cv_type_sighandler=no])])
+if test $sc_cv_type_sighandler = yes; then
+ AC_DEFINE(HAVE_TYPE_SIGHANDLER)
+fi
+AC_MSG_RESULT($sc_cv_type_socklen)
+
+AC_MSG_CHECKING(for uint8_t)
+AC_CACHE_VAL(sc_cv_type_uint8,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+/* Tru64 has uint8_t etc from netdb.h */
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#include <unistd.h>],[uint8_t s;],
+[sc_cv_type_uint8=yes],
+[sc_cv_type_uint8=no])])
+if test $sc_cv_type_uint8 = yes; then
+ AC_DEFINE(HAVE_TYPE_UINT8)
+fi
+AC_MSG_RESULT($sc_cv_type_uint8)
+
+AC_MSG_CHECKING(for uint16_t)
+AC_CACHE_VAL(sc_cv_type_uint16,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+/* Tru64 has uint16_t etc from netdb.h */
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#include <unistd.h>],[uint16_t s;],
+[sc_cv_type_uint16=yes],
+[sc_cv_type_uint16=no])])
+if test $sc_cv_type_uint16 = yes; then
+ AC_DEFINE(HAVE_TYPE_UINT16)
+fi
+AC_MSG_RESULT($sc_cv_type_uint16)
+
+AC_MSG_CHECKING(for uint32_t)
+AC_CACHE_VAL(sc_cv_type_uint32,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+/* Tru64 has uint32_t etc from netdb.h */
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#include <unistd.h>],[uint32_t s;],
+[sc_cv_type_uint32=yes],
+[sc_cv_type_uint32=no])])
+if test $sc_cv_type_uint32 = yes; then
+ AC_DEFINE(HAVE_TYPE_UINT32)
+fi
+AC_MSG_RESULT($sc_cv_type_uint32)
+
+AC_MSG_CHECKING(for uint64_t)
+AC_CACHE_VAL(sc_cv_type_uint64,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+/* Tru64 has uint32_t etc from netdb.h */
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#include <unistd.h>],[uint64_t s;],
+[sc_cv_type_uint64=yes],
+[sc_cv_type_uint64=no])])
+if test $sc_cv_type_uint64 = yes; then
+ AC_DEFINE(HAVE_TYPE_UINT64)
+fi
+AC_MSG_RESULT($sc_cv_type_uint64)
+
+### AIX 4.1 needs _XOPEN_EXTENDED_SOURCE for syslog headers,
+# but then gets problems with 3rd arg of getsockaddr...
+#AC_MSG_CHECKING(for _XOPEN_EXTENDED_SOURCE requirement)
+#CFLAGS="-Werror -Wall"
+#AC_TRY_COMPILE([#include <sys/syslog.h>],
+#[syslog(0," ");],
+#[AC_MSG_RESULT(no)],
+#[AC_MSG_RESULT(required); AC_DEFINE(_XOPEN_EXTENDED_SOURCE)])
+
+
+### fds_bits
+
+AC_MSG_CHECKING(for fdset->fds_bits)
+AC_TRY_COMPILE([#include <sys/types.h>
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif],
+[fd_set s; s.fds_bits[0]=0;],
+[AC_MSG_RESULT(yes); AC_DEFINE(HAVE_FDS_BITS)],
+[AC_MSG_RESULT(no);])
+
+### struct termios .c_ispeed
+AC_MSG_CHECKING(for termios.c_ispeed)
+AC_CACHE_VAL(sc_cv_termios_ispeed,
+[AC_TRY_COMPILE([#include <termios.h>],
+[struct termios t; t.c_ispeed=0;],
+[sc_cv_termios_ispeed=yes],
+[sc_cv_termios_ispeed=no])])
+if test $sc_cv_termios_ispeed = yes; then
+ AC_DEFINE(HAVE_TERMIOS_ISPEED)
+fi
+AC_MSG_RESULT($sc_cv_termios_ispeed)
+
+if test $sc_cv_termios_ispeed = yes; then
+AC_MSG_CHECKING(for offset of c_ispeed in struct termios)
+LIBS1="$LIBS"; LIBS="" # avoid libwrap allow_severity undefined
+AC_CACHE_VAL(ac_cv_ispeed_offset,
+ [conftestspeedoff="conftestspeedoff.out"
+ AC_TRY_RUN([
+ #include <errno.h>
+ #include <stdio.h>
+ #include <termios.h>
+ #include <string.h>
+ main(){
+ struct termios t;
+ FILE *f;
+ if ((f=fopen("$conftestspeedoff","w"))==NULL){
+ fprintf(stderr,"\\"$conftestspeedoff\\": %s\n",strerror(errno)); exit(-1);
+ }
+ fprintf(f, "%d", ((char*)&t.c_ispeed-(char*)&t)/sizeof(speed_t));
+ exit(0);
+ }
+ ],
+ [ac_cv_ispeed_offset=`cat $conftestspeedoff`],
+ [ac_cv_ispeed_offset=-1],
+ [ac_cv_ispeed_offset=-1] #!
+)])
+LIBS="$LIBS1"
+AC_MSG_RESULT($ac_cv_ispeed_offset)
+ if test $ac_cv_ispeed_offset -ge 0; then
+ AC_DEFINE_UNQUOTED(ISPEED_OFFSET, $ac_cv_ispeed_offset)
+ fi
+fi
+
+# there is another issue with termios: OSR requires "#define _SVID3 ..."
+# for reasonable termios support. We check this situation using IMAXBEL
+AC_MSG_CHECKING(if _SVID3 is helpful)
+AC_CACHE_VAL(ac_cv_svid3,
+ [AC_TRY_COMPILE([#include <termios.h>],
+ [int i=IMAXBEL],
+ [ac_cv_svid3=no],
+ [AC_TRY_COMPILE([#define _SVID3 1
+#include <termios.h>],
+ [int i=IMAXBEL],
+ [ac_cv_svid3=yes],
+ [ac_cv_svid3=no]
+ )]
+)])
+if test $ac_cv_svid3 = yes; then
+ AC_DEFINE(_SVID3)
+fi
+AC_MSG_RESULT($ac_cv_svid3)
+
+
+# struct timespec
+AC_MSG_CHECKING(for struct timespec)
+AC_CACHE_VAL(sc_cv_struct_timespec,
+[AC_TRY_COMPILE([#include <time.h>
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif],[struct timespec s;],
+[sc_cv_struct_timespec=yes],
+[sc_cv_struct_timespec=no])])
+if test $sc_cv_struct_timespec = yes; then
+ AC_DEFINE(HAVE_STRUCT_TIMESPEC)
+fi
+AC_MSG_RESULT($sc_cv_struct_timespec)
+
+
+# struct linger; FreeBSD requires sys/types.h for sys/socket.h
+AC_MSG_CHECKING(for struct linger)
+AC_CACHE_VAL(sc_cv_struct_linger,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>],[struct linger s;],
+[sc_cv_struct_linger=yes],
+[sc_cv_struct_linger=no])])
+if test $sc_cv_struct_linger = yes; then
+ AC_DEFINE(HAVE_STRUCT_LINGER)
+fi
+AC_MSG_RESULT($sc_cv_struct_linger)
+
+
+# struct ip_mreq (for multicasting options)
+AC_MSG_CHECKING(for struct ip_mreq)
+AC_CACHE_VAL(sc_cv_struct_ip_mreq,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>],[struct ip_mreq s;],
+[sc_cv_struct_ip_mreq=yes],
+[sc_cv_struct_ip_mreq=no])])
+if test $sc_cv_struct_ip_mreq = yes; then
+ AC_DEFINE(HAVE_STRUCT_IP_MREQ)
+fi
+AC_MSG_RESULT($sc_cv_struct_ip_mreq)
+
+# struct ip_mreqn (for multicasting options)
+AC_MSG_CHECKING(for struct ip_mreqn)
+AC_CACHE_VAL(sc_cv_struct_ip_mreqn,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/ip.h>],[struct ip_mreqn s;],
+[sc_cv_struct_ip_mreqn=yes],
+[sc_cv_struct_ip_mreqn=no])])
+if test $sc_cv_struct_ip_mreqn = yes; then
+ AC_DEFINE(HAVE_STRUCT_IP_MREQN)
+fi
+AC_MSG_RESULT($sc_cv_struct_ip_mreqn)
+
+# struct ipv6_mreq (for multicasting options)
+AC_MSG_CHECKING(for struct ipv6_mreq)
+AC_CACHE_VAL(sc_cv_struct_ipv6_mreq,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>],[struct ipv6_mreq s;],
+[sc_cv_struct_ipv6_mreq=yes],
+[sc_cv_struct_ipv6_mreq=no])])
+if test $sc_cv_struct_ipv6_mreq = yes; then
+ AC_DEFINE(HAVE_STRUCT_IPV6_MREQ)
+fi
+AC_MSG_RESULT($sc_cv_struct_ipv6_mreq)
+
+
+# struct ifreq (for network interfaces)
+AC_MSG_CHECKING(for struct ifreq)
+AC_CACHE_VAL(sc_cv_struct_ifreq,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>],[struct ifreq s;],
+[sc_cv_struct_ifreq=yes],
+[sc_cv_struct_ifreq=no])])
+if test $sc_cv_struct_ifreq = yes; then
+ AC_DEFINE(HAVE_STRUCT_IFREQ)
+fi
+AC_MSG_RESULT($sc_cv_struct_ifreq)
+
+# struct ifreq.ifr_index
+# on most systems that have struct ifreq
+AC_MSG_CHECKING(for struct ifreq.ifr_index)
+AC_CACHE_VAL(sc_cv_struct_ifreq_ifr_index,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>],
+[struct ifreq ir;ir.ifr_index=0;],
+[sc_cv_struct_ifreq_ifr_index=yes],
+[sc_cv_struct_ifreq_ifr_index=no])])
+if test $sc_cv_struct_ifreq_ifr_index = yes; then
+ AC_DEFINE(HAVE_STRUCT_IFREQ_IFR_INDEX)
+fi
+AC_MSG_RESULT($sc_cv_struct_ifreq_ifr_index)
+
+# struct ifreq.ifr_ifindex
+# Linux has ifr_ifindex instead of ifr_index
+AC_MSG_CHECKING(for struct ifreq.ifr_ifindex)
+AC_CACHE_VAL(sc_cv_struct_ifreq_ifr_ifindex,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>],
+[struct ifreq ir;ir.ifr_ifindex=0;],
+[sc_cv_struct_ifreq_ifr_ifindex=yes],
+[sc_cv_struct_ifreq_ifr_ifindex=no])])
+if test $sc_cv_struct_ifreq_ifr_ifindex = yes; then
+ AC_DEFINE(HAVE_STRUCT_IFREQ_IFR_IFINDEX)
+fi
+AC_MSG_RESULT($sc_cv_struct_ifreq_ifr_ifindex)
+
+
+# some systems have a sa_len field in struct sockaddr and we need to support it
+# so we can compare sockaddrs simply with memcmp
+AC_MSG_CHECKING(for struct sockaddr.sa_len)
+AC_CACHE_VAL(sc_cv_struct_sockaddr_salen,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>],
+[struct sockaddr sa;sa.sa_len=0;],
+[sc_cv_struct_sockaddr_salen=yes],
+[sc_cv_struct_sockaddr_salen=no])])
+if test $sc_cv_struct_sockaddr_salen = yes; then
+ AC_DEFINE(HAVE_STRUCT_SOCKADDR_SALEN)
+fi
+AC_MSG_RESULT($sc_cv_struct_sockaddr_salen)
+
+### IP6 sockaddr_in6
+
+AC_MSG_CHECKING(for component names of sockaddr_in6)
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>],
+[struct sockaddr_in6 sa6;sa6.sin6_addr.s6_addr[0]=0;],
+[AC_MSG_RESULT(s6_addr);
+ AC_DEFINE(HAVE_IP6_SOCKADDR, 0)],
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>],
+ [struct sockaddr_in6 sa6;sa6.sin6_addr.u6_addr.u6_addr16[0]=0;],
+ [AC_MSG_RESULT(u6_addr.u6_addr16);
+ AC_DEFINE(HAVE_IP6_SOCKADDR, 1)],
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>],
+ [struct sockaddr_in6 sa6;sa6.sin6_addr.u6_addr16[0]=0;],
+ [AC_MSG_RESULT(u6_addr16); AC_DEFINE(HAVE_IP6_SOCKADDR, 2)],
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>],
+ [struct sockaddr_in6 sa6;sa6.sin6_addr.in6_u.u6_addr16[0]=0;],
+ [AC_MSG_RESULT(in6_u.u6_addr16);
+ AC_DEFINE(HAVE_IP6_SOCKADDR, 3)],
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>],
+ [struct sockaddr_in6 sa6;sa6.sin6_addr._S6_un._S6_u32[0]=0;],
+ [AC_MSG_RESULT(_S6_un._S6_u32);
+ AC_DEFINE(HAVE_IP6_SOCKADDR, 4)],
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>],
+ [struct sockaddr_in6 sa6;sa6.sin6_addr.__u6_addr.__u6_addr32[0]=0;],
+ [AC_MSG_RESULT(__u6_addr.__u6_addr32);
+ AC_DEFINE(HAVE_IP6_SOCKADDR, 5)],
+
+ [AC_MSG_RESULT([none or unknown])]
+)])])])])])
+
+dnl Check for struct iovec
+AC_MSG_CHECKING(for struct iovec)
+AC_CACHE_VAL(sc_cv_struct_iovec,
+[AC_TRY_COMPILE([#include <sys/uio.h>],[struct iovec s;],
+[sc_cv_struct_iovec=yes],
+[sc_cv_struct_iovec=no])])
+if test $sc_cv_struct_iovec = yes; then
+ AC_DEFINE(HAVE_STRUCT_IOVEC)
+fi
+AC_MSG_RESULT($sc_cv_struct_iovec)
+
+dnl check for msg_control in struct msghdr
+AC_MSG_CHECKING(for struct msghdr.msg_control)
+AC_CACHE_VAL(sc_cv_struct_msghdr_msgcontrol,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>],
+[struct msghdr s;s.msg_control=0;],
+[sc_cv_struct_msghdr_msgcontrol=yes],
+[sc_cv_struct_msghdr_msgcontrol=no])])
+if test $sc_cv_struct_msghdr_msgcontrol = yes; then
+ AC_DEFINE(HAVE_STRUCT_MSGHDR_MSGCONTROL)
+fi
+AC_MSG_RESULT($sc_cv_struct_msghdr_msgcontrol)
+
+dnl check for msg_controllen in struct msghdr
+AC_MSG_CHECKING(for struct msghdr.msg_controllen)
+AC_CACHE_VAL(sc_cv_struct_msghdr_msgcontrollen,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>],
+[struct msghdr s;s.msg_controllen=0;],
+[sc_cv_struct_msghdr_msgcontrollen=yes],
+[sc_cv_struct_msghdr_msgcontrollen=no])])
+if test $sc_cv_struct_msghdr_msgcontrollen = yes; then
+ AC_DEFINE(HAVE_STRUCT_MSGHDR_MSGCONTROLLEN)
+fi
+AC_MSG_RESULT($sc_cv_struct_msghdr_msgcontrollen)
+
+dnl check for msg_flags in struct msghdr
+AC_MSG_CHECKING(for struct msghdr.msgflags)
+AC_CACHE_VAL(sc_cv_struct_msghdr_msgflags,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>],
+[struct msghdr s;s.msg_flags=0;],
+[sc_cv_struct_msghdr_msgflags=yes],
+[sc_cv_struct_msghdr_msgflags=no])])
+if test $sc_cv_struct_msghdr_msgflags = yes; then
+ AC_DEFINE(HAVE_STRUCT_MSGHDR_MSGFLAGS)
+fi
+AC_MSG_RESULT($sc_cv_struct_msghdr_msgflags)
+
+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,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>],
+[struct ip s;s.ip_hl=0;],
+[sc_cv_struct_ip_ip_hl=yes],
+[sc_cv_struct_ip_ip_hl=no])])
+if test $sc_cv_struct_ip_ip_hl = yes; then
+ AC_DEFINE(HAVE_STRUCT_IP_IP_HL)
+fi
+AC_MSG_RESULT($sc_cv_struct_ip_ip_hl)
+
+
+dnl Library function checks
+
+dnl Check sigaction()
+AC_CHECK_FUNC(sigaction, AC_DEFINE(HAVE_SIGACTION))
+
+dnl Check for 64bit versions of system calls
+AC_CHECK_FUNC(stat64, AC_DEFINE(HAVE_STAT64))
+AC_CHECK_FUNC(fstat64, AC_DEFINE(HAVE_FSTAT64))
+AC_CHECK_FUNC(lstat64, AC_DEFINE(HAVE_LSTAT64))
+AC_CHECK_FUNC(lseek64, AC_DEFINE(HAVE_LSEEK64))
+AC_CHECK_FUNC(truncate64, AC_DEFINE(HAVE_TRUNCATE64))
+AC_CHECK_FUNC(ftruncate64, AC_DEFINE(HAVE_FTRUNCATE64))
+
+AC_CHECK_FUNC(strtoll, AC_DEFINE(HAVE_STRTOLL))
+AC_CHECK_FUNC(hstrerror, AC_DEFINE(HAVE_HSTRERROR))
+AC_CHECK_FUNC(inet_ntop, AC_DEFINE(HAVE_INET_NTOP))
+
+#if test "$ac_cv_func_hstrerror" = "yes"; then
+# AC_MSG_CHECKING(if _XOPEN_SOURCE_EXTENDED is helpful)
+# AC_CACHE_VAL(ac_cv_xopen_source_extended,
+# [AC_TRY_COMPILE([#include <netdb.h>],
+# [hstrerror()],
+# [ac_cv_xopen_source_extended=no],
+# [AC_TRY_COMPILE([#define _XOPEN_SOURCE_EXTENDED 1
+## include <netdb.h>],
+# [hstrerror()],
+# [ac_cv_xopen_source_extended=yes],
+# [ac_cv_xopen_source_extended=no]
+# )]
+# )])
+# if test $ac_cv_xopen_source_extended = yes; then
+# AC_DEFINE(_XOPEN_SOURCE_EXTENDED)
+# fi
+# AC_MSG_RESULT($ac_cv_xopen_source_extended)
+#fi
+
+dnl Search for openpty()
+# MacOS
+AC_CHECK_FUNC(openpty, AC_DEFINE(HAVE_OPENPTY))
+# AIX
+AC_CHECK_LIB(bsd, openpty,
+ [LIBS="-lbsd $LIBS"; AC_DEFINE(HAVE_OPENPTY)])
+# Linux 2.4
+AC_CHECK_LIB(util, openpty,
+ [LIBS="-lutil $LIBS"; AC_DEFINE(HAVE_OPENPTY)])
+
+dnl Search for flock()
+# with Linux it's in libc, with AIX in libbsd
+AC_CHECK_FUNC(flock, AC_DEFINE(HAVE_FLOCK),
+ AC_CHECK_LIB(bsd, flock, [LIBS="-lbsd $LIBS"]))
+
+dnl Search for setenv()
+AC_CHECK_FUNC(setenv, AC_DEFINE(HAVE_SETENV),
+ AC_CHECK_LIB(isode, setenv, [LIBS="-lisode $LIBS"]))
+
+
+dnl Run time checks
+
+
+AC_MSG_CHECKING(if printf has Z modifier)
+AC_CACHE_VAL(ac_cv_have_z_modifier,
+[AC_TRY_RUN([
+#include <stdio.h>
+main(){
+char s[16];
+sprintf(s,"%Zu",1);
+exit(strcmp(s,"1"));
+}],
+[ac_cv_have_z_modifier=yes],
+[ac_cv_have_z_modifier=no],
+[ac_cv_have_z_modifier=no])])
+if test $ac_cv_have_z_modifier = yes; then
+ AC_DEFINE(HAVE_FORMAT_Z)
+fi
+AC_MSG_RESULT($ac_cv_have_z_modifier)
+
+
+dnl find the number of bits we must shift a value to match the given mask
+dnl (e.g., mask 0x00f0 requires shifting with 4)
+## NOTE: some platforms only need on '\' to escape '"' in string constant
+define(AC_SHIFT_OFFSET,[
+AC_CACHE_CHECK(shift offset of $1, $2,
+[LIBS1="$LIBS"; LIBS="" # avoid libwrap allow_severity undefined
+ conftestoffset="conftestoffset.out"
+ AC_TRY_RUN([
+ #include <errno.h>
+ #include <stdio.h>
+ #include <termios.h>
+ #include <string.h>
+ main(){
+ unsigned int i,n=$1;
+ FILE *f;
+ if ((f=fopen("$conftestoffset","w"))==NULL){
+ fprintf(stderr,"\\"$conftestoffset\\": %s\n",strerror(errno)); exit(-1);
+ }
+ if (n==0) {fprintf(stderr,"$1 is 0 (impossible!)\n"); exit(1);}
+ i=0; while (!(n&1)) {
+ n>>=1; ++i; }
+ fprintf(f, "%u", i);
+ exit(0);
+ }
+ ],
+ [$2=`cat $conftestoffset`],
+ [$2=-1],
+ [AC_MSG_RESULT(please determine $1_SHIFT manually)]
+)
+ LIBS="$LIBS1"])
+AC_DEFINE_UNQUOTED($1_SHIFT, ${$2})
+])
+
+AC_SHIFT_OFFSET(CRDLY, sc_cv_sys_crdly_shift)
+AC_SHIFT_OFFSET(TABDLY, sc_cv_sys_tabdly_shift)
+AC_SHIFT_OFFSET(CSIZE, sc_cv_sys_csize_shift)
+
+
+dnl find what physical type (basic C type) is equivalent to the given type.
+dnl arg1: include file(s)
+dnl arg2: type name
+dnl arg3: output variable
+dnl arg4: cache variable (might be constructed automatically)
+dnl output values: 1..short, 2..unsigned short, 3..int, 4..u-int,
+dnl 5..long, 6..u-long; others not yet supported
+define(AC_BASIC_TYPE,[
+AC_CACHE_CHECK(for equivalent simple type of $2, $4,
+[CFLAGS1="$CFLAGS"; CFLAGS="-Werror -O0 $CFLAGS1"
+ AC_TRY_COMPILE([$1],[$2 u; short v; &u==&v;],
+ [$4="1 /* short */"],
+ [AC_TRY_COMPILE([$1],[$2 u; unsigned short v; &u==&v;],
+ [$4="2 /* unsigned short */"],
+ [AC_TRY_COMPILE([$1],[$2 u; int v; &u==&v;],
+ [$4="3 /* int */"],
+ [AC_TRY_COMPILE([$1],[$2 u; unsigned int v; &u==&v;],
+ [$4="4 /* unsigned int */"],
+ [AC_TRY_COMPILE([$1],[$2 u; long v; &u==&v;],
+ [$4="5 /* long */"],
+ [AC_TRY_COMPILE([$1],[$2 u; unsigned long v; &u==&v;],
+ [$4="6 /* unsigned long */"],
+ [AC_TRY_COMPILE([$1],[$2 u; long long v; &u==&v;],
+ [$4="7 /* long long */"],
+ [AC_TRY_COMPILE([$1],[$2 u; unsigned long long v; &u==&v;],
+ [$4="8 /* unsigned long long */"],
+ [$4="0 /* unknown, taking default */"
+]) ]) ]) ]) ]) ]) ]) ])
+ CFLAGS="$CFLAGS1" ])
+AC_DEFINE_UNQUOTED($3, ${$4})
+])
+
+dnl find what physical type (basic C type) describes the given struct or union
+dnl component.
+dnl arg1: include file(s); must declare the structure type
+dnl arg2: struct name (e.g., "struct stat")
+dnl arg3: variable or component (e.g., "st_ino")
+dnl arg4: output variable, values see AC_BASIC_TYPE
+dnl arg5: cache variable (might be constructed automatically)
+define(AC_TYPEOF_COMPONENT,[
+AC_CACHE_CHECK(for basic type of $2.$3, $5,
+[CFLAGS1="$CFLAGS"; CFLAGS="-Werror -O0 $CFLAGS1"
+AC_TRY_COMPILE([$1],[$2 u;short v; &u.$3==&v;],
+[$5="1 /* short */"],
+[AC_TRY_COMPILE([$1],[$2 u; unsigned short v; &u.$3==&v;],
+ [$5="2 /* unsigned short */"],
+ [AC_TRY_COMPILE([$1],[$2 u; int v; &u.$3==&v;],
+ [$5="3 /* int */"],
+ [AC_TRY_COMPILE([$1],[$2 u; unsigned int v; &u.$3==&v;],
+ [$5="4 /* unsigned int */"],
+ [AC_TRY_COMPILE([$1],[$2 u; long v; &u.$3==&v;],
+ [$5="5 /* long */"],
+ [AC_TRY_COMPILE([$1],[$2 u; unsigned long v; &u.$3==&v;],
+ [$5="6 /* unsigned long */"],
+ [AC_TRY_COMPILE([$1],[$2 u; long long v; &u.$3==&v;],
+ [$5="7 /* long long */"],
+ [AC_TRY_COMPILE([$1],[$2 u; unsigned long long v; &u.$3==&v;],
+ [$5="8 /* unsigned long long */"],
+ [$5="0 /* unknown, taking default */"
+]) ]) ]) ]) ]) ]) ]) ])
+ CFLAGS="$CFLAGS1" ])
+AC_DEFINE_UNQUOTED($4, ${$5})
+])
+
+AC_BASIC_TYPE([#include <stdlib.h>], size_t, HAVE_BASIC_SIZE_T, sc_cv_type_sizet_basic)
+AC_BASIC_TYPE([#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>], mode_t, HAVE_BASIC_MODE_T, sc_cv_type_modet_basic)
+AC_BASIC_TYPE([#include <sys/types.h>
+#include <unistd.h>], pid_t, HAVE_BASIC_PID_T, sc_cv_type_pidt_basic)
+AC_BASIC_TYPE([#include <sys/types.h>
+#include <unistd.h>], uid_t, HAVE_BASIC_UID_T, sc_cv_type_uidt_basic)
+AC_BASIC_TYPE([#include <sys/types.h>
+#include <unistd.h>], gid_t, HAVE_BASIC_GID_T, sc_cv_type_gidt_basic)
+
+AC_BASIC_TYPE([#include <time.h>], time_t, HAVE_BASIC_TIME_T,
+ sc_cv_type_timet_basic)
+
+# this is questionable, might fail on some systems
+AC_BASIC_TYPE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>], socklen_t, HAVE_BASIC_SOCKLEN_T,
+ sc_cv_type_socklent_basic)
+
+AC_BASIC_TYPE([#include <sys/types.h>
+#include <unistd.h>], off64_t, HAVE_BASIC_OFF64_T, sc_cv_type_off64_basic)
+
+# oh god, __dev_t in Linux 2.4 is struct{int[2];}, not handled here yet.
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat, st_dev, HAVE_TYPEOF_ST_DEV, sc_cv_type_stat_stdev_basic)
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat, st_ino, HAVE_TYPEOF_ST_INO, sc_cv_type_stat_stino_basic)
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat, st_nlink, HAVE_TYPEOF_ST_NLINK, sc_cv_type_stat_stnlink_basic)
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat, st_size, HAVE_TYPEOF_ST_SIZE, sc_cv_type_stat_stsize_basic)
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat, st_blksize, HAVE_TYPEOF_ST_BLKSIZE, sc_cv_type_stat_stblksize_basic)
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat, st_blocks, HAVE_TYPEOF_ST_BLOCKS, sc_cv_type_stat_stblocks_basic)
+#
+if test "$ac_cv_func_stat64" = yes; then
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat64, st_dev, HAVE_TYPEOF_ST64_DEV, sc_cv_type_stat64_stdev_basic)
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat64, st_ino, HAVE_TYPEOF_ST64_INO, sc_cv_type_stat64_stino_basic)
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat64, st_nlink, HAVE_TYPEOF_ST64_NLINK, sc_cv_type_stat64_stnlink_basic)
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat64, st_size, HAVE_TYPEOF_ST64_SIZE, sc_cv_type_stat64_stsize_basic)
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat64, st_blksize, HAVE_TYPEOF_ST64_BLKSIZE, sc_cv_type_stat64_stblksize_basic)
+AC_TYPEOF_COMPONENT([#include <sys/stat.h>], struct stat64, st_blocks, HAVE_TYPEOF_ST64_BLOCKS, sc_cv_type_stat64_stblocks_basic)
+fi
+
+AC_TYPEOF_COMPONENT([#include <sys/time.h>], struct timeval, tv_usec, HAVE_TYPEOF_STRUCT_TIMEVAL_TVUSEC, sc_cv_type_struct_timeval_tvusec)
+
+AC_TYPEOF_COMPONENT([#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>],
+struct rlimit, rlim_max, HAVE_TYPEOF_RLIM_MAX, sc_cv_type_rlimit_rlimmax_basic)
+
+### snprintf, vsnprintf
+
+
+AC_MSG_CHECKING(for /dev/ptmx)
+if test -c /dev/ptmx; then
+ AC_DEFINE(HAVE_DEV_PTMX, 1)
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING(for /dev/ptc)
+ if test -c /dev/ptc; then
+ AC_DEFINE(HAVE_DEV_PTC)
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+fi
+
+AC_MSG_CHECKING(for /proc)
+if test -d /proc; then
+ AC_DEFINE(HAVE_PROC_DIR, 1)
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_MSG_CHECKING(for /proc/*/fd)
+if test -d /proc/$$/fd; then
+ AC_DEFINE(HAVE_PROC_DIR_FD, 1)
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
+dnl "tcpd" "tcpwrappers"
+# on some platforms, raw linking with libwrap fails because allow_severity and
+# deny_severity are not explicitely defined. Thus we put the libwrap part to
+# the end
+AC_MSG_CHECKING(whether to include libwrap support)
+AC_ARG_ENABLE(libwrap, [ --disable-libwrap disable libwrap support],
+ [ case "$enableval" in
+ no) AC_MSG_RESULT(no); WITH_LIBWRAP= ;;
+ *) AC_MSG_RESULT(yes); WITH_LIBWRAP=1 ;;
+ esac],
+ [ AC_MSG_RESULT(yes); WITH_LIBWRAP=1 ])
+#
+# check if we find the components of libwrap ("tcpd" "tcpwrappers")
+if test -n "$WITH_LIBWRAP"; then
+ AC_MSG_NOTICE(checking for components of libwrap)
+ # first, we need to find the include file <tcpd.h>
+ AC_CACHE_VAL(sc_cv_have_tcpd_h,
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <tcpd.h>],[;],
+ [sc_cv_have_tcpd_h=yes; LIBWRAP_ROOT=""],
+ [sc_cv_have_tcpd_h=no
+ for D in "/sw" "/usr/local" "/opt/freeware" "/usr/sfw"; do
+ I="$D/include"
+ i="$I/tcpd.h"
+ if test -r "$i"; then
+ #V_INCL="$V_INCL -I$I"
+ CPPFLAGS="$CPPFLAGS -I$I"
+ AC_MSG_NOTICE(found $i)
+ sc_cv_have_tcpd_h=yes; LIBWRAP_ROOT="$D"
+ break;
+ fi
+ done])
+ ])
+ if test "$sc_cv_have_tcpd_h" = "yes"; then
+ AC_DEFINE(HAVE_TCPD_H)
+ fi
+ AC_MSG_NOTICE(checked for tcpd.h... $sc_cv_have_tcpd_h)
+fi # end checking for tcpd.h
+if test -n "$WITH_LIBWRAP" -a "$sc_cv_have_tcpd_h" = yes; then
+ # next, we search for the wrap library (libwrap.*)
+ AC_MSG_CHECKING(for libwrap)
+ AC_CACHE_VAL(sc_cv_have_libwrap,
+ [ LIBS0="$LIBS"
+ if test -n "$LIBWRAP_ROOT"; then
+ L="$LIBWRAP_ROOT/lib"; LIBS="-L$L -lwrap $LIBS"
+ else
+ LIBS="-lwrap $LIBS"
+ fi
+ AC_TRY_LINK([#include <sys/types.h>
+#include <tcpd.h>
+int allow_severity,deny_severity;],[hosts_access(0)],
+ [sc_cv_have_libwrap='yes'],
+ [sc_cv_have_libwrap='no'
+ LIBS="$LIBS -lnsl" # RedHat73
+ AC_TRY_LINK([#include <sys/types.h>
+#include <tcpd.h>
+int allow_severity,deny_severity;],[hosts_access(0)],
+ [sc_cv_have_libwrap='yes'],
+ [sc_cv_have_libwrap='no'])
+ ]
+ )
+ if test "$sc_cv_have_libwrap" != 'yes'; then
+ LIBS="$LIBS0"
+ fi
+ ]
+ )
+ if test "$sc_cv_have_libwrap" = 'yes'; then
+ AC_DEFINE(HAVE_LIBWRAP)
+ fi
+ AC_MSG_RESULT($sc_cv_have_libwrap)
+fi
+#
+if test -n "$WITH_LIBWRAP"; then
+ if test "$sc_cv_have_tcpd_h" = "yes" -a "$sc_cv_have_libwrap" = "yes"; then
+ AC_DEFINE(WITH_LIBWRAP)
+ else
+ AC_MSG_WARN([not all components of tcp wrappers found, disabling it]);
+ fi
+fi
+
+# check of hosts_allow_table
+if test -n "$WITH_LIBWRAP"; then
+ AC_MSG_CHECKING(checking for hosts_allow_table)
+ AC_CACHE_VAL(sc_cv_have_hosts_allow_table,
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <tcpd.h>],[hosts_allow_table="";],
+ [sc_cv_have_hosts_allow_table=yes],
+ [sc_cv_have_hosts_allow_table=no])])
+ if test $sc_cv_have_hosts_allow_table = yes; then
+ AC_DEFINE(HAVE_HOSTS_ALLOW_TABLE)
+ fi
+ AC_MSG_RESULT($sc_cv_have_hosts_allow_table)
+fi # test -n "$WITH_LIBWRAP"
+
+
+if test "$GCC" = yes; then
+ CFLAGS="$CFLAGS"
+fi
+
+# FIPS support requires compiling with fipsld.
+# fipsld requires the FIPSLD_CC variable to be set to the original CC.
+# This check must be done after all other checks that require compiling
+# so that fipsld is not used by the configure script itself.
+if test -n "$WITH_FIPS"; then
+ if test "$sc_cv_have_openssl_fips_h" = 'yes' -a "$sc_cv_have_libcrypto" = 'yes'; then
+ FIPSLD_CC=$CC
+ if test "${FIPSLD+set}" != set ; then
+ FIPSLD=fipsld
+ fi
+ CC="FIPSLD_CC=$CC $FIPSLD"
+ fi
+fi
+AC_SUBST(FIPSLD_CC)
+
+AC_OUTPUT(Makefile)
diff --git a/daemon.sh b/daemon.sh
new file mode 100755
index 0000000..fd7aa14
--- /dev/null
+++ b/daemon.sh
@@ -0,0 +1,34 @@
+#! /bin/sh
+# $Id: daemon.sh,v 1.4 2001/10/29 09:52:47 gerhard Exp $
+# Copyright Gerhard Rieger 2001
+# Published under the GNU General Public License V.2, see file COPYING
+
+# This script assumes that you create group daemon1 and user daemon1 before.
+# they need only the right to exist (no login etc.)
+
+# Note: this pid file mechanism is not robust!
+
+# You will adapt these variables
+USER=daemon1
+GROUP=daemon1
+INIF=fwnonsec.domain.org
+OUTIF=fwsec.domain.org
+TARGET=w3.intra.domain.org
+INPORT=80
+DSTPORT=80
+#
+INOPTS="fork,setgid=$GROUP,setuid=$USER"
+OUTOPTS=
+PIDFILE=/var/run/socat-$INPORT.pid
+OPTS="-d -d -lm" # notice to stderr, then to syslog
+SOCAT=/usr/local/bin/socat
+
+if [ "$1" = "start" -o -z "$1" ]; then
+
+ $SOCAT $OPTS tcp-l:$INPORT,bind=$INIF,$INOPTS tcp:$TARGET:$DSTPORT,bind=$OUTIF,$OUTOPTS </dev/null &
+ echo $! >$PIDFILE
+
+elif [ "$1" = "stop" ]; then
+
+ /bin/kill $(/bin/cat $PIDFILE)
+fi
diff --git a/dalan.c b/dalan.c
new file mode 100644
index 0000000..2313ee2
--- /dev/null
+++ b/dalan.c
@@ -0,0 +1,224 @@
+/* $Id: dalan.c,v 1.8 2004/06/20 21:49:11 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2004 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* idea of a low level data description language. currently only a most
+ primitive subset exists. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "dalan.h"
+
+/* test structure to find maximal alignment */
+static struct {
+ char a;
+ long double b;
+} maxalign;
+
+/* test structure to find minimal alignment */
+static struct {
+ char a;
+ char b;
+} minalign;
+
+/* test union to find kind of byte ordering */
+static union {
+ char a[2];
+ short b;
+} byteorder = { "01" };
+
+struct dalan_opts_s dalan_opts = {
+ sizeof(int),
+ sizeof(short),
+ sizeof(long),
+ sizeof(char),
+ sizeof(float),
+ sizeof(double)
+} ;
+
+/* fill the dalan_opts structure with machine dependent defaults values. */
+static void _dalan_dflts(struct dalan_opts_s *dlo) {
+ dlo->c_int = sizeof(int);
+ dlo->c_short = sizeof(short);
+ dlo->c_long = sizeof(long);
+ dlo->c_char = sizeof(char);
+ dlo->c_float = sizeof(float);
+ dlo->c_double = sizeof(double);
+ dlo->maxalign = (char *)&maxalign.b-&maxalign.a;
+ dlo->minalign = &minalign.b-&minalign.a;
+ dlo->byteorder = (byteorder.b!=7711);
+}
+
+/* allocate a new dalan_opts structure, fills it with machine dependent
+ defaults values, and returns the pointer. */
+struct dalan_opts_s *dalan_props(void) {
+ struct dalan_opts_s *dlo;
+ dlo = malloc(sizeof(struct dalan_opts_s));
+ if (dlo == NULL) {
+ return NULL;
+ }
+ _dalan_dflts(dlo);
+ return dlo;
+}
+
+void dalan_init(void) {
+ _dalan_dflts(&dalan_opts);
+}
+
+/* read data description from line, write result to data; do not write
+ so much data that *p exceeds n !
+ return 0 on success,
+ -1 if the data was cut due to n limit,
+ 1 if a syntax error occurred
+ *p is a global data counter; especially it must be used when calculating
+ alignment. On successful return from the function *p must be actual!
+*/
+int dalan(const char *line, char *data, size_t *p, size_t n) {
+ int align, mask, i, x;
+ size_t p1 = *p;
+ char c;
+
+ fputs(line, stderr); fputc('\n', stderr);
+ while (c = *line++) {
+ switch (c) {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ break;
+ case ',':
+ align = 2;
+ while (*line == ',') {
+ align <<= 1;
+ ++line;
+ }
+ mask = align - 1; /* create the bitmask */
+ i = (align - (p1 & mask)) & mask;
+ while (i && p1<n) data[p1++] = 0, --i;
+ if (i) { *p = p1; return -1; }
+ break;
+ case ';':
+ align = dalan_opts.c_int;
+ mask = align - 1;
+ i = (align - (p1 & mask)) & mask;
+ while (i && p1<n) data[p1++] = 0, --i;
+ if (i) { *p = p1; return -1; }
+ break;
+ case '"':
+ while (1) {
+ switch (c = *line++) {
+ case '\0': fputs("unterminated string\n", stderr);
+ return 1;
+ case '"':
+ break;
+ case '\\':
+ if (!(c = *line++)) {
+ fputs("continuation line not implemented\n", stderr);
+ return 1;
+ }
+ switch (c) {
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'f': c = '\f'; break;
+ case 'b': c = '\b'; break;
+ case 'a': c = '\a'; break;
+#if 0
+ case 'e': c = '\e'; break;
+#else
+ case 'e': c = '\033'; break;
+#endif
+ case '0': c = '\0'; break;
+ }
+ /* PASSTHROUGH */
+ default:
+ if (p1 >= n) { *p = p1; return -1; }
+ data[p1++] = c;
+ continue;
+ }
+ if (c == '"')
+ break;
+ }
+ break;
+ case '\'':
+ switch (c = *line++) {
+ case '\0': fputs("unterminated character\n", stderr);
+ return 1;
+ case '\'': fputs("error in character\n", stderr);
+ return 1;
+ case '\\':
+ if (!(c = *line++)) {
+ fputs("continuation line not implemented\n", stderr);
+ return 1;
+ }
+ switch (c) {
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'f': c = '\f'; break;
+ case 'b': c = '\b'; break;
+ case 'a': c = '\a'; break;
+#if 0
+ case 'e': c = '\e'; break;
+#else
+ case 'e': c = '\033'; break;
+#endif
+ }
+ /* PASSTHROUGH */
+ default:
+ if (p1 >= n) { *p = p1; return -1; }
+ data[p1++] = c;
+ break;
+ }
+ if (*line != '\'') {
+ fputs("error in character termination\n", stderr);
+ *p = p1; return 1;
+ }
+ ++line;
+ break;
+#if LATER
+ case '0':
+ c = *line++;
+ if (c == 'x') {
+ /* hexadecimal */ ;
+ } else if (isdigit(c&0xff)) {
+ /* octal */
+ } else {
+ /* it was only 0 */
+ }
+ break;
+#endif /* LATER */
+ case 'x':
+ /* expecting hex data, must be an even number of digits!! */
+ while (true) {
+ c = *line;
+ if (isdigit(c&0xff)) {
+ x = (c-'0') << 4;
+ } else if (isxdigit(c&0xff)) {
+ x = ((c&0x07) + 9) << 4;
+ } else
+ break;
+ ++line;
+ c = *line;
+ if (isdigit(c&0xff)) {
+ x |= (c-'0');
+ } else if (isxdigit(c&0xff)) {
+ x |= (c&0x07) + 9;
+ } else {
+ fputs("odd number of hexadecimal digits\n", stderr);
+ *p = p1; return 1;
+ }
+ ++line;
+ if (p1 >= n) { *p = p1; return -1; }
+ data[p1++] = x;
+ }
+ break;
+ case 'A': case 'a':
+ case 'C': case 'c':
+ default: fprintf(stderr, "syntax error in \"%s\"\n", line-1);
+ return 1;
+ }
+ }
+ *p = p1; return 0;
+}
diff --git a/dalan.h b/dalan.h
new file mode 100644
index 0000000..5d8c44e
--- /dev/null
+++ b/dalan.h
@@ -0,0 +1,30 @@
+/* $Id: dalan.h,v 1.3 2001/06/30 14:02:39 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __dalan_h_included
+#define __dalan_h_included 1
+
+#include "mytypes.h"
+
+/* machine properties and command line options */
+struct dalan_opts_s {
+ int c_int; /* natural int size / C int size */
+ int c_short; /* C short size */
+ int c_long; /* C long size */
+ int c_char; /* C char size */
+ int c_float; /* C float size */
+ int c_double; /* C double size */
+ int maxalign; /* maximal alignment (double after char) */
+ int minalign; /* minimal alignment (char after char) */
+ int byteorder; /* 0: Motorola, network, big endian; 1: Intel, little
+ endian */
+} ;
+
+extern struct dalan_opts_s dalan_opts;
+
+extern void dalan_init(void);
+extern struct dalan_opts_s *dalan_props(void);
+extern int dalan(const char *line, char *data, size_t *p, size_t n);
+
+#endif /* !defined(__dalan_h_included) */
diff --git a/doc/dest-unreach.css b/doc/dest-unreach.css
new file mode 100644
index 0000000..b5dd82f
--- /dev/null
+++ b/doc/dest-unreach.css
@@ -0,0 +1,15 @@
+<!-- $Revision: 1.1 $ $Date: 2007/03/06 20:42:56 $ -->
+<html><head>
+<title>dest-unreach.org stylesheet</title>
+<style type="text/css">
+.frame { border-style:solid; border-width:4px; border-color:black; }
+.shell { font-family:Courier;
+ padding:2px; padding-left:6px; padding-right:6px;
+ border-style:solid; border-width:1px; border-color:gray;
+ color:lightgreen; background-color:black;
+}
+</style>
+</head>
+<body>
+</body>
+</html>
diff --git a/doc/socat-multicast.html b/doc/socat-multicast.html
new file mode 100644
index 0000000..fc31f7b
--- /dev/null
+++ b/doc/socat-multicast.html
@@ -0,0 +1,340 @@
+<!-- $Revision: 1.1 $ $Date: 2007/03/06 20:54:43 $ -->
+<html><head>
+<title>IP Multicasting with Socat</title>
+<link rel="stylesheet" type="text/css" href="dest-unreach.css">
+</head>
+
+<body>
+
+<h1>IP Multicasting with Socat</h1>
+
+<h2>Introduction</h2>
+<p>
+Multicasting (and broadcasting which is also discussed in this article)
+provides a means to direct a single packet to more than one host. Special
+addresses are defined for this purpose and are handled specially by network
+adapters, networking hardware, and IP stacks.
+</p>
+<p>
+IPv4 specifications provide broadcasting and multicasting; IPv6 provides
+multicasting but replaces broadcasting by special multicast modes. UNIX domain
+sockets do not know broadcasting or multicasting.
+</p>
+<p>
+The following examples use UDP/IPv4 only. However, they can easily be
+adapted for raw IPv4 sockets. IPv6 multicasting has not yet been successfully
+used with socat; please contact the author if you have positive experiences or
+ideas that go beyond <tt>IPV6_ADD_MEMBERSHIP</tt>.
+</p>
+<p>
+All multicast examples presented in this document use multicast address
+224.1.0.1; it can be replaced by any valid IPv4 multicast address (except
+<a href="#ALLSYSTEMS">all-systems</a>).
+</p>
+<p>
+We assume a local network with address 192.168.10.0 and mask 255.255.255.0; an
+eventual "client" has 192.168.10.1, example "server" and example peer have
+192.168.10.2 in all examples. Change these addresses and mask to your own
+requirements.
+</p>
+<p>
+All the following examples work bidirectionally except when otherwise noticed.
+For "clients" we just use <tt>STDIO</tt>, and for "servers" we use <tt>EXEC:hostname</tt> which
+ingores its input but shows us which host the reply comes from. Replace these
+addresses with what is appropriate for you (e.g. shell script
+invokations). Port 6666 can be replaced with any other port (but for ports <
+1024 root privilege might be required).
+</p>
+<p>
+Different kinds of broadcast addresses exist: 255.255.255.255 is local network
+only; for the IPv4 network 192.168.10.0/24 the "official" broadcast address
+is 192.168.10.255; the network address 192.168.10.0 is also interpreted as
+broadcast by some hosts. The two latter forms are routed by gateways. In the
+following examples we only use broadcast address 192.168.10.255.
+</p>
+
+<h2>Example 1: Multicast client and servers</h2>
+
+<p>This example builds something like a "supervisor" or "client" that
+communicates with a set of "servers". The supervisor may send packets to the
+multicast address, and the servers may send response packets. Note that the
+servers would also respond to other clients' requests.</p>
+
+<p>Multicast server:</p>
+
+<span class="frame"><span class="shell">
+socat UDP4-RECVFROM:6666,ip-add-membership=224.1.0.1:192.168.10.2,fork EXEC:hostname
+</span></span>
+<p>
+This command receives multicast packets addressed to 224.1.0.1 and forks a
+child process for each. The child processes may each send one or more reply
+packets back to the particular sender. 192.168.10.2 means the address of the
+interface where multicasts should be received.
+Run this command on a number of hosts, and they will all respond in
+parallel.</p>
+
+<p>Multicast client:</p>
+
+<span class="frame"><span class="shell">
+socat STDIO UDP4-DATAGRAM:224.1.0.1:6666,range=192.168.10.0/24
+</span></span>
+<p>
+This process transfers data from stdin to the multicast address, and transfers
+packets received from the local network to stdout. It does not matter in which
+direction the first data is passed.
+A packet from the network is accepted by the IP stack for our socket if:
+<ul>
+<li>it is an incoming UDP/IPv4 packet</li>
+<li>its target port matches the local port assigned to the socket (6666)</li>
+<li>its target address matches one of the hosts local addresses or the any-host
+multicast address</li>
+</ul>
+Of these packets, socat handles only those matching the following criteria:
+<ul>
+<li>the source address is within the given range</li>
+<li>the source port is 6666</li>
+</ul>
+</p>
+
+
+<h2>Example 2: Broadcast client and servers</h2>
+
+<p>Broadcast server:</p>
+
+<span class="frame"><span class="shell">
+socat UDP4-RECVFROM:6666,broadcast,fork EXEC:hostname
+</span></span>
+<p>
+This command receives packets addressed to a local broadcast address and forks
+a child process for each. The child processes may each send one or more reply
+packets back to the particular sender.
+Run this command on a number of hosts, and they will all respond in
+parallel.</p>
+
+<p>Broadcast client:</p>
+
+<span class="frame"><span class="shell">
+socat STDIO UDP4-DATAGRAM:192.168.10.255:6666,broadcast,range=192.168.10.0/24
+</span></span>
+<p>
+This process transfers data from stdin to the broadcast address, and transfers
+packets received from the local network to stdout. It does not matter in which
+direction the first data is passed.
+A packet from the network is accepted by the IP stack for our socket if:
+<ul>
+<li>it is an incoming UDP/IPv4 packet</li>
+<li>its target port matches the local port assigned to the socket (6666)</li>
+<li>its target address matches one of the hosts local addresses or the any-host
+multicast address, or a local broadcast address</li>
+</ul>
+Of these packets, socat handles only those matching the following criteria:
+<ul>
+<li>the source address is within the given range</li>
+<li>the source port is 6666</li>
+</ul>
+</p>
+<p>The <tt>broadcast</tt> option is only required for sending or receiving
+local broadcasts.</p>
+
+<h2>Example 3: Multicast peers</h2>
+
+<p>It is possible to combine multicast sender and receiver in one socat
+address. This allows to start processes on different hosts on the local network
+that will communicate symmetrically, so each process can send messages that are
+received by all the other ones.</p>
+
+<span class="frame"><span class="shell">
+socat STDIO UDP4-DATAGRAM:224.1.0.1:6666,bind=:6666,range=192.168.10.0/24,ip-add-membership=224.1.0.1:192.168.10.2
+</span></span>
+<p>
+This command is valid for host 192.168.10.2; adapt this address to the
+particular interface addresses of the hosts.
+</p>
+<p>
+Starting this process opens a socket on port 6666 that will receive packets
+directed to multicast address 224.1.0.1. Only packets with matching source
+address and source port 6666 will be handled though. When this process sends
+data to the network the packets will be addressed to 224.1.0.1:6666 and have a
+source address of 192.168.10.2:6666, matching the accept criteria of the peers
+on the local network.
+</p>
+
+<p>Note: this command receives the packets it just has sent; add option
+<tt>ip-multicast-loop=0</tt> if this in undesired.</p>
+
+<h2>Example 4: Broadcast peers</h2>
+
+<p>Just as with multicast, it is possible to combine broadcast sender and
+receiver in one socat address.</p>
+
+<span class="frame"><span class="shell">
+socat STDIO UDP4-DATAGRAM:255.255.255.255:6666,bind=:6666,range=192.168.10.0/24,broadcast
+</span></span>
+<p>
+Starting this process opens a socket on port 6666 that will receive packets
+directed to a local broadcast addresses. Only packets with matching source
+address and source port 6666 will be handled though. When this process sends
+data to the network the packets will be addressed to 255.255.255.255:6666 and
+have a source address of 192.168.10.2:6666, matching the accept criteria of
+the peers on the local network.
+</p>
+
+<p>Note: this command receives the packets it just has sent; there does not
+seem to exist a simple way to prevent this.</p>
+
+
+<h2>Troubleshooting</h2>
+
+<p>
+If you do not get an error message during operation, but the packets do not
+reach the target processes, use <tt>tcpdump</tt> to see if the packets have the
+correct source and destination addresses and ports, and if they leave and enter
+the hosts as expected.
+</p>
+<p>
+The following subsections discuss some typical sources of trouble.
+</p>
+
+<h3>IP filters</h3>
+<p>
+If you do not succeed in receiving multicast or broadcast packets, check if
+iptables are activated on the receiving or sending host. They might be
+configured to disallow this traffic.
+</p>
+
+<h3>Do not bind()</h3>
+<p>
+When using multicast communications, you should not bind the sockets to a
+specific IP address. It seems that the (Linux) IP stack compares the
+destination address with the bind address, not taking care of the multicast
+property of the incoming packet.
+</p>
+
+<h3>Routing</h3>
+<p>
+When you receive an error like:</p>
+<table border="1" bgcolor="#e08080"><tr><td><tt>... E sendto(3, 0x80c2e44, 4,
+0, AF=2 224.1.0.1:6666, 16): Network is unreachable</tt></td></tr></table>
+<p>you have a routing problem. The (Linux) IP stack seems to handle multicast
+addresses just like unicast addresses when determining their route (interface and gateway).</p>
+<p>
+For the same reason, multicast packets will probably leave your host on the
+interface with the default route.</p>
+<p>
+Set a multicast/broadcast route with the following command:</p>
+<span class="frame"><span class="shell">
+route add -net 224.0.0.0/3 gw 192.168.10.2
+</span></span>
+
+<h3>ALL-SYSTEMS multicast address</h3>
+<p>
+<a name="ALLSYSTEMS"><tt>224.0.0.1</tt></a> is the all-systems multicast address: all
+datagram sockets appear to be automatically member of this group on all
+interfaces. This membership cannot be dropped on Linux.
+</p>
+
+
+<h2>(In)Security</h2>
+
+<p>When you use the above examples you should understand that all datagram
+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.</p>
+
+<p>Authentication or encryption are not available.</p>
+
+<p>It is very easy to fake the source address of UDP (or raw IP) packets. You
+should understand whether your network is protected from address spoofing
+attacks.</p>
+
+<p>Broadcast and multicast traffic can trivially be received by <em>any</em>
+host on the local network.</p>
+
+
+<h2>History</h2>
+
+Starting with version 1.5.0, socat provides a set of address types that
+allow various operations on datagram oriented sockets:
+<dl>
+<dt>SENDTO</dt><dd>send packets to a remote socket and receive packet from this
+remote socket only</dd>
+<dt>RECV</dt><dd>receive all packets that arrive on the local socket, but do
+not reply</dd>
+<dt>RECVFROM</dt><dd>receive all packets that arrive on the local socket, and
+reply using child processes</dd>
+</dl>
+
+<p>
+These modes already enable several different client/server oriented operations.
+Moreover, the SENDTO addresses can send to multicast and broadcast addresses
+(the latter requires the <tt>broadcast</tt> option though). RECV and RECVFROM
+also would accept packets addressed to a local broadcast address (with option
+<tt>broadcast</tt>) or the all-systems multicast address.
+</p>
+
+<p>
+These address types had, however, two major caveats:
+<ul>
+<li>Missing control of multicast group membership in the RECV and RECVFROM
+addresses</li>
+<li>The SENDTO address would never accept a reply to a broadcast or multicast
+addressed packet because the source address of incoming replies would not match
+the target address of the sent packet.
+</ul>
+</p>
+
+<h3>New Features in socat 1.6.0</h3>
+
+<p>
+socat version 1.6.0 addresses these problems and provides a new more generic
+datagram address type (*-DATAGRAM) and the new address option IP-ADD-MEMBERSHIP.
+</p>
+
+<p>
+Please note that the new features could not be successfully tested on IPv6;
+these sections thus apply to IPv4 only.
+</p>
+
+<p>This document was last modified in March 2007.</p>
+
+<h2>More info about socat datagrams</h2>
+
+<h3>Links regarding this tutorial</h3>
+<a href="socat.html#ADDRESS_UDP4_DATAGRAM">address udp4-datagram</a><br>
+<a href="socat.html#ADDRESS_UDP4_RECVFROM">address udp4-recvfrom</a><br>
+<a href="socat.html#OPTION_RANGE">option range</a><br>
+<a href="socat.html#OPTION_SO_BROADCAST">option broadcast</a><br>
+<a href="socat.html#OPTION_IP_ADD_MEMBERSHIP">option ip-add-membership</a><br>
+<a href="socat.html#OPTION_FORK">option fork</a><br>
+<a href="socat.html#OPTION_BIND">option bind</a><br>
+
+<h3>Other datagram addresses</h3>
+<a href="socat.html#ADDRESS_UDP4_RECV">address udp4-recv</a>: pure datagram receiver<br>
+<a href="socat.html#ADDRESS_UDP4_SENDTO">address udp4-sendto</a>: communicate
+with one peer address<br>
+<a href="socat.html#ADDRESS_UDP4_LISTEN">address udp4-listen</a>: pseudo stream server<br>
+<a href="socat.html#ADDRESS_UDP4_CONNECT">address udp4-connect</a>: pseudo stream client<br>
+
+<h3>Related socat option groups</h3>
+<a href="socat.html#GROUP_IP">IP options</a><br>
+<a href="socat.html#GROUP_SOCKET">socket options</a><br>
+<a href="socat.html#GROUP_FD">file descriptor options</a><br>
+<a href="socat.html#GROUP_RANGE">range options</a><br>
+<a href="socat.html#GROUP_CHILD">child process options</a><br>
+
+
+<h2>References</h2>
+<a href="http://www.dest-unreach.org/socat">socat home page</a><br>
+<a href="socat.html">socat man page</a><br>
+<a href="http://en.wikipedia.org/wiki/Multicast">multicasting on Wikipedia</a><br>
+<a href="http://en.wikipedia.org/wiki/Broadcast_address">broadcasting on Wikipedia</a><br>
+
+<p>
+<small>Copyright: Gerhard Rieger 2007</small><br>
+<small>License: <a href="http://www.fsf.org/licensing/licenses/fdl.html">GNU Free Documentation License (FDL)</a></small>
+</p>
+
+</body>
+</html>
diff --git a/doc/socat-openssltunnel.html b/doc/socat-openssltunnel.html
new file mode 100644
index 0000000..e2ce0fc
--- /dev/null
+++ b/doc/socat-openssltunnel.html
@@ -0,0 +1,192 @@
+<!-- $Revision: 1.1 $ $Date: 2007/03/06 20:54:43 $ -->
+<html><head>
+<title>Securing Traffic Between two Socat Instances Using SSL</title>
+<link rel="stylesheet" type="text/css" href="dest-unreach.css">
+</head>
+
+<body>
+
+<h1>Securing Traffic Between two Socat Instances Using SSL</h1>
+
+<h2>Introduction</h2>
+<p>
+When you want to connect two socat processes running on different machines and
+feel that you need to protect the connection against unauthorized access,
+sniffing, data manipulation etc., you might want to encrypt the communications.
+</p>
+<p>
+For this purpose socat integrates the OpenSSL library and provides SSL client
+and server features.
+</p>
+<p>
+SSL is a complex protocol that provides much more features than required for
+protecting a single connection; in this document we present only a simple
+scenario that provides just the basic security requirements.
+</p>
+
+<!-- discussion -->
+<h2>Configuring OpenSSL in socat</h2>
+<p>
+This section shows how the SSL addresses can be configured in socat.
+In this docu we only use self signed certificates for the sake of simplicity.
+</p>
+<p>We assume that the server host is called <tt>server.domain.org</tt> and the
+server process uses port 4433. To keep it simple, we use a very simple server
+funtionality that just echos data (<tt>echo</tt>), and <tt>stdio</tt> on the
+client.</p>
+<h3>Generate a server certificate</h3>
+
+<p>Perform the following steps on a trusted host where OpenSSL is
+installed. It might as well be the client or server host themselves.</p>
+<p>Prepare a basename for the files related to the server certificate:</p>
+<span class="frame"><span class="shell">FILENAME=server</span></span>
+
+<p>Generate a public/private key pair:</p>
+<span class="frame"><span class="shell">openssl genrsa -out $FILENAME.key 1024</span></span>
+
+<p>Generate a self signed certificate:</p>
+<span class="frame"><span class="shell">
+openssl req -new -key $FILENAME.key -x509 -days 3653 -out $FILENAME.crt</span></span>
+<p>You will be prompted for your country code, name etc.; you may quit all prompts
+with the enter key.</p>
+<p>Generate the PEM file by just appending the key and certificate files:<p>
+<span class="frame"><span class="shell">cat $FILENAME.key $FILENAME.crt >$FILENAME.pem</span></span>
+
+<p>The files that contain the private key should be kept secret, thus adapt
+their permissions:<p>
+<span class="frame"><span class="shell">chmod 600 $FILENAME.key $FILENAME.pem</span></span>
+
+<p>Now bring the file <tt>server.pem</tt> to the SSL server, e.g. to directory
+<tt>$HOME/etc/</tt>, using a secure channel like USB memory stick or SSH. Keep
+tight permissions on the file even on the target host, and remove all other
+instances of <tt>server.key</tt> and <tt>server.pem</tt>.
+</p>
+<p>Copy the trust certificate server.crt to the SSL client host, e.g. to directory
+<tt>$HOME/etc/</tt>; a secure channel is not required here, and the permissions
+are not critical.
+</p>
+
+<h3>Generate a client certificate</h3>
+<p>First prepare a different basename for the files related to the client certificate:</p>
+<span class="frame"><span class="shell">FILENAME=client</span></span>
+
+<p>Repeat the procedure for certificate generation described above.
+Copy <tt>client.pem</tt> to the SSL client, and <tt>client.crt</tt> to the
+server.</p>
+
+<h3>OpenSSL Server</h3>
+
+<p>Instead of using a tcp-listen (tcp-l) address, we use openssl-listen (ssl-l)
+for the server, <tt>cert=...</tt> tells the program to the file containing its
+ceritificate and private key, and <tt>cafile=...</tt> points to the file
+containing the certificate of the peer; we trust clients only if they can proof
+that they have the related private key (OpenSSL handles this for us):<p>
+<span class="frame"><span class="shell">socat openssl-listen:4433,reuseaddr,cert=$HOME/etc/server.pem,cafile=$HOME/etc/client.crt echo</span></span>
+<p>After starting this command, socat should be listening on port 4433, but
+will require client authentication.</p>
+
+<h3>OpenSSL Client</h3>
+<p>Substitute your <tt>tcp-connect</tt> or <tt>tcp</tt> address keyword with
+<tt>openssl-connect</tt> or just <tt>ssl</tt> and here too add the
+<tt>cert</tt> and <tt>cafile</tt> options:<p>
+<span class="frame"><span class="shell">socat stdio openssl-connect:server.domain.org:4433,cert=$HOME/etc/client.pem,cafile=$HOME/etc/server.crt</span></span>
+<p>This command should establish a secured connection to the server
+process.</p>
+
+<h3>TCP/IP version 6</h3>
+
+<p>If the communication is to go over IPv6, the above described commands have
+to be adapted; <tt>ip6name.domain.org</tt> is assumed to resolve to the IPv6
+address of the server:</p>
+<p>Server:</p>
+<span class="frame"><span class="shell">socat
+openssl-listen:4433,<b style="color:yellow">pf=ip6</b>,reuseaddr,cert=$HOME/etc/server.pem,cafile=$HOME/etc/client.crt echo</span></span>
+
+<p>Client:</p>
+<span class="frame"><span class="shell">socat stdio openssl-connect:<b style="color:yellow">ip6name</b>.domain.org:4433,cert=$HOME/etc/client.pem,cafile=$HOME/etc/server.crt</span></span>
+
+<h2>Troubleshooting</h2>
+
+<h3>Test OpenSSL Integration</h3>
+<p>
+If you get error messages like this:</p>
+<table border="1" bgcolor="#e08080"><tr><td><tt>... E unknown device/address "openssl-listen"</tt></td></tr></table>
+<p>your socat executable probably does not have the OpenSSL library linked in.
+Check socat's compile time configuration with the following command:</p>
+<span class="frame"><span class="shell">socat -V |grep SSL</span></span>
+<p>Positive output:
+<tt>#define WITH_OPENSSL 1</tt><br>
+Negative output:
+<tt>#undef WITH_OPENSSL</tt><br>
+</p>
+<p>
+In the latter case, make sure you have OpenSSL and its development package
+(include files) installed, and check the run of the configure script.
+</p>
+
+
+<h2>History</h2>
+<p>
+A first OpenSSL client was implemented in socat 1.2.0; it did not support
+client certificates and could not verify server certificates. It was rather
+considered as a tool for probing typical SSL secured Internet services.
+</p>
+<p>
+From version 1.4.0 on, socat provided experimental support for SSL client and
+SSL server, implemented using the OpenSSL libraries. Only TCP/IPv4 transport
+was supported. With both SSL client and server, trust certificates for checking
+the peers authentication, and certificates for authentication could be
+specified. This allowed for non interactive secure connection establishing.
+The features were considered experimental; like most Internet sites, socat
+server did not require the client to present a certificate per default, but the
+client required a server certificate.
+
+</p>
+<p>
+DSA certificate support is implemented since version 1.4.2.
+</p>
+<p>
+Socat version 1.5.0 extended SSL to TCP/IPv6 transports.
+</p>
+<p>
+With socat version 1.6.0, the SSL server per default requires the client to
+present a trusted certificate. socat's OpenSSL implementation still does not
+check the contents of a certificate like host name or host address.
+</p>
+
+<p>This document was last modified in March 2007.</p>
+
+<h2>More info about socat OpenSSL</h2>
+
+<h3>Links regarding this tutorial</h3>
+<a href="socat.html#ADDRESS_OPENSSL_CONNECT">address openssl-connect</a><br>
+<a href="socat.html#ADDRESS_OPENSSL_LISTEN">address openssl-listen</a><br>
+<a href="socat.html#OPTION_OPENSSL_CERTIFICATE">option cert</a><br>
+<a href="socat.html#OPTION_OPENSSL_CAFILE">option cafile</a><br>
+
+<h3>More socat options for OpenSSL addresses</h3>
+<a href="socat.html#GROUP_OPENSSL">OpenSSL options</a><br>
+<a href="socat.html#GROUP_TCP">TCP options</a><br>
+<a href="socat.html#GROUP_IP">IP options</a><br>
+<a href="socat.html#GROUP_SOCKET">socket options</a><br>
+<a href="socat.html#GROUP_FD">file descriptor options</a><br>
+<a href="socat.html#GROUP_RETRY">retry options</a><br>
+<p>For openssl-listen only:</p>
+<a href="socat.html#GROUP_LISTEN">listen options</a><br>
+<a href="socat.html#GROUP_CHILD">child options</a><br>
+<a href="socat.html#GROUP_RANGE">range options</a><br>
+
+<h2>References</h2>
+<a href="http://www.dest-unreach.org/socat">socat home page</a><br>
+<a href="socat.html">socat man page</a><br>
+<a href="http://www.openssl.org/">OpenSSL home page</a><br>
+<a href="http://www.stunnel.org/">stunnel home page</a><br>
+<a href="http://en.wikipedia.org/wiki/Secure_Sockets_Layer">secure sockets layer on Wikipedia</a><br>
+
+<p>
+<small>Copyright: Gerhard Rieger 2007</small><br>
+<small>License: <a href="http://www.fsf.org/licensing/licenses/fdl.html">GNU Free Documentation License (FDL)</a></small>
+</p>
+
+</body>
+</html>
diff --git a/doc/socat-tun.html b/doc/socat-tun.html
new file mode 100644
index 0000000..0df6bca
--- /dev/null
+++ b/doc/socat-tun.html
@@ -0,0 +1,165 @@
+<!-- $Revision: 1.1 $ $Date: 2007/03/06 20:54:43 $ -->
+<html><head>
+<title>Building TUN based virtual networks with socat</title>
+<link rel="stylesheet" type="text/css" href="dest-unreach.css">
+</head>
+
+<body>
+
+<h1>Building TUN based virtual networks with socat</h1>
+
+<h2>Introduction</h2>
+<p>
+Some operating systems allow the generation of virtual network interfaces that
+do not connect to a wire but to a process that simulates the network. Often
+these devices are called TUN or TAP.
+</p>
+<p>
+socat provides an address type that creates a TUN device on Linux; the other
+socat address can be any type; it transfer the "wire" data as desired.
+</p>
+<p>
+This document shows how a simple virtual network can be created between
+two hosts that may be far (many network hops) apart. On both hosts a socat
+instance is started that connects to the other host using TCP and creates a TUN
+device. See <a href="socat-openssltunnel.html">socat-openssltunnel.html</a> for
+a guide on securing the connection using SSL.
+</p>
+<p>
+The following IP addresses are used in the example; replace them in the
+following commands with the requirements of your situation:</p>
+<table border="1">
+<tr><th>host</th><th>address</th><th>mask</th></tr>
+<tr><td>physical "server" address</td><td>1.2.3.4</td><td>n/a</td></tr>
+<tr><td>physical "client" address</td><td>223.2.3.4</td><td>n/a</td></tr>
+<tr><td>TUN on "server"</td><td>192.168.255.1</td><td>255.255.255.0</td></tr>
+<tr><td>TUN on "client"</td><td>192.168.255.2</td><td>255.255.255.0</td></tr>
+</table>
+<p>The TCP connection uses port 11443.</p>
+
+<p>On "default" Linux installations, creating TUN/TAP devices might require
+root privilege.</p>
+
+<!-- discussion -->
+<h2>Generate TUN devices with socat</h2>
+<p>In this section two instances of socat are used to generate TUN devices on
+different hosts and connect the "wire" sides, providing a simple virtual
+network.
+</p>
+<p>
+We distinguish server and client only with respect to the connection between
+the two socat instances; the TUN interfaces both have the same quality.
+</p>
+
+<h3>TUN Server</h3>
+
+<span class="frame"><span class="shell">socat -d -d TCP-LISTEN:11443,reuseaddr TUN:192.168.255.1/24,up</span></span>
+<p>After starting this command, socat will wait for a connection and then
+create a TUN pseudo network device with address 192.168.255.1; the bit number
+specifies the mask of the network that is pretended to be connected on this
+interface.</p>
+
+<h3>TUN Client</h3>
+<span class="frame"><span class="shell">socat TCP:1.2.3.4:11443 TUN:192.168.255.2/24,up</span></span>
+<p>This command should establish a connection to the server and create the TUN
+device on the client.</p>
+
+<h3>Seeing it work</h3>
+
+<p>
+After successful connection both TUN interfaces should be active and transfer
+date between each other using the TCP connection. Try this by pinging
+192.168.255.1 from the client and 192.168.255.2 from the server.
+</p>
+
+<h3>TCP/IP version 6</h3>
+
+<p>IPv6 as transport should work just like any TCP/IPv6 connection.</p>
+
+<p>Creation of an IPv6 virtual interface is not directly possible, but you can
+generate an IPv4 interface as described above, and add IPv6 addresses using
+the <tt>ifconfig</tt> command.
+
+<h2>Troubleshooting</h2>
+
+<h3>Test TUN integration</h3>
+<p>
+If you get error messages like this:</p>
+<table border="1" bgcolor="#e08080"><tr><td><tt>... E unknown device/address "tun"</tt></td></tr></table>
+<p>your socat executable probably does not provide TUN/TAP support. Potential
+reasons: you are not on Linux or are using an older version of socat.
+</p>
+
+<h3>Missing kernel support</h3>
+<p>An error message like:</p>
+<table border="1" bgcolor="#e08080"><tr><td><tt>... E open("/dev/net/tun", 02, 0666): No such file or directory</tt></td></tr></table>
+<p>indicates that your kernel does not have TUN/TAP support compiled
+in. Rebuild your kernel with the appropriate configuration (probably under
+<b>Device driver / Network device support / Network device / Universal TUN/TAP</b>).
+</p>
+
+<h3>TUN cloning device permissions</h3>
+<p>An error message like:</p>
+<table border="1" bgcolor="#e08080"><tr><td><tt>... E open("/dev/net/tun", 02, 0666): Permission denied</tt></td></tr></table>
+<p>indicates that you do not have permission to read or write the TUN cloning
+device. Check its permission and ownership.</p>
+
+<h3>Interface down</h3>
+<p>If no error occurs but the pings do not work check if the network devices
+have been created:</p>
+<span class="frame"><span class="shell">ifconfig tun0</span></span>
+<p>The output should look like:</p>
+<pre>
+tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+ inet addr:192.168.255.1 P-t-P:192.168.255.1 Mask:255.255.255.0
+ UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
+ RX packets:0 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
+ collisions:0 txqueuelen:500
+ RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
+</pre>
+<p>Check the "UP" keyword; you forget the "up" option in the socat command if
+ it is missing.<p>
+<p>Check if the correct IP address and network mask are displayed.</p>
+
+<h3>Routing</h3>
+<p></p>
+<span class="frame"><span class="shell">netstat -an |fgrep 192.168.255</span></span>
+<p>The output should look like:</p>
+<pre>
+192.168.255.0 0.0.0.0 255.255.255.0 U 0 0 0 tun0
+</pre>
+
+<h3>Other problems</h3>
+<p>Another reason for failure might be iptables.</p>
+<p>Run socat with options <tt>-d -d -d</tt>, this will show every data transfer
+between the two processes. Each ping probe should cause a forth and a back
+transfer.<p>
+
+<h2>History</h2>
+<p>
+Linux TUN/TAP support was added to socat in version 1.6.0.</p>
+
+<p>This document was last modified in March 2007.</p>
+
+<h2>More info about socat TUN/TAP support</h2>
+
+<h3>Links regarding this tutorial</h3>
+<a href="socat.html#ADDRESS_TUN">socat address tun</a><br>
+
+<h3>socat options for TUN/TAP addresses</h3>
+<a href="socat.html#GROUP_TUN">TUN/TAP options</a><br>
+
+<h2>References</h2>
+<a href="http://www.dest-unreach.org/socat">socat home page</a><br>
+<a href="socat.html">socat man page</a><br>
+<a href="http://openvpn.net/">OpenVPN home page</a><br>
+<a href="http://en.wikipedia.org/wiki/TUN/TAP">TUN/TAP on Wikipedia</a><br>
+
+<p>
+<small>Copyright: Gerhard Rieger 2007</small><br>
+<small>License: <a href="http://www.fsf.org/licensing/licenses/fdl.html">GNU Free Documentation License (FDL)</a></small>
+</p>
+
+</body>
+</html>
diff --git a/doc/socat.1 b/doc/socat.1
new file mode 100644
index 0000000..3be5004
--- /dev/null
+++ b/doc/socat.1
@@ -0,0 +1,2877 @@
+.TH "socat" "1" "March 2007" "socat" ""
+.PP
+.PP
+.SH "NAME"
+socat \- Multipurpose relay (SOcket CAT)
+.PP
+.SH "SYNOPSIS"
+\f(CWsocat [options] <address> <address>\fP
+.br
+\f(CWsocat -V\fP
+.br
+\f(CWsocat -h[h[h]] | -?[?[?]]\fP
+.br
+\f(CWfilan\fP
+.br
+\f(CWprocan\fP
+.PP
+.SH "DESCRIPTION"
+.PP
+\fBSocat\fP is a command line based utility that establishes two bidirectional byte
+streams and transfers data between them\&. Because the streams can be constructed
+from a large set of different types of data sinks and sources
+(see address types), and because lots of
+address options may be applied to the streams, socat can
+be used for many different purposes\&.
+It might be one of the tools that one `has already needed\'\&.
+.PP
+\fBFilan\fP is a utility that prints information about its active file
+descriptors to stdout\&. It has been written for debugging \fBsocat\fP, but might be
+useful for other purposes too\&. Use the -h option to find more infos\&.
+.PP
+\fBProcan\fP is a utility that prints information about process parameters to
+stdout\&. It has been written to better understand
+some UNIX process properties and for debugging \fBsocat\fP, but might be
+useful for other purposes too\&.
+.PP
+The life cycle of a \fBsocat\fP instance typically consists of four phases\&.
+.PP
+In the \fIinit\fP phase, the command line options are parsed and logging is
+initialized\&.
+.PP
+During the \fIopen\fP phase, \fBsocat\fP opens the first address and afterwards the
+second address\&. These steps are usually blocking; thus, especially for complex address types like socks,
+connection requests or authentication dialogs must be completed before the next
+step is started\&.
+.PP
+In the \fItransfer\fP phase, \fBsocat\fP watches both streams\' read and write file
+descriptors via \f(CWselect()\fP, and, when data is available on one side \fIand\fP
+can be written to the other side, socat reads it, performs newline
+character conversions if required, and writes the data to the write file
+descriptor of the other stream, then continues waiting for more data in both
+directions\&.
+.PP
+When one of the streams effectively reaches EOF, the \fIclosing\fP phase
+begins\&. \fBSocat\fP transfers the EOF condition to the other stream,
+i\&.e\&. tries to shutdown only its write stream, giving it a chance to
+terminate gracefully\&. For a defined time \fBsocat\fP continues to transfer data in
+the other direction, but then closes all remaining channels and terminates\&.
+.PP
+.SH "OPTIONS"
+.PP
+\fBSocat\fP provides some command line options that modify the behaviour of the
+program\&. They have nothing to do with so called
+address options that are used as parts of address specifications\&.
+.PP
+.IP "\fB\f(CW-V\fP\fP"
+Print version and available feature information to stdout, and exit\&.
+.IP "\fB\f(CW-h | -?\fP\fP"
+Print a help text to stdout describing command line options and available address
+types, and exit\&.
+.IP "\fB\f(CW-hh | -??\fP\fP"
+Like -h, plus a list of the short names of all available address options\&. Some options are
+platform dependend, so this output is helpful for checking the particular
+implementation\&.
+.IP "\fB\f(CW-hhh | -???\fP\fP"
+Like -hh, plus a list of all available address option names\&.
+.IP "\fB\f(CW-d\fP\fP"
+Without this option, only fatal and error messages are generated; applying
+this option also prints warning messages\&. See DIAGNOSTICS
+for more information\&.
+.IP "\fB\f(CW-d -d\fP\fP"
+Prints fatal, error, warning, and notice messages\&.
+.IP "\fB\f(CW-d -d -d\fP\fP"
+Prints fatal, error, warning, notice, and info messages\&.
+.IP "\fB\f(CW-d -d -d -d\fP\fP"
+Prints fatal, error, warning, notice, info, and debug
+messages\&.
+.IP "\fB\f(CW-D\fP\fP"
+Logs information about file descriptors before starting the transfer phase\&.
+.IP "\fB\f(CW-ly[<facility>]\fP\fP"
+Writes messages to syslog instead of stderr; severity as defined with -d
+option\&. With optional <facility>, the syslog type can
+be selected, default is "daemon"\&.
+.IP "\fB\f(CW-lf\fP\fP\f(CW <logfile>\fP"
+Writes messages to <logfile> [filename] instead of
+stderr\&.
+.IP "\fB\f(CW-ls\fP\fP"
+Writes messages to stderr (this is the default)\&.
+.IP "\fB\f(CW-lp\fP\fP\f(CW<progname>\fP"
+Overrides the program name printed in error messages\&.
+.IP "\fB\f(CW-lu\fP\fP"
+Extends the timestamp of error messages to microsecond resolution\&. Does not
+work when logging to syslog\&.
+.IP "\fB\f(CW-lm[<facility>]\fP\fP"
+Mixed log mode\&. During startup messages are printed to stderr; when \fBsocat\fP
+starts the transfer phase loop or daemon mode (i\&.e\&. after opening all
+streams and before starting data transfer, or, with listening sockets with
+fork option, before the first accept call), it switches logging to syslog\&.
+With optional <facility>, the syslog type can be
+selected, default is "daemon"\&.
+.IP "\fB\f(CW-lh\fP\fP"
+Adds hostname to log messages\&. Uses the value from environment variable
+HOSTNAME or the value retrieved with \f(CWuname()\fP if HOSTNAME is not set\&.
+.IP "\fB\f(CW-v\fP\fP"
+Writes the transferred data not only to their target streams, but also to
+stderr\&. The output format is text with some conversions for readability, and
+prefixed with "> " or "< " indicating flow directions\&.
+.IP "\fB\f(CW-x\fP\fP"
+Writes the transferred data not only to their target streams, but also to
+stderr\&. The output format is hexadecimal, prefixed with "> " or "< "
+indicating flow directions\&. Can be combined with \f(CW-v\fP\&.
+.IP "\fB\f(CW-b\fP\fP\f(CW<size>\fP"
+Sets the data transfer block <size> [size_t]\&.
+At most <size> bytes are transferred per step\&. Default is 8192 bytes\&.
+.IP "\fB\f(CW-s\fP\fP"
+By default, \fBsocat\fP terminates when an error occurred to prevent the process
+from running when some option could not be applied\&. With this
+option, \fBsocat\fP is sloppy with errors and tries to continue\&. Even with this
+option, socat will exit on fatals, and will abort connection attempts when
+security checks failed\&.
+.IP "\fB\f(CW-t\fP\fP\f(CW<timeout>\fP"
+When one channel has reached EOF, the write part of the other channel is shut
+down\&. Then, \fBsocat\fP waits <timeout> [timeval] seconds
+before terminating\&. Default is 0\&.5 seconds\&. This timeout only applies to
+addresses where write and read part can be closed independently\&. When during
+the timeout intervall the read part gives EOF, socat terminates without
+awaiting the timeout\&.
+.IP "\fB\f(CW-T\fP\fP\f(CW<timeout>\fP"
+Total inactivity timeout: when socat is already in the transfer loop and
+nothing has happened for <timeout> [timeval] seconds
+(no data arrived, no interrupt occurred\&.\&.\&.) then it terminates\&.
+Useful with protocols like UDP that cannot transfer EOF\&.
+.IP "\fB\f(CW-u\fP\fP"
+Uses unidirectional mode\&. The first address is only used for reading, and the
+second address is only used for writing (example)\&.
+.IP "\fB\f(CW-U\fP\fP"
+Uses unidirectional mode in reverse direction\&. The first address is only
+used for writing, and the second address is only used for reading\&.
+.IP "\fB\f(CW-g\fP\fP"
+During address option parsing, don\'t check if the option is considered
+useful in the given address environment\&. Use it if you want to force, e\&.g\&.,
+appliance of a socket option to a serial device\&.
+.IP "\fB\f(CW-L\fP\fP\f(CW<lockfile>\fP"
+If lockfile exists, exits with error\&. If lockfile does not exist, creates it
+and continues, unlinks lockfile on exit\&.
+.IP "\fB\f(CW-W\fP\fP\f(CW<lockfile>\fP"
+If lockfile exists, waits until it disappears\&. When lockfile does not exist,
+creates it and continues, unlinks lockfile on exit\&.
+.IP "\fB\f(CW-4\fP\fP"
+Use IP version 4 in case that the addresses do not implicitly or explicitly
+specify a version; this is the default\&.
+.IP "\fB\f(CW-6\fP\fP"
+Use IP version 6 in case that the addresses do not implicitly or explicitly
+specify a version\&.
+.PP
+.SH "ADDRESS SPECIFICATIONS"
+.PP
+With the address command line arguments, the user gives \fBsocat\fP instructions and
+the necessary information for establishing the byte streams\&.
+.PP
+An address specification usually consists of an address type
+keyword, zero or more required address parameters separated by \':\' from the keyword and
+from each
+other, and zero or more address options separated by \',\'\&.
+.PP
+The keyword specifies the address type (e\&.g\&., TCP4, OPEN, EXEC)\&. For some
+keywords there exist synonyms (\'-\' for STDIO, TCP for TCP4)\&. Keywords are case
+insensitive\&.
+For a few special address types, the keyword may be omitted:
+Address specifications starting with a number are assumed to be FD (raw file
+descriptor) addresses;
+if a \'/\' is found before the first \':\' or \',\', GOPEN (generic file open) is
+assumed\&.
+.PP
+The required number and type of address parameters depend on the address
+type\&. E\&.g\&., TCP4 requires a server specification (name or address), and a port
+specification (number or service name)\&.
+.PP
+Zero or more address options may be given with each address\&. They influence the
+address in some ways\&.
+Options consist of an option keyword or an option keyword and a value,
+separated by \'=\'\&. Option keywords are case insensitive\&.
+For filtering the options that are useful with an address
+type, each option is member of one option group\&. For
+each address type there is a set of option groups allowed\&. Only options
+belonging to one of these address groups may be used (except with option -g)\&.
+.PP
+Address specifications following the above schema are also called \fIsingle\fP
+address specifications\&.
+Two single addresses can be combined with "!!" to form a \fIdual\fP type
+address for one channel\&. Here, the first address is used by \fBsocat\fP for reading
+data, and the
+second address for writing data\&. There is no way to specify an option only once
+for being applied to both single addresses\&.
+.PP
+Usually, addresses are opened in read/write
+mode\&. When an address is part of a dual address specification, or when
+option -u or -U is used, an address might be
+used only for reading or for writing\&. Considering this is important with some
+address types\&.
+.PP
+With socat version 1\&.5\&.0 and higher, the lexical analysis tries to handle
+quotes and parenthesis meaningfully and allows escaping of special characters\&.
+If one of the characters ( { [ \' is found, the corresponding closing
+character - ) } ] \' - is looked for; they may also be nested\&. Within these
+constructs, socats special characters and strings : , !! are not handled
+specially\&. All those characters and strings can be escaped with \e or within ""
+.PP
+.SH "ADDRESS TYPES"
+.PP
+This section describes the available address types with their keywords,
+parameters, and semantics\&.
+.PP
+.IP "\fB\f(CWCREATE:<filename>\fP\fP"
+Opens <filename> with \f(CWcreat()\fP and uses the file
+descriptor for writing\&.
+This address type requires write-only context, because a file opened with
+\f(CWcreat\fP cannot be read from\&.
+<filename> must be a valid existing or not existing path\&.
+If <filename> is a named pipe, \f(CWcreat()\fP might block;
+if <filename> refers to a socket, this is an error\&.
+.br
+Option groups: FD,REG,NAMED
+.br
+Useful options:
+mode,
+user,
+group,
+unlink-early,
+unlink-late,
+append
+.br
+See also: OPEN, GOPEN
+.IP "\fB\f(CWEXEC:<command-line>\fP\fP"
+Forks a sub process that establishes communication with its parent process
+and invokes the specified program with \f(CWexecvp()\fP\&.
+<command-line> is a simple command
+with arguments separated by single spaces\&. If the program name
+contains a \'/\', the part after the last \'/\' is taken as ARGV[0]\&. If the
+program name is a relative
+path, the \f(CWexecvp()\fP semantics for finding the program via
+\f(CW$PATH\fP
+apply\&. After successful program start, \fBsocat\fP writes data to stdin of the
+process and reads from its stdout using a UNIX domain socket generated by
+\f(CWsocketpair()\fP per default\&. (example)
+.br
+Option groups: FD,SOCKET,EXEC,FORK,TERMIOS
+.br
+Useful options:
+path,
+fdin,
+fdout,
+chroot,
+su,
+su-d,
+nofork,
+pty,
+stderr,
+ctty,
+setsid,
+pipes,
+login,
+sigint,
+sigquit
+.br
+See also: SYSTEM
+.IP "\fB\f(CWFD:<fdnum>\fP\fP"
+Uses the file descriptor <fdnum>\&. It must already exist as
+valid UN*X file descriptor\&.
+.br
+Option groups: FD (TERMIOS,REG,SOCKET)
+.br
+See also:
+STDIO,
+STDIN,
+STDOUT,
+STDERR
+.IP "\fB\f(CWGOPEN:<filename>\fP\fP"
+(Generic open) This address type tries to handle any file system entry
+except directories usefully\&. <filename> may be a
+relative or absolute path\&. If it already exists, its type is checked\&.
+In case of a UNIX domain socket, \fBsocat\fP connects; if connecting fails,
+\fBsocat\fP assumes a datagram socket and uses \f(CWsendto()\fP calls\&.
+If the entry is not a socket, \fBsocat\fP opens it applying the \f(CWO_APPEND\fP
+flag\&.
+If it does not exist, it is opened with flag
+\f(CWO_CREAT\fP as a regular file (example)\&.
+.br
+Option groups: FD,REG,SOCKET,NAMED,OPEN
+.br
+See also:
+OPEN,
+CREATE,
+UNIX-CONNECT
+.IP
+.IP "\fB\f(CWIP-SENDTO:<host>:<protocol>\fP\fP"
+Opens a raw IP socket\&. Depending on host specification or option pf, IP procotol version
+4 or 6 is used\&. It uses <protocol> to send packets
+to <host> [IP address] and receives packets from
+host, ignores packets from other hosts\&.
+Protocol 255 uses the raw socket with the IP header being part of the
+data\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6
+.br
+Useful options:
+pf,
+ttl
+See also:
+IP4-SENDTO,
+IP6-SENDTO,
+IP-RECVFROM,
+IP-RECV,
+UDP-SENDTO
+UNIX-SENDTO
+.IP "\fB\f(CWIP4-SENDTO:<host>:<protocol>\fP\fP"
+Like IP-SENDTO, but always uses IPv4\&.
+.br
+Option groups: FD,SOCKET,IP4
+.br
+.IP "\fB\f(CWIP6-SENDTO:<host>:<protocol>\fP\fP"
+Like IP-SENDTO, but always uses IPv6\&.
+.br
+Option groups: FD,SOCKET,IP6
+.br
+.IP
+.IP "\fB\f(CWIP-DATAGRAM:<address>:<protocol>\fP\fP"
+Sends outgoing data to the specified address which may in particular be a
+broadcast or multicast address\&. Packets arriving on the local socket are
+checked if their source addresses match
+eventual RANGE or TCPWRAP
+options\&. This address type can for example be used for implementing
+symmetric or asymmetric broadcast or multicast communications\&.
+.br
+Option groups: FD, SOCKET,
+IP4, IP6, RANGE
+.br
+Useful options:
+range,
+tcpwrap,
+broadcast,
+ip-multicast-loop,
+ip-multicast-ttl,
+ip-multicast-if,
+ip-add-membership,
+ttl,
+tos,
+bind,
+pf
+.br
+See also:
+IP4-DATAGRAM,
+IP6-DATAGRAM,
+IP-SENDTO,
+IP-RECVFROM,
+IP-RECV,
+UDP-DATAGRAM
+.IP "\fB\f(CWIP4-DATAGRAM:<host>:<protocol>\fP\fP"
+Like IP-DATAGRAM, but always uses IPv4\&.
+(example)
+.br
+Option groups: FD, SOCKET,
+IP4, RANGE
+.br
+.IP "\fB\f(CWIP6-DATAGRAM:<host>:<protocol>\fP\fP"
+Like IP-DATAGRAM, but always uses IPv6\&. Please
+note that IPv6 does not know broadcasts\&.
+.br
+Option groups: FD, SOCKET,
+IP6, RANGE
+.br
+.IP
+.IP "\fB\f(CWIP-RECVFROM:<protocol>\fP\fP"
+Opens a raw IP socket of <protocol>\&. Depending on option pf, IP procotol version
+4 or 6 is used\&. It receives one packet from an unspecified peer and may send one or more answer packets to that peer\&.
+This mode is particularly useful with fork option where each arriving packet - from arbitrary peers - is handled by its own sub process\&.
+This allows a behaviour similar to typical UDP based servers like ntpd or named\&.
+This address works well with IP-SENDTO address peers (see above)\&.
+Protocol 255 uses the raw socket with the IP header being part of the
+data\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6,CHILD,RANGE
+.br
+Useful options:
+pf,
+fork,
+range,
+ttl,
+broadcast
+.br
+See also:
+IP4-RECVFROM,
+IP6-RECVFROM,
+IP-SENDTO,
+IP-RECV,
+UDP-RECVFROM,
+UNIX-RECVFROM
+.IP "\fB\f(CWIP4-RECVFROM:<protocol>\fP\fP"
+Like IP-RECVFROM, but always uses IPv4\&.
+.br
+Option groups: FD,SOCKET,IP4,CHILD,RANGE
+.br
+.IP "\fB\f(CWIP6-RECVFROM:<protocol>\fP\fP"
+Like IP-RECVFROM, but always uses IPv6\&.
+.br
+Option groups: FD,SOCKET,IP6,CHILD,RANGE
+.br
+.IP
+.IP "\fB\f(CWIP-RECV:<protocol>\fP\fP"
+Opens a raw IP socket of <protocol>\&. Depending on option pf, IP procotol version
+4 or 6 is used\&. It receives packets from multiple unspecified peers and merges the data\&.
+No replies are possible\&.
+It can be, e\&.g\&., addressed by socat IP-SENDTO address peers\&.
+Protocol 255 uses the raw socket with the IP header being part of the
+data\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6,RANGE
+.br
+Useful options:
+pf,
+range
+.br
+See also:
+IP4-RECV,
+IP6-RECV,
+IP-SENDTO,
+IP-RECVFROM,
+UDP-RECV,
+UNIX-RECV
+.IP "\fB\f(CWIP4-RECV:<protocol>\fP\fP"
+Like IP-RECV, but always uses IPv4\&.
+.br
+Option groups: FD,SOCKET,IP4,RANGE
+.br
+.IP "\fB\f(CWIP6-RECV:<protocol>\fP\fP"
+Like IP-RECV, but always uses IPv6\&.
+.br
+Option groups: FD,SOCKET,IP6,RANGE
+.br
+.IP
+.IP "\fB\f(CWOPEN:<filename>\fP\fP"
+Opens <filename> using the \f(CWopen()\fP system call
+(example)\&.
+This operation fails on UNIX domain sockets\&.
+.br
+Note: This address type is rarly useful in bidirectional mode\&.
+.br
+Option groups: FD,REG,NAMED,OPEN
+.br
+Useful options:
+creat,
+excl,
+noatime,
+nofollow,
+append,
+rdonly,
+wronly,
+lock,
+readbytes,
+ignoreeof
+.br
+See also:
+CREATE,
+GOPEN,
+UNIX-CONNECT
+.IP "\fB\f(CWOPENSSL:<host>:<port>\fP\fP"
+Tries to establish a SSL connection to <port> [TCP
+service] on
+<host> [IP address] using TCP/IP version 4 or 6
+depending on address specification, name resolution, or option
+pf\&.
+.br
+NOTE: The server certificate is only checked for validity against
+cafile or capath,
+but not for match with the server\'s name or its IP address!
+.br
+Option groups: FD,SOCKET,IP4,IP6,TCP,OPENSSL,RETRY
+.br
+Useful options:
+cipher,
+method,
+verify,
+cafile,
+capath,
+certificate,
+bind,
+pf,
+connect-timeout,
+sourceport,
+retry
+.br
+See also:
+OPENSSL-LISTEN,
+TCP
+.IP "\fB\f(CWOPENSSL-LISTEN:<port>\fP\fP"
+Listens on tcp <port> [TCP service]\&.
+The IP version is 4 or the one specified with
+pf\&. When a
+connection is accepted, this address behaves as SSL server\&.
+.br
+Note: You probably want to use the certificate option with this address\&.
+.br
+NOTE: The client certificate is only checked for validity against
+cafile or capath,
+but not for match with the client\'s name or its IP address!
+.br
+Option groups: FD,SOCKET,IP4,IP6,TCP,LISTEN,OPENSSL,CHILD,RANGE,RETRY
+.br
+Useful options:
+pf,
+cipher,
+method,
+verify,
+cafile,
+capath,
+certificate,
+fork,
+bind,
+range,
+tcpwrap,
+su,
+reuseaddr,
+retry
+.br
+See also:
+OPENSSL,
+TCP
+.IP "\fB\f(CWPIPE:<filename>\fP\fP"
+If <filename> already exists, it is opened\&.
+If is does not exist, a named pipe is created and opened\&. Beginning with
+socat version 1\&.4\&.3, the named pipe is removed when the address is closed
+(but see option unlink-close
+.br
+Note: When a pipe is used for both reading and writing, it works
+as echo service\&.
+.br
+Note: When a pipe is used for both reading and writing, and socat tries
+to write more bytes than the pipe can buffer (Linux 2\&.4: 2048 bytes), socat
+might block\&. Consider using socat option, e\&.g\&., \f(CW-b 2048\fP
+.br
+Option groups: FD,NAMED,OPEN
+.br
+Useful options:
+rdonly,
+nonblock,
+group,
+user,
+mode,
+unlink-early
+.br
+See also: unnamed pipe
+.IP "\fB\f(CWPIPE\fP\fP"
+Creates an unnamed pipe and uses it for reading and writing\&. It works as an
+echo, because everything written
+to it appeares immediately as read data\&.
+.br
+Note: When socat tries to write more bytes than the pipe can queue (Linux
+2\&.4: 2048 bytes), socat might block\&. Consider, e\&.g\&., using
+option \f(CW-b 2048\fP
+.br
+Option groups: FD
+.br
+See also: named pipe
+.IP "\fB\f(CWPROXY:<proxy>:<hostname>:<port>\fP\fP"
+Connects to an HTTP proxy server on port 8080 using TCP/IP version 4 or 6
+depending on address specification, name resolution, or option
+pf, and sends a CONNECT
+request for hostname:port\&. If the proxy grants access and succeeds to
+connect to the target, data transfer between socat and the target can
+start\&. Note that the traffic need not be HTTP but can be an arbitrary
+protocol\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6,TCP,HTTP,RETRY
+.br
+Useful options:
+proxyport,
+ignorecr,
+proxyauth,
+resolve,
+crnl,
+bind,
+connect-timeout,
+mss,
+sourceport,
+retry
+.br
+See also: SOCKS, TCP
+.IP "\fB\f(CWPTY\fP\fP"
+Generates a pseudo terminal (pty) and uses its master side\&. Another process
+may open the pty\'s slave side using it like a serial line or terminal\&.
+(example)\&. If
+both the ptmx and the openpty mechanisms are available, ptmx is used
+(POSIX)\&.
+.br
+Option groups: FD,NAMED,PTY,TERMIOS
+.br
+Useful options:
+link,
+openpty,
+wait-slave,
+mode,
+user,
+group
+.br
+See also:
+UNIX-LISTEN,
+PIPE,
+EXEC, SYSTEM
+.IP "\fB\f(CWREADLINE\fP\fP"
+Uses GNU readline and history on stdio to allow editing and reusing input
+lines (example)\&. This requires the GNU readline and
+history libraries\&. Note that stdio should be a (pseudo) terminal device,
+otherwise readline does not seem to work\&.
+.br
+Option groups: FD,READLINE,TERMIOS
+.br
+Useful options:
+history,
+noecho
+.br
+See also:
+STDIO
+.IP "\fB\f(CWSOCKS4:<socks-server>:<host>:<port>\fP\fP"
+Connects via <socks-server> [IP address]
+to <host> [IPv4 address]
+on <port> [TCP service],
+using socks version 4 protocol over IP version 4 or 6 depending on address specification, name resolution, or option
+pf (example)\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6,TCP,SOCKS4,RETRY
+.br
+Useful options:
+socksuser,
+socksport,
+sourceport,
+pf,
+retry
+.br
+See also:
+SOCKS4A,
+PROXY,
+TCP
+.IP "\fB\f(CWSOCKS4A:<socks-server>:<host>:<port>\fP\fP"
+like SOCKS4, but uses socks protocol version 4a, thus
+leaving host name resolution to the socks server\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6,TCP,SOCKS4,RETRY
+.br
+.IP "\fB\f(CWSTDERR\fP\fP"
+Uses file descriptor 2\&.
+.br
+Option groups: FD (TERMIOS,REG,SOCKET)
+.br
+See also: FD
+.IP "\fB\f(CWSTDIN\fP\fP"
+Uses file descriptor 0\&.
+.br
+Option groups: FD (TERMIOS,REG,SOCKET)
+.br
+Useful options:
+readbytes
+.br
+See also: FD
+.IP "\fB\f(CWSTDIO\fP\fP"
+Uses file descriptor 0 for reading, and 1 for writing\&.
+.br
+Option groups: FD (TERMIOS,REG,SOCKET)
+.br
+Useful options:
+readbytes
+.br
+See also: FD
+.IP "\fB\f(CWSTDOUT\fP\fP"
+Uses file descriptor 1\&.
+.br
+Option groups: FD (TERMIOS,REG,SOCKET)
+.br
+See also: FD
+.IP "\fB\f(CWSYSTEM:<shell-command>\fP\fP"
+Forks a sub process that establishes communication with its parent process
+and invokes the specified program with \f(CWsystem()\fP\&. Please note that
+<shell-command> [string] must
+not contain \',\' or "!!", and that shell meta characters may have to be
+protected\&.
+After successful program start, \fBsocat\fP writes data to stdin of the
+process and reads from its stdout\&.
+.br
+Option groups: FD,SOCKET,EXEC,FORK,TERMIOS
+.br
+Useful options:
+path,
+fdin,
+fdout,
+chroot,
+su,
+su-d,
+nofork,
+pty,
+stderr,
+ctty,
+setsid,
+pipes,
+sigint,
+sigquit
+.br
+See also: EXEC
+.IP "\fB\f(CWTCP:<host>:<port>\fP\fP"
+Connects to <port> [TCP service] on
+<host> [IP address] using TCP/IP version 4 or 6
+depending on address specification, name resolution, or option
+pf\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6,TCP,RETRY
+.br
+Useful options:
+crnl,
+bind,
+pf,
+connect-timeout,
+tos,
+mtudiscover,
+mss,
+nodelay,
+nonblock,
+sourceport,
+retry,
+readbytes
+.br
+See also:
+TCP4,
+TCP6,
+TCP-LISTEN,
+UDP,
+UNIX-CONNECT
+.IP "\fB\f(CWTCP4:<host>:<port>\fP\fP"
+Like TCP, but only supports IPv4 protocol (example)\&.
+.br
+Option groups: FD,SOCKET,IP4,TCP,RETRY
+.br
+.IP "\fB\f(CWTCP6:<host>:<port>\fP\fP"
+Like TCP, but only supports IPv6 protocol\&.
+.br
+Option groups: FD,SOCKET,IP6,TCP,RETRY
+.br
+.IP "\fB\f(CWTCP-LISTEN:<port>\fP\fP"
+Listens on <port> [TCP service] and accepts a
+TCP/IP connection\&. The IP version is 4 or the one specified with
+pf\&.
+Note that opening
+this address usually blocks until a client connects\&.
+.br
+Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP4,IP6,TCP,RETRY
+.br
+Useful options:
+crnl,
+fork,
+bind,
+range,
+tcpwrap,
+pf,
+backlog,
+mss,
+su,
+reuseaddr,
+retry,
+retry
+.br
+See also:
+TCP4-LISTEN,
+TCP6-LISTEN,
+UDP-LISTEN,
+UNIX-LISTEN,
+OPENSSL-LISTEN
+.IP "\fB\f(CWTCP4-LISTEN:<port>\fP\fP"
+Like TCP-LISTEN, but only supports IPv4
+protocol (example)\&.
+.br
+Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP4,TCP,RETRY
+.br
+.IP "\fB\f(CWTCP6-LISTEN:<port>\fP\fP"
+Like TCP-LISTEN, but only supports IPv6
+protocol\&.
+.br
+Additional useful option:
+ipv6only
+.br
+Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP6,TCP,RETRY
+.br
+.IP "\fB\f(CWTUN:<if-addr>/<bits>\fP\fP"
+Creates a Linux TUN/TAP device and assignes to it the address and netmask
+defined by the parameters\&. The resulting network interface is ready for use
+by other processes; socat serves its "wire side"\&. This address requires read
+and write access to the tunnel cloning device, usually \f(CW/dev/net/tun\fP\&.
+.br
+Option groups: FD,NAMED,OPEN,TUN
+.br
+Useful options:
+iff-up,
+tun-device,
+tun-name,
+tun-type,
+iff-no-pi
+.br
+See also:
+ip-recv
+.IP "\fB\f(CWUDP:<host>:<port>\fP\fP"
+Connects to <port> [UDP service] on
+<host> [IP address] using UDP/IP version 4 or 6
+depending on address specification, name resolution, or option
+pf\&.
+.br
+Please note that,
+due to UDP protocol properties, no real connection is established; data has
+to be sent for `connecting\' to the server, and no end-of-file condition can
+be transported\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6
+.br
+Useful options:
+ttl,
+tos,
+bind,
+sourceport,
+pf
+.br
+See also:
+UDP4,
+UDP6,
+UDP-LISTEN,
+TCP,
+IP
+.IP "\fB\f(CWUDP4:<host>:<port>\fP\fP"
+Like UDP, but only supports IPv4 protocol\&.
+.br
+Option groups: FD,SOCKET,IP4
+.br
+.IP "\fB\f(CWUDP6:<host>:<port>\fP\fP"
+Like UDP, but only supports IPv6 protocol\&.
+.br
+Option groups: FD,SOCKET,IP6
+.br
+.IP "\fB\f(CWUDP-DATAGRAM:<address>:<port>\fP\fP"
+Sends outgoing data to the specified address which may in particular be a
+broadcast or multicast address\&. Packets arriving on the local socket are
+checked for the correct remote port and if their source addresses match
+eventual RANGE or TCPWRAP
+options\&. This address type can for example be used for implementing
+symmetric or asymmetric broadcast or multicast communications\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6,RANGE
+.br
+Useful options:
+range,
+tcpwrap,
+broadcast,
+ip-multicast-loop,
+ip-multicast-ttl,
+ip-multicast-if,
+ip-add-membership,
+ttl,
+tos,
+bind,
+sourceport,
+pf
+.br
+See also:
+UDP4-DATAGRAM,
+UDP6-DATAGRAM,
+UDP-SENDTO,
+UDP-RECVFROM,
+UDP-RECV,
+UDP-CONNECT,
+UDP-LISTEN,
+IP-DATAGRAM
+.IP "\fB\f(CWUDP4-DATAGRAM:<address>:<port>\fP\fP"
+Like UDP-DATAGRAM, but only supports IPv4
+protocol (example1,
+example2)\&.
+.br
+Option groups: FD, SOCKET,
+IP4, RANGE
+.IP "\fB\f(CWUDP6-DATAGRAM:<address>:<port>\fP\fP"
+Like UDP-DATAGRAM, but only supports IPv6
+protocol\&.
+.br
+Option groups: FD,SOCKET,
+IP6,RANGE
+.IP "\fB\f(CWUDP-LISTEN:<port>\fP\fP"
+Waits for a UDP/IP packet arriving on <port>
+[UDP service] and `connects\' back to sender\&.
+The accepted IP version is 4 or the one specified with option
+pf\&.
+Please note that,
+due to UDP protocol properties, no real connection is established; data has
+to arrive from the peer first, and no end-of-file condition can be
+transported\&. Note that opening
+this address usually blocks until a client connects\&.
+.br
+Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP4,IP6
+.br
+Useful options:
+fork,
+bind,
+range,
+pf
+.br
+See also:
+UDP,
+UDP4-LISTEN,
+UDP6-LISTEN,
+TCP-LISTEN
+.IP "\fB\f(CWUDP4-LISTEN:<port>\fP\fP"
+Like UDP-LISTEN, but only support IPv4
+protocol\&.
+.br
+Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP4
+.br
+.IP "\fB\f(CWUDP6-LISTEN:<port>\fP\fP"
+Like UDP-LISTEN, but only support IPv6
+protocol\&.
+.br
+Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP6
+.br
+.IP "\fB\f(CWUDP-SENDTO:<host>:<port>\fP\fP"
+Communicates with the specified peer socket, defined by <port> [UDP
+service] on
+<host> [IP address], using UDP/IP version 4 or 6
+depending on address specification, name resolution, or option
+pf\&. It sends packets to and receives packets
+from that peer socket only\&.
+This address effectively implements a datagram client\&.
+It works well with socat UDP-RECVFROM and UDP-RECV address peers\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6
+.br
+Useful options:
+ttl,
+tos,
+bind,
+sourceport,
+pf
+.br
+See also:
+UDP4-SENDTO,
+UDP6-SENDTO,
+UDP-RECVFROM,
+UDP-RECV,
+UDP-CONNECT,
+UDP-LISTEN,
+IP-SENDTO
+.IP "\fB\f(CWUDP4-SENDTO:<host>:<port>\fP\fP"
+Like UDP-SENDTO, but only supports IPv4
+protocol\&.
+.br
+Option groups: FD,SOCKET,IP4
+.IP "\fB\f(CWUDP6-SENDTO:<host>:<port>\fP\fP"
+Like UDP-SENDTO, but only supports IPv6
+protocol\&.
+.br
+Option groups: FD,SOCKET,IP6
+.IP
+.IP "\fB\f(CWUDP-RECVFROM:<port>\fP\fP"
+Creates a UDP socket on <port> [UDP service] using
+UDP/IP version 4 or 6
+depending on option pf\&.
+It receives one packet from an unspecified peer and may send one or more
+answer packets to that peer\&. This mode is particularly useful with fork
+option
+where each arriving packet - from arbitrary peers - is handled by its own sub
+process\&. This allows a behaviour similar to typical UDP based servers like ntpd
+or named\&. This address works well with socat SENDTO address peers\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6,CHILD,RANGE
+.br
+Useful options:
+fork,
+ttl,
+tos,
+bind,
+sourceport,
+pf
+.br
+See also:
+UDP4-RECVFROM,
+UDP6-RECVFROM,
+UDP-SENDTO,
+UDP-RECV,
+UDP-CONNECT,
+UDP-LISTEN,
+IP-RECVFROM,
+UNIX-RECVFROM
+.IP "\fB\f(CWUDP4-RECVFROM:<port>\fP\fP"
+Like UDP-RECVFROM, but only supports IPv4 protocol\&.
+.br
+Option groups: FD,SOCKET,IP4,CHILD,RANGE
+.IP "\fB\f(CWUDP6-RECVFROM:<port>\fP\fP"
+Like UDP-RECVFROM, but only supports IPv6 protocol\&.
+.br
+Option groups: FD,SOCKET,IP6,CHILD,RANGE
+.IP
+.IP "\fB\f(CWUDP-RECV:<port>\fP\fP"
+Creates a UDP socket on <port> [UDP service] using UDP/IP version 4 or 6
+depending on option pf\&.
+It receives packets from multiple unspecified peers and merges the data\&.
+No replies are possible\&. It works well with, e\&.g\&., socat UDP-SENDTO address peers; it behaves similar to a syslog server\&.
+.br
+Option groups: FD,SOCKET,IP4,IP6,RANGE
+.br
+Useful options:
+fork,
+pf,
+bind,
+sourceport,
+ttl,
+tos
+.br
+See also:
+UDP4-RECV,
+UDP6-RECV,
+UDP-SENDTO,
+UDP-RECVFROM,
+UDP-CONNECT,
+UDP-LISTEN,
+IP-RECV,
+UNIX-RECV
+.IP "\fB\f(CWUDP4-RECV:<port>\fP\fP"
+Like UDP-RECV, but only supports IPv4 protocol\&.
+.br
+Option groups: FD,SOCKET,IP4,RANGE
+.IP "\fB\f(CWUDP6-RECV:<port>\fP\fP"
+Like UDP-RECV, but only supports IPv6 protocol\&.
+.br
+Option groups: FD,SOCKET,IP6,RANGE
+.IP
+.IP "\fB\f(CWUNIX-CONNECT:<filename>\fP\fP"
+Connects to <filename> assuming it is a UNIX domain
+socket\&.
+If <filename> does not exist, this is an error;
+if <filename> is not a UNIX domain socket, this is an error;
+if <filename> is a UNIX domain socket, but no process is listening, this is
+an error\&.
+.br
+Option groups: FD,SOCKET,
+NAMED,RETRY,
+UNIX
+.br
+)
+Useful options:
+bind
+.br
+See also:
+UNIX-LISTEN,
+UNIX-SENDTO,
+TCP
+.IP
+.IP "\fB\f(CWUNIX-LISTEN:<filename>\fP\fP"
+Listens on <filename> using a UNIX domain stream
+socket and accepts a connection\&.
+If <filename> exists and is not a socket, this is an error\&.
+If <filename> exists and is a UNIX domain socket, binding to the address
+fails (use option unlink-early!)\&.
+Note that opening this address usually blocks until a client connects\&.
+Beginning with socat version 1\&.4\&.3, the file system entry is removed when
+this address is closed (but see option unlink-close) (example)\&.
+.br
+Option groups: FD,SOCKET,
+NAMED,LISTEN,
+CHILD,RETRY,
+UNIX
+.br
+Useful options:
+fork,
+umask,
+mode,
+user,
+group,
+unlink-early
+.br
+See also:
+UNIX-CONNECT,
+UNIX-RECVFROM,
+UNIX-RECV,
+TCP-LISTEN
+.IP
+.IP "\fB\f(CWUNIX-SENDTO:<filename>\fP\fP"
+Communicates with the specified peer socket, defined by [<filename>] assuming it is a UNIX domain datagram socket\&.
+It sends packets to and receives packets from that peer socket only\&.
+It works well with socat UNIX-RECVFROM and UNIX-RECV address peers\&.
+.br
+Option groups: FD,SOCKET,
+NAMED,UNIX
+.br
+Useful options:
+bind
+.br
+See also:
+UNIX-RECVFROM,
+UNIX-RECV,
+UNIX-CONNECT,
+UDP-SENDTO,
+IP-SENDTO
+.IP
+.IP "\fB\f(CWUNIX-RECVFROM:<filename>\fP\fP"
+Creates a UNIX domain datagram socket [<filename>]\&.
+Receives one packet and may send one or more answer packets to that peer\&.
+This mode is particularly useful with fork option where each arriving packet - from arbitrary peers - is handled by its own sub process\&.
+This address works well with socat UNIX-SENDTO address peers\&.
+.br
+Option groups: FD,SOCKET,
+NAMED,CHILD,
+UNIX
+.br
+Useful options:
+fork
+.br
+See also:
+UNIX-SENDTO,
+UNIX-RECV,
+UNIX-LISTEN,
+UDP-RECVFROM,
+IP-RECVFROM
+.IP
+.IP "\fB\f(CWUNIX-RECV:<filename>\fP\fP"
+Creates a UNIX domain datagram socket [<filename>]\&.
+Receives packets from multiple unspecified peers and merges the data\&.
+No replies are possible\&. It can be, e\&.g\&., addressed by socat UNIX-SENDTO address peers\&.
+It behaves similar to a syslog server\&.
+Option groups: FD,SOCKET,
+NAMED,UNIX
+.br
+See also:
+UNIX-SENDTO,
+UNIX-RECVFROM,
+UNIX-LISTEN,
+UDP-RECV,
+IP-RECV
+.IP
+.IP "\fB\f(CWUNIX-CLIENT:<filename>\fP\fP"
+Communicates with the specified peer socket, defined by
+[<filename>] assuming it is a UNIX domain socket\&.
+It first tries to connect and, if that fails, assumes it is a datagram
+socket, thus supporting both types\&.
+.br
+Option groups: FD,SOCKET,
+NAMED,UNIX
+.br
+Useful options:
+bind
+.br
+See also:
+UNIX-CONNECT,
+UNIX-SENDTO,
+GOPEN
+.IP
+.IP "\fB\f(CWABSTRACT-CONNECT:<string>\fP\fP"
+.IP "\fB\f(CWABSTRACT-LISTEN:<string>\fP\fP"
+.IP "\fB\f(CWABSTRACT-SENDTO:<string>\fP\fP"
+.IP "\fB\f(CWABSTRACT-RECVFROM:<string>\fP\fP"
+.IP "\fB\f(CWABSTRACT-RECV:<string>\fP\fP"
+.IP "\fB\f(CWABSTRACT-CLIENT:<string>\fP\fP"
+The ABSTRACT addresses are almost identical to the related UNIX addresses
+except that they do not address file system based sockets but an alternate
+UNIX domain address space\&. To archieve this the socket address strings are
+prefixed with "\e0" internally\&. This feature is available (only?) on Linux\&.
+Option groups are the same as with the related UNIX addresses, except that
+the ABSTRACT addresses are not member of the NAMED group\&.
+.PP
+.SH "ADDRESS OPTIONS"
+.PP
+Address options can be applied to address specifications to influence the
+process of opening the addresses and the
+properties of the resulting data channels\&.
+.PP
+For technical reasons not every option can be
+applied to every address type; e\&.g\&., applying a socket option to a regular file
+will fail\&. To catch most useless combinations as early as in the open phase,
+the concept of \fIoption groups\fP was introduced\&. Each option belongs to one
+or more option groups\&. Options can be used only with address types that support
+at least one of their option groups (but see option -g)\&.
+.PP
+Address options have data types that their values must conform to\&.
+Every address option consists of just a keyword or a keyword followed by
+"=value", where value must conform to the options type\&.
+Some address options manipulate parameters of system calls;
+e\&.g\&., option sync sets the \f(CWO_SYNC\fP flag with the \f(CWopen()\fP call\&.
+Other options cause a system or library call; e\&.g\&., with option `ttl=value\'
+the \f(CWsetsockopt(fd, SOL_IP, IP_TTL, value, sizeof(int))\fP call is applied\&.
+Other
+options set internal \fBsocat\fP variables that are used during data transfer;
+e\&.g\&., `crnl\' causes explicit character conversions\&.
+A few options have more complex implementations; e\&.g\&., su-d
+(substuser-delayed) inquires some user and group infos, stores them, and
+applies them later after a possible \f(CWchroot()\fP call\&.
+.PP
+If multiple options are given to an address, their sequence in the address specification has (almost) no
+effect on the sequence of their execution/application\&. Instead, \fBsocat\fP has
+built in an \fIoption phase\fP model that tries to bring the options in a useful
+order\&. Some options exist in different forms (e\&.g\&.,
+unlink, unlink-early, unlink-late) to control the time of their execution\&.
+.PP
+If the same option is specified more than once within one address
+specification, with equal or different values, the effect depends on the kind of option\&. Options
+resulting in function calls like \f(CWsetsockopt()\fP cause multiple
+invocations\&. With options that set parameters for a required call like
+\f(CWopen()\fP
+or set internal flags, the value of the last option occurrence is effective\&.
+.PP
+The existence or semantics of many options are system dependent\&. \fBSocat\fP
+usually does NOT try to emulate missing libc or kernel features, it just
+provides an
+interface to the underlying system\&. So, if an operating system lacks a feature,
+the related option is simply not available on this platform\&.
+.PP
+The following paragraphs introduce just the more common address options\&. For
+a more comprehensive reference and to find information about canonical option
+names, alias names, option phases, and platforms see file \fBxio\&.help\fP\&.
+.br
+.br
+.PP
+.br
+.PP
+\fI\fBFD option group\fP\fP
+.PP
+This option group contains options that are applied to a UN*X
+style file descriptor, no matter how it was generated\&.
+Because all current \fBsocat\fP address types are file descriptor based, these
+options may be applied to any address\&.
+.br
+Note: Some of these options are also member of another option group, that
+provides an other, non-fd based mechanism\&.
+For these options, it depends on the actual address type and its option groups
+which mechanism is used\&. The second, non-fd based mechanism is prioritized\&.
+.IP "\fB\f(CWcloexec=<bool>\fP\fP"
+Sets the \f(CWFD_CLOEXEC\fP flag with the \f(CWfcntl()\fP system call to value
+<bool>\&. If set,
+the file descriptor is closed on \f(CWexec()\fP family function calls\&. \fBSocat\fP
+internally handles
+this flag for the fds it controls, so in most cases there will be no need to
+apply this option\&.
+.IP "\fB\f(CWsetlk\fP\fP"
+Tries to set a discretionary write lock to the whole file using the \f(CWfcntl(fd,
+F_SETLK, \&.\&.\&.)\fP system call\&. If the file is already locked, this call results
+in an error\&.
+On Linux, when the file permissions for group are "S" (g-x,g+s), and the
+file system is locally mounted with the "mand" option, the lock is
+mandatory, i\&.e\&. prevents other processes from opening the file\&.
+.IP "\fB\f(CWsetlkw\fP\fP"
+Tries to set a discretionary waiting write lock to the whole file using the
+\f(CWfcntl(fd, F_SETLKW, \&.\&.\&.)\fP system call\&. If the file is already locked,
+this call blocks\&.
+See option setlk for information about making this
+lock mandatory\&.
+.IP "\fB\f(CWsetlk-rd\fP\fP"
+Tries to set a discretionary read lock to the whole file using the \f(CWfcntl(fd,
+F_SETLK, \&.\&.\&.)\fP system call\&. If the file is already write locked, this call
+results in an error\&.
+See option setlk for information about making this
+lock mandatory\&.
+.IP "\fB\f(CWsetlkw-rd\fP\fP"
+Tries to set a discretionary waiting read lock to the whole file using the
+\f(CWfcntl(fd, F_SETLKW, \&.\&.\&.)\fP system call\&. If the file is already write
+locked, this call blocks\&.
+See option setlk for information about making this
+lock mandatory\&.
+.IP "\fB\f(CWflock-ex\fP\fP"
+Tries to set a blocking exclusive advisory lock to the file using the
+\f(CWflock(fd, LOCK_EX)\fP system call\&. \fBSocat\fP hangs in this call if the file
+is locked by another process\&.
+.IP "\fB\f(CWflock-ex-nb\fP\fP"
+Tries to set a nonblocking exclusive advisory lock to the file using the
+\f(CWflock(fd, LOCK_EX|LOCK_NB)\fP system call\&. If the file is already locked,
+this option results in an error\&.
+.IP "\fB\f(CWflock-sh\fP\fP"
+Tries to set a blocking shared advisory lock to the file using the
+\f(CWflock(fd, LOCK_SH)\fP system call\&. \fBSocat\fP hangs in this call if the file
+is locked by another process\&.
+.IP "\fB\f(CWflock-sh-nb\fP\fP"
+Tries to set a nonblocking shared advisory lock to the file using the
+\f(CWflock(fd, LOCK_SH|LOCK_NB)\fP system call\&. If the file is already locked,
+this option results in an error\&.
+.IP "\fB\f(CWlock\fP\fP"
+Sets a blocking lock on the file\&. Uses the setlk or flock mechanism
+depending on availability on the particular platform\&. If both are available,
+the POSIX variant (setlkw) is used\&.
+.IP "\fB\f(CWuser=<user>\fP\fP"
+Sets the <user> (owner) of the stream\&.
+If the address is member of the NAMED option group,
+\fBsocat\fP uses the \f(CWchown()\fP system call after opening the
+file or binding to the UNIX domain socket (race condition!)\&.
+Without filesystem entry, \fBsocat\fP sets the user of the stream
+using the \f(CWfchown()\fP system call\&.
+These calls might require root privilege\&.
+.IP "\fB\f(CWuser-late=<user>\fP\fP"
+Sets the owner of the fd to <user> with the \f(CWfchown()\fP
+system call after opening
+or connecting the channel\&.
+This is useful only on file system entries\&.
+.IP "\fB\f(CWgroup=<group>\fP\fP"
+Sets the <group> of the stream\&.
+If the address is member of the NAMED option group,
+\fBsocat\fP uses the \f(CWchown()\fP system call after opening the
+file or binding to the UNIX domain socket (race condition!)\&.
+Without filesystem entry, \fBsocat\fP sets the group of the stream
+with the \f(CWfchown()\fP system call\&.
+These calls might require group membership or root privilege\&.
+.IP "\fB\f(CWgroup-late=<group>\fP\fP"
+Sets the group of the fd to <group> with the
+\f(CWfchown()\fP system call after opening
+or connecting the channel\&.
+This is useful only on file system entries\&.
+.IP "\fB\f(CWmode=<mode>\fP\fP"
+Sets the <mode> [mode_t] (permissions) of the stream\&.
+If the address is member of the NAMED option group and
+uses the \f(CWopen()\fP or \f(CWcreat()\fP call, the mode is applied with these\&.
+If the address is member of the NAMED option group without using these
+system calls, \fBsocat\fP uses the \f(CWchmod()\fP system call after opening the
+filesystem entry or binding to the UNIX domain socket (race condition!)\&.
+Otherwise, \fBsocat\fP sets the mode of the stream
+using \f(CWfchmod()\fP\&.
+These calls might require ownership or root privilege\&.
+.IP "\fB\f(CWperm-late=<mode>\fP\fP"
+Sets the permissions of the fd to value <mode>
+[mode_t] using the \f(CWfchmod()\fP system call after
+opening or connecting the channel\&.
+This is useful only on file system entries\&.
+.IP "\fB\f(CWappend=<bool>\fP\fP"
+Always writes data to the actual end of file\&.
+If the address is member of the OPEN option group,
+\fBsocat\fP uses the \f(CWO_APPEND\fP flag with the \f(CWopen()\fP system call
+(example)\&.
+Otherwise, \fBsocat\fP applies the \f(CWfcntl(fd, F_SETFL, O_APPEND)\fP call\&.
+.IP "\fB\f(CWnonblock=<bool>\fP\fP"
+Tries to open or use file in nonblocking mode\&. Its only effects are that the
+\f(CWconnect()\fP call of TCP addresses does not block, and that opening a
+named pipe for reading does not block\&.
+If the address is member of the OPEN option group,
+\fBsocat\fP uses the \f(CWO_NONBLOCK\fP flag with the \f(CWopen()\fP system call\&.
+Otherwise, \fBsocat\fP applies the \f(CWfcntl(fd, F_SETFL, O_NONBLOCK)\fP call\&.
+.IP "\fB\f(CWbinary\fP\fP"
+Opens the file in binary mode to avoid implicit line terminator
+conversions (Cygwin)\&.
+.IP "\fB\f(CWtext\fP\fP"
+Opens the file in text mode to force implicit line terminator conversions
+(Cygwin)\&.
+.IP "\fB\f(CWnoinherit\fP\fP"
+Does not keep this file open in a spawned process (Cygwin)\&.
+.IP "\fB\f(CWcool-write\fP\fP"
+Takes it easy when write fails with EPIPE or ECONNRESET and logs the message
+with \fInotice\fP level instead of \fIerror\fP\&.
+This prevents the log file from being filled with useless error messages
+when socat is used as a high volume server or proxy where clients often
+abort the connection\&.
+.br
+This option is experimental\&.
+.IP "\fB\f(CWend-close\fP\fP"
+Changes the (address dependent) method of ending a connection to just close
+the file descriptors\&. This is useful when the connection is to be reused by
+or shared with other processes (example)\&.
+.br
+Normally, socket connections will be ended with \f(CWshutdown(2)\fP which
+terminates the socket even if it is shared by multiple processes\&.
+\f(CWclose(2)\fP "unlinks" the socket from the process but keeps it active as
+long as there are still links from other processes\&.
+.br
+Similarly, when an address of type EXEC or SYSTEM is ended, socat usually
+will explicitely kill the sub process\&. With this option, it will just close
+the file descriptors\&.
+.PP
+.br
+.PP
+\fI\fBNAMED option group\fP\fP
+.PP
+These options work on file system entries\&.
+.br
+See also options user, group, and
+mode\&.
+.PP
+.IP "\fB\f(CWuser-early=<user>\fP\fP"
+Changes the <user> (owner) of the file system entry before
+accessing it, using the
+\f(CWchown()\fP system call\&. This call might require root privilege\&.
+.IP "\fB\f(CWgroup-early=<group>\fP\fP"
+Changes the <group> of the file system entry before
+accessing it, using the
+\f(CWchown()\fP system call\&. This call might require group membership or root
+privilege\&.
+.IP "\fB\f(CWperm-early=<mode>\fP\fP"
+Changes the <mode> [mode_t] of the file system entry
+before accessing it, using the
+\f(CWchmod()\fP system call\&. This call might require ownership or root
+privilege\&.
+.IP "\fB\f(CWumask=<mode>\fP\fP"
+Sets the umask of the process to <mode> [mode_t] before
+accessing the file system entry (useful
+with UNIX domain sockets!)\&. This call might affect all further operations
+of the \fBsocat\fP process!
+.IP "\fB\f(CWunlink-early\fP\fP"
+Unlinks (removes) the file before opening it and even before applying
+user-early etc\&.
+.IP "\fB\f(CWunlink\fP\fP"
+Unlinks (removes) the file before accessing it, but after user-early etc\&.
+.IP "\fB\f(CWunlink-late\fP\fP"
+Unlinks (removes) the file after opening it to make it inaccessible for
+other processes after a short race condition\&.
+.IP "\fB\f(CWunlink-close\fP\fP"
+Removes the addresses file system entry when closing the address\&.
+For named pipes,
+listening unix domain sockets,
+and the symbolic links of pty addresses,
+the default is 1; for created files,
+opened files,
+generic opened files, and
+client unix domain sockets the default is 0\&.
+.PP
+.br
+.PP
+\fI\fBOPEN option group\fP\fP
+.PP
+The OPEN group options allow to set flags with the \f(CWopen()\fP system call\&.
+E\&.g\&., option `creat\' sets the \f(CWO_CREAT\fP flag\&.
+.br
+See also options append and
+nonblock\&.
+.IP "\fB\f(CWcreat=<bool>\fP\fP"
+Creates the file if it does not exist (example)\&.
+.IP "\fB\f(CWdsync=<bool>\fP\fP"
+Blocks \f(CWwrite()\fP calls until metainfo is physically written to media\&.
+.IP "\fB\f(CWexcl=<bool>\fP\fP"
+With option creat, if file exists this is an error\&.
+.IP "\fB\f(CWlargefile=<bool>\fP\fP"
+On 32 bit systems, allows a file larger than 2^31 bytes\&.
+.IP "\fB\f(CWnoatime\fP\fP"
+Sets the O_NOATIME options, so reads do not change the access timestamp\&.
+.IP "\fB\f(CWnoctty=<bool>\fP\fP"
+Does not make this file the controlling terminal\&.
+.IP "\fB\f(CWnofollow=<bool>\fP\fP"
+Does not follow symbolic links\&.
+.IP "\fB\f(CWnshare=<bool>\fP\fP"
+Does not allow to share this file with other processes\&.
+.IP "\fB\f(CWrshare=<bool>\fP\fP"
+Does not allow other processes to open this file for writing\&.
+.IP "\fB\f(CWrsync=<bool>\fP\fP"
+Blocks \f(CWwrite()\fP until metainfo is physically written to media\&.
+.IP "\fB\f(CWsync=<bool>\fP\fP"
+Blocks \f(CWwrite()\fP until data is physically written to media\&.
+.IP "\fB\f(CWrdonly=<bool>\fP\fP"
+Opens the file for reading only\&.
+.IP "\fB\f(CWwronly=<bool>\fP\fP"
+Opens the file for writing only\&.
+.IP "\fB\f(CWtrunc\fP\fP"
+Truncates the file to size 0 during opening it\&.
+.PP
+.br
+.PP
+\fI\fBREG and BLK option group\fP\fP
+.PP
+These options are usually applied to a UN*X file descriptor, but their
+semantics make sense only on a file supporting random access\&.
+.IP "\fB\f(CWseek=<offset>\fP\fP"
+Applies the \f(CWlseek(fd, <offset>, SEEK_SET)\fP (or \f(CWlseek64\fP) system
+call, thus positioning the file pointer absolutely to <offset>
+[off_t or off64_t]\&.
+.IP "\fB\f(CWseek-cur=<offset>\fP\fP"
+Applies the \f(CWlseek(fd, <offset>, SEEK_CUR)\fP (or \f(CWlseek64\fP) system
+call, thus positioning the file pointer <offset> [off_t or
+off64_t] bytes relatively to its current position (which
+is usually 0)\&.
+.IP "\fB\f(CWseek-end=<offset>\fP\fP"
+Applies the \f(CWlseek(fd, <offset>, SEEK_END)\fP (or \f(CWlseek64\fP) system
+call, thus positioning the file pointer <offset> [off_t or
+off64_t] bytes relatively to the files current end\&.
+.IP "\fB\f(CWftruncate=<offset>\fP\fP"
+Applies the \f(CWftruncate(fd, <offset>)\fP
+(or \f(CWftruncate64\fP if available) system call, thus
+truncating the file at the position <offset> [off_t or
+off64_t]\&.
+.IP
+.IP "\fB\f(CWsecrm=<bool>\fP\fP"
+.IP "\fB\f(CWunrm=<bool>\fP\fP"
+.IP "\fB\f(CWcompr=<bool>\fP\fP"
+.IP "\fB\f(CWext2-sync=<bool>\fP\fP"
+.IP "\fB\f(CWimmutable=<bool>\fP\fP"
+.IP "\fB\f(CWext2-append=<bool>\fP\fP"
+.IP "\fB\f(CWnodump=<bool>\fP\fP"
+.IP "\fB\f(CWext2-noatime=<bool>\fP\fP"
+.IP "\fB\f(CWjournal-data=<bool>\fP\fP"
+.IP "\fB\f(CWnotail=<bool>\fP\fP"
+.IP "\fB\f(CWdirsync=<bool>\fP\fP"
+These options change non standard file attributes on operating systems and
+file systems that support these features, like Linux with ext2fs,
+ext3fs, or reiserfs\&. See man 1 chattr for information on these options\&.
+Please note that there might be a race condition between creating the file
+and applying these options\&.
+.PP
+.br
+.PP
+\fI\fBPROCESS option group\fP\fP
+.PP
+Options of this group change the process properties instead of just affecting
+one data channel\&.
+For EXEC and SYSTEM addresses and for LISTEN and CONNECT type addresses with
+option FORK,
+these options apply to the child processes instead of the main socat process\&.
+.IP "\fB\f(CWchroot=<directory>\fP\fP"
+Performs a \f(CWchroot()\fP operation to <directory>
+after processing the address (example)\&. This call might require root privilege\&.
+.IP "\fB\f(CWchroot-early=<directory>\fP\fP"
+Performs a \f(CWchroot()\fP operation to <directory>
+before opening the address\&. This call might require root privilege\&.
+.IP "\fB\f(CWsetgid=<group>\fP\fP"
+Changes the primary <group> of the process after
+processing the address\&. This call might require root privilege\&.
+.IP "\fB\f(CWsetgid-early=<group>\fP\fP"
+Changes the primary <group> of the process before opening
+the address\&. This call might require root privilege\&.
+.IP "\fB\f(CWsetuid=<user>\fP\fP"
+Changes the <user> (owner) of the process after processing
+the address\&. This call might require root privilege\&.
+.IP "\fB\f(CWsetuid-early=<user>\fP\fP"
+Changes the <user> (owner) of the process before opening
+the address\&. This call might require root privilege\&.
+.IP "\fB\f(CWsu=<user>\fP\fP"
+Changes the <user> (owner) and groups of the process after
+processing the address (example)\&. This call might require root privilege\&.
+.IP "\fB\f(CWsu-d=<user>\fP\fP"
+Short name for \fB\f(CWsubstuser-delayed\fP\fP\&.
+Changes the <user>
+(owner) and groups of the process after processing the address (example)\&.
+The user and his groups are retrieved \fIbefore\fP a possible
+\f(CWchroot()\fP\&. This call might require root privilege\&.
+.IP "\fB\f(CWsetpgid=<pid_t>\fP\fP"
+Makes the process a member of the specified process group
+<pid_t>\&. If no value
+is given, or if the value is 0 or 1, the process becomes leader of a new
+process group\&.
+.IP "\fB\f(CWsetsid\fP\fP"
+Makes the process the leader of a new session (example)\&.
+.PP
+.br
+.PP
+\fI\fBREADLINE option group\fP\fP
+.PP
+These options apply to the readline address type\&.
+.IP "\fB\f(CWhistory=<filename>\fP\fP"
+Reads and writes history from/to <filename> (example)\&.
+.IP "\fB\f(CWnoprompt\fP\fP"
+Since version 1\&.4\&.0, socat per default tries to determine a prompt -
+that is then passed to the readline call - by remembering the last
+incomplete line of the output\&. With this option, socat does not pass a
+prompt to readline, so it begins line editing in the first column
+of the terminal\&.
+.IP "\fB\f(CWnoecho=<pattern>\fP\fP"
+Specifies a regular pattern for a prompt that prevents the following input
+line from being displayed on the screen and from being added to the history\&.
+The prompt is defined as the text that was output to the readline address
+after the lastest newline character and before an input character was
+typed\&. The pattern is a regular expression, e\&.g\&.
+"^[Pp]assword:\&.*$" or "([Uu]ser:|[Pp]assword:)"\&. See regex(7) for details\&.
+(example)
+.IP "\fB\f(CWprompt=<string>\fP\fP"
+Passes the string as prompt to the readline function\&. readline prints this
+prompt when stepping through the history\&. If this string matches a constant
+prompt issued by an interactive program on the other socat address,
+consistent look and feel can be archieved\&.
+.PP
+.br
+.PP
+\fI\fBAPPLICATION option group\fP\fP
+.PP
+This group contains options that work at data level\&.
+Note that these options only apply to the "raw" data transferred by socat,
+but not to protocol data used by addresses like
+PROXY\&.
+.IP "\fB\f(CWcr\fP\fP"
+Converts the default line termination character NL (\'\en\', 0x0a) to/from CR
+(\'\er\', 0x0d) when writing/reading on this channel\&.
+.IP "\fB\f(CWcrnl\fP\fP"
+Converts the default line termination character NL (\'\en\', 0x0a) to/from CRNL
+("\er\en", 0x0d0a) when writing/reading on this channel (example)\&.
+Note: socat simply strips all CR characters\&.
+.IP "\fB\f(CWignoreeof\fP\fP"
+When EOF occurs on this channel, \fBsocat\fP ignores it and tries to read more
+data (like "tail -f") (example)\&.
+.IP "\fB\f(CWreadbytes=<bytes>\fP\fP"
+\fBsocat\fP reads only so many bytes from this address (the address provides
+only so many bytes for transfer and pretends to be at EOF afterwards)\&.
+Must be greater than 0\&.
+.IP "\fB\f(CWlockfile=<filename>\fP\fP"
+If lockfile exists, exits with error\&. If lockfile does not exist, creates it
+and continues, unlinks lockfile on exit\&.
+.IP "\fB\f(CWwaitlock=<filename>\fP\fP"
+If lockfile exists, waits until it disappears\&. When lockfile does not exist,
+creates it and continues, unlinks lockfile on exit\&.
+.PP
+.br
+.PP
+\fI\fBSOCKET option group\fP\fP
+.PP
+These options are intended for all kinds of sockets, e\&.g\&. IP or UNIX domain\&. Most are applied with a \f(CWsetsockopt()\fP call\&.
+.IP "\fB\f(CWbind=<sockname>\fP\fP"
+Binds the socket to the given socket address using the \f(CWbind()\fP system
+call\&. The form of <sockname> is socket domain dependent:
+IP4 and IP6 allow the form [hostname|hostaddress][:(service|port)] (example),
+UNIX domain sockets require <filename>\&.
+.IP "\fB\f(CWconnect-timeout=<seconds>\fP\fP"
+Abort the connection attempt after <seconds> [timeval]
+with error status\&.
+.IP "\fB\f(CWinterface=<interface>\fP\fP"
+Binds the socket to the given <interface>\&.
+This option might require root privilege\&.
+.IP "\fB\f(CWbroadcast\fP\fP"
+For datagram sockets, allows sending to broadcast addresses and receiving
+packets addressed to broadcast addresses\&.
+.IP "\fB\f(CWbsdcompat\fP\fP"
+Emulates some (old?) bugs of the BSD socket implementation\&.
+.IP "\fB\f(CWdebug\fP\fP"
+Enables socket debugging\&.
+.IP "\fB\f(CWdontroute\fP\fP"
+Only communicates with directly connected peers, does not use routers\&.
+.IP "\fB\f(CWkeepalive\fP\fP"
+Enables sending keepalives on the socket\&.
+.IP "\fB\f(CWlinger=<seconds>\fP\fP"
+Blocks \f(CWshutdown()\fP or \f(CWclose()\fP until data transfers have finished
+or the given timeout [int] expired\&.
+.IP "\fB\f(CWoobinline\fP\fP"
+Places out-of-band data in the input data stream\&.
+.IP "\fB\f(CWpriority=<priority>\fP\fP"
+Sets the protocol defined <priority> [<int>] for outgoing
+packets\&.
+.IP "\fB\f(CWrcvbuf=<bytes>\fP\fP"
+Sets the size of the receive buffer after the \f(CWsocket()\fP call to
+<bytes> [int]\&. With TCP
+sockets, this value corresponds to the socket\'s maximal window size\&.
+.IP "\fB\f(CWrcvbuf-late=<bytes>\fP\fP"
+Sets the size of the receive buffer when the socket is already
+connected to <bytes> [int]\&.
+With TCP sockets, this value corresponds to the socket\'s
+maximal window size\&.
+.IP "\fB\f(CWrcvlowat=<bytes>\fP\fP"
+Specifies the minimum number of received bytes [int] until
+the socket layer will pass the buffered data to \fBsocat\fP\&.
+.IP "\fB\f(CWrcvtimeo=<seconds>\fP\fP"
+Sets the receive timeout [timeval]\&.
+.IP "\fB\f(CWreuseaddr\fP\fP"
+Allows other sockets to bind to an address even if parts of it (e\&.g\&. the
+local port) are already in use by \fBsocat\fP (example)\&.
+.IP "\fB\f(CWsndbuf=<bytes>\fP\fP"
+Sets the size of the send buffer after the \f(CWsocket()\fP call to
+<bytes> [int]\&.
+.IP "\fB\f(CWsndbuf-late=<bytes>\fP\fP"
+Sets the size of the send buffer when the socket is connected to
+<bytes> [int]\&.
+.IP "\fB\f(CWsndlowat=<bytes>\fP\fP"
+Specifies the minimum number of bytes in the send buffer until the socket
+layer will send the data to <bytes> [int]\&.
+.IP "\fB\f(CWsndtimeo=<seconds>\fP\fP"
+Sets the send timeout to seconds [timeval]\&.
+.IP "\fB\f(CWtype=<type>\fP\fP"
+Sets the type of the socket, usually as argument to the \f(CWsocket()\fP or
+\f(CWsocketpair()\fP call, to <type> [int]\&.
+Under Linux, 1 means stream oriented socket, 2 means datagram socket, and 3
+means raw socket\&.
+.IP "\fB\f(CWpf=<string>\fP\fP"
+Forces the use of the specified IP version\&. <string> can be
+something like "ip4" or "ip6"\&.
+.PP
+.br
+.PP
+\fI\fBUNIX option group\fP\fP
+.PP
+These options apply to UNIX domain based addresses\&.
+.IP "\fB\f(CWunix-tightsocklen=[0|1]\fP\fP"
+On socket operations, pass a socket address length that does not include the
+whole \f(CWstruct sockaddr_un\fP record but (besides other components) only
+the relevant part of the filename or abstract string\&. Default is 1\&.
+.PP
+\fI\fBIP4 and IP6 option groups\fP\fP
+.PP
+These options can be used with IPv4 and IPv6 based sockets\&.
+.IP "\fB\f(CWtos=<tos>\fP\fP"
+Sets the TOS (type of service) field of outgoing packets to <tos>
+[byte] (see RFC 791)\&.
+.IP "\fB\f(CWttl=<ttl>\fP\fP"
+Sets the TTL (time to live) field of outgoing packets to <ttl>
+[byte]\&.
+.IP "\fB\f(CWipoptions=<data>\fP\fP"
+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 \f(CWipoptions=x8307040a000001\fP\&.
+.br
+IP options are defined in RFC 791\&.
+.br
+.IP "\fB\f(CWmtudiscover=<0|1|2>\fP\fP"
+Takes 0, 1, 2 to never, want, or always use path MTU discover on this
+socket\&.
+.IP "\fB\f(CWip-add-membership=<multicast-address:interface-address>\fP\fP"
+.IP "\fB\f(CWip-add-membership=<multicast-address:interface-name>\fP\fP"
+.IP "\fB\f(CWip-add-membership=<multicast-address:interface-index>\fP\fP"
+.IP "\fB\f(CWip-add-membership=<multicast-address:interface-address:interface-name>\fP\fP"
+.IP "\fB\f(CWip-add-membership=<multicast-address:interface-address:interface-index>\fP\fP"
+Makes the socket member of the specified multicast group\&. This is currently
+only implemented for IPv4\&. The option takes the IP address of the multicast
+group and info about the desired network interface\&. The most common syntax
+is the first one, while the others are only available on systems that
+provide \f(CWstruct mreqn\fP (Linux)\&.
+.br
+The indices of active network interfaces can be shown using the utility
+\fBprocan\fP\&.
+dif(\fB\f(CWip-multicast-if=<hostname>\fP\fP)
+Specifies hostname or address of the network interface to be used for
+multicast traffic\&.
+dif(\fB\f(CWip-multicast-loop=<bool>\fP\fP)
+Specifies if outgoing multicast traffic should loop back to the interface\&.
+dif(\fB\f(CWip-multicast-ttl=<byte>\fP\fP)
+Sets the TTL used for outgoing multicast traffic\&. Default is 1\&.
+.IP "\fB\f(CWres-debug\fP\fP"
+.IP "\fB\f(CWres-aaonly\fP\fP"
+.IP "\fB\f(CWres-usevc\fP\fP"
+.IP "\fB\f(CWres-primary\fP\fP"
+.IP "\fB\f(CWres-igntc\fP\fP"
+.IP "\fB\f(CWres-recurse\fP\fP"
+.IP "\fB\f(CWres-defnames\fP\fP"
+.IP "\fB\f(CWres-stayopen\fP\fP"
+.IP "\fB\f(CWres-dnsrch\fP\fP"
+These options set the corresponding resolver (name resolution) option flags\&.
+Append "=0" to clear a default option\&. See man resolver(5) for more
+information on these options\&. Note: these options are valid only for the
+address they are applied to\&.
+.IP
+.PP
+.br
+.PP
+\fI\fBIP6 option group\fP\fP
+.PP
+These options can only be used on IPv6 based sockets\&. See IP
+options for options that can be applied to both IPv4 and IPv6
+sockets\&.
+.IP "\fB\f(CWipv6only=<bool>\fP\fP"
+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\&.
+.PP
+.br
+.PP
+\fI\fBTCP option group\fP\fP
+.PP
+These options may be applied to TCP sockets\&. They work by invoking \f(CWsetsockopt()\fP with the appropriate parameters\&.
+.IP "\fB\f(CWcork\fP\fP"
+Doesn\'t send packets smaller than MSS (maximal segment size)\&.
+.IP "\fB\f(CWdefer-accept\fP\fP"
+While listening, accepts connections only when data from the peer arrived\&.
+.IP "\fB\f(CWkeepcnt=<count>\fP\fP"
+Sets the number of keepalives before shutting down the socket to
+<count> [int]\&.
+.IP "\fB\f(CWkeepidle=<seconds>\fP\fP"
+Sets the idle time before sending the first keepalive to <seconds>
+[int]\&.
+.IP "\fB\f(CWkeepintvl=<seconds>\fP\fP"
+Sets the intervall between two keepalives to <seconds>
+[int]\&.
+.IP "\fB\f(CWlinger2=<seconds>\fP\fP"
+Sets the time to keep the socket in FIN-WAIT-2 state to <seconds>
+[int]\&.
+.IP "\fB\f(CWmss=<bytes>\fP\fP"
+Sets the MSS (maximum segment size) after the \f(CWsocket()\fP call to <bytes>
+[int]\&. This
+value is then proposed to the peer with the SYN or SYN/ACK packet
+(example)\&.
+.IP "\fB\f(CWmss-late=<bytes>\fP\fP"
+Sets the MSS of the socket after connection has been established to <bytes>
+[int]\&.
+.IP "\fB\f(CWnodelay\fP\fP"
+Turns off the Nagle algorithm for measuring the RTT (round trip time)\&.
+.IP "\fB\f(CWrfc1323\fP\fP"
+Enables RFC1323 TCP options: TCP window scale, round-trip time measurement
+(RTTM), and protect against wrapped sequence numbers (PAWS) (AIX)\&.
+.IP "\fB\f(CWstdurg\fP\fP"
+Enables RFC1122 compliant urgent pointer handling (AIX)\&.
+.IP "\fB\f(CWsyncnt=<count>\fP\fP"
+Sets the maximal number of SYN retransmits during connect to <count>
+[int]\&.
+.IP "\fB\f(CWmd5sig\fP\fP"
+Enables generation of MD5 digests on the packets (FreeBSD)\&.
+.IP "\fB\f(CWnoopt\fP\fP"
+Disables use of TCP options (FreeBSD, MacOSX)\&.
+.IP "\fB\f(CWnopush\fP\fP"
+sets the TCP_NOPUSH socket option (FreeBSD, MacOSX)\&.
+.IP "\fB\f(CWsack-disable\fP\fP"
+Disables use the selective acknowledge feature (OpenBSD)\&.
+.IP "\fB\f(CWsignature-enable\fP\fP"
+Enables generation of MD5 digests on the packets (OpenBSD)\&.
+.IP "\fB\f(CWabort-threshold=<milliseconds>\fP\fP"
+Sets the time to wait for an answer of the peer on an established connection
+(HP-UX)\&.
+.IP "\fB\f(CWconn-abort-threshold=<milliseconds>\fP\fP"
+Sets the time to wait for an answer of the server during the initial connect
+(HP-UX)\&.
+.IP "\fB\f(CWkeepinit\fP\fP"
+Sets the time to wait for an answer of the server during connect() before
+giving up\&. Value in half seconds, default is 150 (75s) (Tru64)\&.
+.IP "\fB\f(CWpaws\fP\fP"
+Enables the "protect against wrapped sequence numbers" feature (Tru64)\&.
+.IP "\fB\f(CWsackena\fP\fP"
+Enables selective acknowledge (Tru64)\&.
+.IP "\fB\f(CWtsoptena\fP\fP"
+Enables the time stamp option that allows RTT recalculation on existing
+connections (Tru64)\&.
+.PP
+.br
+.PP
+\fI\fBUDP and TCP option groups\fP\fP
+.PP
+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\&.
+.IP "\fB\f(CWsourceport=<port>\fP\fP"
+For outgoing (client) TCP and UDP connections, it sets the source
+<port> using an extra \f(CWbind()\fP call\&.
+With TCP or UDP listen addresses, socat immediately shuts down the
+connection if the client does not use this sourceport (example)\&.
+.IP "\fB\f(CWlowport\fP\fP"
+Outgoing (client) TCP and UDP connections with this option use
+an unused random source port between 640 and 1023 incl\&. On UNIX class operating
+systems, this requires root privilege, and thus indicates that the
+client process is authorized by local root\&.
+TCP and UDP listen addresses with this option immediately shut down the
+connection if the client does not use a sourceport <= 1023\&.
+This mechanism can provide limited authorization under some circumstances\&.
+.PP
+.br
+.PP
+\fI\fBSOCKS option group\fP\fP
+.PP
+When using SOCKS type addresses, some socks specific options can be set\&.
+.IP "\fB\f(CWsocksport=<tcp service>\fP\fP"
+Overrides the default "socks" service or port 1080 for the socks server
+port with <TCP service>\&.
+.IP "\fB\f(CWsocksuser=<user>\fP\fP"
+Sends the <user> [string] in the username field to the
+socks server\&. Default is the actual user name ($LOGNAME or $USER) (example)\&.
+.PP
+.br
+.PP
+\fI\fBHTTP option group\fP\fP
+.PP
+Options that can be provided with HTTP type addresses\&. The only HTTP address
+currently implemented is proxy-connect\&.
+.PP
+.IP "\fB\f(CWproxyport=<TCP service>\fP\fP"
+Overrides the default HTTP proxy port 8080 with
+<TCP service>\&.
+.IP "\fB\f(CWignorecr\fP\fP"
+The HTTP protocol requires the use of CR+NL as line terminator\&. When a proxy
+server violates this standard, socat might not understand its answer\&.
+This option directs socat to interprete NL as line terminator and
+to ignore CR in the answer\&. Nevertheless, socat sends CR+NL to the proxy\&.
+.IP "\fB\f(CWproxyauth=<username>:<password>\fP\fP"
+Provide "basic" authentication to the proxy server\&. The argument to the
+option is used with a "Proxy-Authorization: Base" header in base64 encoded
+form\&.
+.br
+Note: username and password are visible for every user on the local machine
+in the process list; username and password are transferred to the proxy
+server unencrypted (base64 encoded) and might be sniffed\&.
+.IP "\fB\f(CWresolve\fP\fP"
+Per default, socat sends to the proxy a CONNECT request containing the
+target hostname\&. With this option, socat resolves the hostname locally and
+sends the IP address\&. Please note that, according to RFC 2396, only name
+resolution to IPv4 addresses is implemented\&.
+.PP
+.br
+.PP
+\fI\fBRANGE option group\fP\fP
+.PP
+These options check if a connecting client should be granted access\&. They can
+be applied to listening and receiving network sockets\&. tcp-wrappers options
+fall into this group\&.
+.IP "\fB\f(CWrange=<address-range>\fP\fP"
+After accepting a connection, tests if the peer is within \fIrange\fP\&. For
+IPv4 addresses, address-range takes the form address/bits, e\&.g\&.
+10\&.0\&.0\&.0/8, or address:mask, e\&.g\&. 10\&.0\&.0\&.0:255\&.0\&.0\&.0 (example); for IPv6, it is [ip6-address/bits], e\&.g\&. [::1/128]\&.
+If the client address does not match, \fBsocat\fP issues a warning and keeps
+listening/receiving\&.
+.IP "\fB\f(CWtcpwrap[=<name>]\fP\fP"
+Uses Wietse Venema\'s libwrap (tcpd) library to determine
+if the client is allowed to connect\&. The configuration files are
+/etc/hosts\&.allow and /etc/hosts\&.deny per default, see "man 5 hosts_access"
+for more information\&. The optional <name> (type string)
+is passed to the wrapper functions as daemon process name (example)\&.
+If omitted, the basename of socats invocation (argv[0]) is passed\&.
+If both tcpwrap and range options are applied to an address, both
+conditions must be fulfilled to allow the connection\&.
+.IP "\fB\f(CWallow-table=<filename>\fP\fP"
+Takes the specified file instead of /etc/hosts\&.allow\&.
+.IP "\fB\f(CWdeny-table=<filename>\fP\fP"
+Takes the specified file instead of /etc/hosts\&.deny\&.
+.IP "\fB\f(CWtcpwrap-etc=<directoryname>\fP\fP"
+Looks for hosts\&.allow and hosts\&.deny in the specified directory\&. Is
+overridden by options hosts-allow
+and hosts-deny\&.
+.PP
+.br
+.PP
+\fI\fBLISTEN option group\fP\fP
+.PP
+Options specific to listening sockets\&.
+.IP "\fB\f(CWbacklog=<count>\fP\fP"
+Sets the backlog value passed with the \f(CWlisten()\fP system call to <count>
+[int]\&. Default is 5\&.
+.br
+.PP
+\fI\fBCHILD option group\fP\fP
+.PP
+Options for addresses with multiple connections via child processes\&.
+.IP "\fB\f(CWfork\fP\fP"
+After establishing a connection, handles its channel in a child process and
+keeps the parent process attempting to produce more connections, either by
+listening or by connecting in a loop (example)\&.
+.br
+SSL-CONNECT and SSL-LISTEN differ in when they actually fork off the child:
+SSL-LISTEN forks \fIbefore\fP the SSL handshake, while SSL-CONNECT forks
+\fIafterwards\fP\&.
+RETRY and FOREVER options are not inherited by the child process\&.
+.br
+.PP
+.br
+.PP
+\fI\fBEXEC option group\fP\fP
+.PP
+Options for addresses that invoke a program\&.
+.IP "\fB\f(CWpath=<string>\fP\fP"
+Overrides the PATH environment variable for searching the program with
+<string>\&. This
+\f(CW$PATH\fP value is effective in the child process too\&.
+.IP "\fB\f(CWlogin\fP\fP"
+Prefixes \f(CWargv[0]\fP for the \f(CWexecvp()\fP call with \'-\', thus making a
+shell behave as login shell\&.
+.PP
+.br
+.PP
+\fI\fBFORK option group\fP\fP
+.PP
+EXEC or SYSTEM addresses invoke a program using a child process and transfer data between \fBsocat\fP and the program\&. The interprocess communication mechanism can be influenced with the following options\&. Per
+default, a \f(CWsocketpair()\fP is created and assigned to stdin and stdout of
+the child process, while stderr is inherited from the \fBsocat\fP process, and the
+child process uses file descriptors 0 and 1 for communicating with the main
+socat process\&.
+.IP "\fB\f(CWnofork\fP\fP"
+Does not fork a subprocess for executing the program, instead calls execvp()
+or system() directly from the actual socat instance\&. This avoids the
+overhead of another process between the program and its peer,
+but introduces a lot of restrictions:
+.IP o
+this option can only be applied to the second \fBsocat\fP address\&.
+.IP o
+it cannot be applied to a part of a dual address\&.
+.IP o
+the first socat address cannot be OPENSSL or READLINE
+.IP o
+socat options -b, -t, -D, -l, -v, -x become useless
+.IP o
+for both addresses, options ignoreeof, cr, and crnl become useless
+.IP o
+for the second address (the one with option nofork), options
+append, cloexec, flock, user, group, mode, nonblock,
+perm-late, setlk, and setpgid cannot be applied\&. Some of these could be
+used on the first address though\&.
+.IP "\fB\f(CWpipes\fP\fP"
+Creates a pair of unnamed pipes for interprocess communication instead of a
+socket pair\&.
+.IP "\fB\f(CWopenpty\fP\fP"
+Establishes communication with the sub process using a pseudo terminal
+created with \f(CWopenpty()\fP instead of the default (socketpair or ptmx)\&.
+.IP "\fB\f(CWptmx\fP\fP"
+Establishes communication with the sub process using a pseudo terminal
+created by opening \fB/dev/ptmx\fP or \fB/dev/ptc\fP instead of the default
+(socketpair)\&.
+.IP "\fB\f(CWpty\fP\fP"
+Establishes communication with the sub process using a pseudo terminal
+instead of a socket pair\&. Creates the pty with an available mechanism\&. If
+openpty and ptmx are both available, it uses ptmx because this is POSIX
+compliant (example)\&.
+.IP "\fB\f(CWctty\fP\fP"
+Makes the pty the controlling tty of the sub process (example)\&.
+.IP "\fB\f(CWstderr\fP\fP"
+Directs stderr of the sub process to its output channel by making stderr a
+\f(CWdup()\fP of stdout (example)\&.
+.IP "\fB\f(CWfdin=<fdnum>\fP\fP"
+Assigns the sub processes input channel to its file descriptor
+<fdnum>
+instead of stdin (0)\&. The program started from the subprocess has to use
+this fd for reading data from \fBsocat\fP (example)\&.
+.IP "\fB\f(CWfdout=<fdnum>\fP\fP"
+Assigns the sub processes output channel to its file descriptor
+<fdnum>
+instead of stdout (1)\&. The program started from the subprocess has to use
+this fd for writing data to \fBsocat\fP (example)\&.
+.IP "\fB\f(CWsighup\fP\fP, \fB\f(CWsigint\fP\fP, \fB\f(CWsigquit\fP\fP"
+Has \fBsocat\fP pass an eventual signal of this type to the sub process\&.
+If no address has this option, socat terminates on these signals\&.
+.PP
+.br
+.PP
+\fI\fBTERMIOS option group\fP\fP
+.PP
+For addresses that work on a tty (e\&.g\&., stdio, file:/dev/tty, exec:\&.\&.\&.,pty), the terminal parameters defined in the UN*X termios mechanism are made available as address option parameters\&.
+Please note that changes of the parameters of your interactive terminal
+remain effective after \fBsocat\fP\'s termination, so you might have to enter "reset"
+or "stty sane" in your shell afterwards\&.
+For EXEC and SYSTEM addresses with option PTY,
+these options apply to the pty by the child processes\&.
+.PP
+.IP "\fB\f(CWb0\fP\fP"
+Disconnects the terminal\&.
+.IP "\fB\f(CWb19200\fP\fP"
+Sets the serial line speed to 19200 baud\&. Some other rates are possible; use
+something like \f(CWsocat -hh |grep \' b[1-9]\'\fP to find all speeds supported by
+your implementation\&.
+.br
+Note: On some operating systems, these options may not be
+available\&. Use ispeed or ospeed
+instead\&.
+.IP "\fB\f(CWecho=<bool>\fP\fP"
+Enables or disables local echo (example)\&.
+.IP "\fB\f(CWicanon=<bool>\fP\fP"
+Sets or clears canonical mode, enabling line buffering and some special
+characters\&.
+.IP "\fB\f(CWraw\fP\fP"
+Sets raw mode, thus passing input and output almost unprocessed (example)\&.
+.IP "\fB\f(CWignbrk=<bool>\fP\fP"
+Ignores or interpretes the BREAK character (e\&.g\&., ^C)
+.IP "\fB\f(CWbrkint=<bool>\fP\fP"
+.IP "\fB\f(CWbs0\fP\fP"
+.IP "\fB\f(CWbs1\fP\fP"
+.IP "\fB\f(CWbsdly=<0|1>\fP\fP"
+.IP "\fB\f(CWclocal=<bool>\fP\fP"
+.IP
+\.LP
+\.nf
+\fBcr0
+cr1
+cr2
+cr3\fP
+\.fi
+\.IP
+Sets the carriage return delay to 0, 1, 2, or 3, respectively\&.
+0 means no delay, the other values are terminal dependent\&.
+.IP
+.IP "\fB\f(CWcrdly=<0|1|2|3>\fP\fP"
+.IP "\fB\f(CWcread=<bool>\fP\fP"
+.IP "\fB\f(CWcrtscts=<bool>\fP\fP"
+.IP
+\.LP
+\.nf
+\fBcs5
+cs6
+cs7
+cs8\fP
+\.fi
+\.IP
+Sets the character size to 5, 6, 7, or 8 bits, respectively\&.
+.IP
+.IP "\fB\f(CWcsize=<0|1|2|3>\fP\fP"
+.IP "\fB\f(CWcstopb=<bool>\fP\fP"
+Sets two stop bits, rather than one\&.
+.IP "\fB\f(CWdsusp=<byte>\fP\fP"
+Sets the value for the VDSUSP character that suspends the current foreground
+process and reactivates the shell (all except Linux)\&.
+.IP "\fB\f(CWechoctl=<bool>\fP\fP"
+Echos control characters in hat notation (e\&.g\&. ^A)
+.IP "\fB\f(CWechoe=<bool>\fP\fP"
+.IP "\fB\f(CWechok=<bool>\fP\fP"
+.IP "\fB\f(CWechoke=<bool>\fP\fP"
+.IP "\fB\f(CWechonl=<bool>\fP\fP"
+.IP "\fB\f(CWechoprt=<bool>\fP\fP"
+.IP "\fB\f(CWeof=<byte>\fP\fP"
+.IP "\fB\f(CWeol=<byte>\fP\fP"
+.IP "\fB\f(CWeol2=<byte>\fP\fP"
+.IP "\fB\f(CWerase=<byte>\fP\fP"
+.IP "\fB\f(CWdiscard=<byte>\fP\fP"
+.IP "\fB\f(CWff0\fP\fP"
+.IP "\fB\f(CWff1\fP\fP"
+.IP "\fB\f(CWffdly=<bool>\fP\fP"
+.IP "\fB\f(CWflusho=<bool>\fP\fP"
+.IP "\fB\f(CWhupcl=<bool>\fP\fP"
+.IP "\fB\f(CWicrnl=<bool>\fP\fP"
+.IP "\fB\f(CWiexten=<bool>\fP\fP"
+.IP "\fB\f(CWigncr=<bool>\fP\fP"
+.IP "\fB\f(CWignpar=<bool>\fP\fP"
+.IP "\fB\f(CWimaxbel=<bool>\fP\fP"
+.IP "\fB\f(CWinlcr=<bool>\fP\fP"
+.IP "\fB\f(CWinpck=<bool>\fP\fP"
+.IP "\fB\f(CWintr=<byte>\fP\fP"
+.IP "\fB\f(CWisig=<bool>\fP\fP"
+.IP "\fB\f(CWispeed=<unsigned-int>\fP\fP"
+Set the baud rate for incoming data on this line\&.
+.br
+See also: ospeed, b19200
+dif(\fB\f(CWistrip=<bool>\fP\fP)
+.IP "\fB\f(CWiuclc=<bool>\fP\fP"
+.IP "\fB\f(CWixany=<bool>\fP\fP"
+.IP "\fB\f(CWixoff=<bool>\fP\fP"
+.IP "\fB\f(CWixon=<bool>\fP\fP"
+.IP "\fB\f(CWkill=<byte>\fP\fP"
+.IP "\fB\f(CWlnext=<byte>\fP\fP"
+.IP "\fB\f(CWmin=<byte>\fP\fP"
+.IP "\fB\f(CWnl0\fP\fP"
+Sets the newline delay to 0\&.
+.IP "\fB\f(CWnl1\fP\fP"
+.IP "\fB\f(CWnldly=<bool>\fP\fP"
+.IP "\fB\f(CWnoflsh=<bool>\fP\fP"
+.IP "\fB\f(CWocrnl=<bool>\fP\fP"
+.IP "\fB\f(CWofdel=<bool>\fP\fP"
+.IP "\fB\f(CWofill=<bool>\fP\fP"
+.IP "\fB\f(CWolcuc=<bool>\fP\fP"
+.IP "\fB\f(CWonlcr=<bool>\fP\fP"
+.IP "\fB\f(CWonlret=<bool>\fP\fP"
+.IP "\fB\f(CWonocr=<bool>\fP\fP"
+.IP "\fB\f(CWopost=<bool>\fP\fP"
+Enables or disables output processing; e\&.g\&., converts NL to CR-NL\&.
+.IP "\fB\f(CWospeed=<unsigned-int>\fP\fP"
+Set the baud rate for outgoing data on this line\&.
+.br
+See also: ispeed, b19200
+.IP "\fB\f(CWparenb=<bool>\fP\fP"
+Enable parity generation on output and parity checking for input\&.
+.IP "\fB\f(CWparmrk=<bool>\fP\fP"
+.IP "\fB\f(CWparodd=<bool>\fP\fP"
+.IP "\fB\f(CWpendin=<bool>\fP\fP"
+.IP "\fB\f(CWquit=<byte>\fP\fP"
+.IP "\fB\f(CWreprint=<byte>\fP\fP"
+.IP "\fB\f(CWsane\fP\fP"
+Brings the terminal to something like a useful default state\&.
+.IP "\fB\f(CWstart=<byte>\fP\fP"
+.IP "\fB\f(CWstop=<byte>\fP\fP"
+.IP "\fB\f(CWsusp=<byte>\fP\fP"
+.IP "\fB\f(CWswtc=<byte>\fP\fP"
+.IP "\fB\f(CWtab0\fP\fP"
+.IP "\fB\f(CWtab1\fP\fP"
+.IP "\fB\f(CWtab2\fP\fP"
+.IP "\fB\f(CWtab3\fP\fP"
+.IP "\fB\f(CWtabdly=<unsigned-int>\fP\fP"
+.IP "\fB\f(CWtime=<byte>\fP\fP"
+.IP "\fB\f(CWtostop=<bool>\fP\fP"
+.IP "\fB\f(CWvt0\fP\fP"
+.IP "\fB\f(CWvt1\fP\fP"
+.IP "\fB\f(CWvtdly=<bool>\fP\fP"
+.IP "\fB\f(CWwerase=<byte>\fP\fP"
+.IP "\fB\f(CWxcase=<bool>\fP\fP"
+.IP "\fB\f(CWxtabs\fP\fP"
+.PP
+.br
+.PP
+\fI\fBPTY option group\fP\fP
+.PP
+These options are intended for use with the pty address
+type\&.
+.PP
+.IP "\fB\f(CWlink=<filename>\fP\fP"
+Generates a symbolic link that points to the actual pseudo terminal
+(pty)\&. This might help
+to solve the problem that ptys are generated with more or less
+unpredictable names, making it difficult to directly access the socat
+generated pty automatically\&. With this option, the user can specify a "fix"
+point in the file hierarchy that helps him to access the actual pty
+(example)\&.
+Beginning with \fBsocat\fP version 1\&.4\&.3, the symbolic link is removed when
+the address is closed (but see option unlink-close)\&.
+.IP "\fB\f(CWwait-slave\fP\fP"
+Blocks the open phase until a process opens the slave side of the pty\&.
+Usually, socat continues after generating the pty with opening the next
+address or with entering the transfer loop\&. With the wait-slave option,
+socat waits until some process opens the slave side of the pty before
+continuing\&.
+This option only works if the operating system provides the \f(CWpoll()\fP
+system call\&. And it depends on an undocumented behaviour of pty\'s, so it
+does not work on all operating systems\&. It has successfully been tested on
+Linux, FreeBSD, NetBSD, and on Tru64 with openpty\&.
+.IP "\fB\f(CWpty-intervall=<seconds>\fP\fP"
+When the wait-slave option is set, socat
+periodically checks the HUP condition using \f(CWpoll()\fP to find if the pty\'s
+slave side has been opened\&. The default polling intervall is 1s\&. Use the
+pty-intervall option [timeval] to change this value\&.
+.PP
+.br
+.PP
+\fI\fBOPENSSL option group\fP\fP
+.PP
+These options apply to the openssl and
+openssl-listen address types\&.
+.PP
+.IP "\fB\f(CWcipher=<cipherlist>\fP\fP"
+Selects the list of ciphers that may be used for the connection\&.
+See the man page of \f(CWciphers\fP, section \fBCIPHER LIST FORMAT\fP, for
+detailed information about syntax, values, and default of <cipherlist>\&.
+.br
+Several cipher strings may be given, separated by \':\'\&.
+Some simple cipher strings:
+.IP "3DES"
+Uses a cipher suite with triple DES\&.
+.IP "MD5"
+Uses a cipher suite with MD5\&.
+.IP "aNULL"
+Uses a cipher suite without authentication\&.
+.IP "NULL"
+Does not use encryption\&.
+.IP "HIGH"
+Uses a cipher suite with "high" encryption\&.
+Note that the peer must support the selected property, or the negotiation
+will fail\&.
+.IP "\fB\f(CWmethod=<ssl-method>\fP\fP"
+Sets the protocol version to be used\&. Valid strings (not case sensitive)
+are:
+.IP "\f(CWSSLv2\fP"
+Select SSL protocol version 2\&.
+.IP "\f(CWSSLv3\fP"
+Select SSL protocol version 3\&.
+.IP "\f(CWSSLv23\fP"
+Select SSL protocol version 2 or 3\&. This is the default when
+this option is not provided\&.
+.IP "\f(CWTLSv1\fP"
+Select TLS protocol version 1\&.
+.IP "\fB\f(CWverify=<bool>\fP\fP"
+Controls check of the peer\'s certificate\&. Default is 1 (true)\&. Disabling
+verify might open your socket for everyone, making the encryption useless!
+.IP "\fB\f(CWcert=<filename>\fP\fP"
+Specifies the file with the certificate and private key for authentication\&.
+The certificate must be in OpenSSL format (*\&.pem)\&.
+With openssl-listen, use of this option is strongly
+recommended\&. Except with cipher aNULL, "no shared ciphers" error will
+occur when no certificate is given\&.
+.IP "\fB\f(CWkey=<filename>\fP\fP"
+Specifies the file with the private key\&. The private key may be in this
+file or in the file given with the cert option\&. The party that has
+to proof that it is the owner of a certificate needs the private key\&.
+.IP "\fB\f(CWdhparams=<filename>\fP\fP"
+Specifies the file with the Diffie Hellman parameters\&. These parameters may
+also be in the file given with the cert
+option in which case the dhparams option is not needed\&.
+.IP "\fB\f(CWcafile=<filename>\fP\fP"
+Specifies the file with the trusted (root) authority certificates\&. The file
+must be in PEM format and should contain one or more certificates\&. The party
+that checks the authentication of its peer trusts only certificates that are
+in this file\&.
+.IP "\fB\f(CWcapath=<dirname>\fP\fP"
+Specifies the directory with the trusted (root) certificates\&. The directory
+must contain certificates in PEM format and their hashes (see OpenSSL
+documentation)
+.IP "\fB\f(CWegd=<filename>\fP\fP"
+On some systems, openssl requires an explicit source of random data\&. Specify
+the socket name where an entropy gathering daemon like egd provides random
+data, e\&.g\&. /dev/egd-pool\&.
+.IP "\fB\f(CWpseudo\fP\fP"
+On systems where openssl cannot find an entropy source and where no entropy
+gathering daemon can be utilized, this option activates a mechanism for
+providing pseudo entropy\&. This is archieved by taking the current time in
+microseconds for feeding the libc pseudo random number generator with an
+initial value\&. openssl is then feeded with output from random() calls\&.
+.br
+NOTE:This mechanism is not sufficient for generation of secure keys!
+.IP "\fB\f(CWfips\fP\fP"
+Enables FIPS mode if compiled in\&. For info about the FIPS encryption
+implementation standard see http://oss-institute\&.org/fips-faq\&.html\&.
+This mode might require that the involved certificates are generated with a
+FIPS enabled version of openssl\&. Setting or clearing this option on one
+socat address affects all OpenSSL addresses of this process\&.
+.PP
+.br
+.PP
+\fI\fBRETRY option group\fP\fP
+.PP
+Options that control retry of some system calls, especially connection
+attempts\&.
+.PP
+.IP "\fB\f(CWretry=<num>\fP\fP"
+Number of retries before the connection or listen attempt is aborted\&.
+Default is 0, which means just one attempt\&.
+.IP "\fB\f(CWintervall=<timespec>\fP\fP"
+Time between consecutive attempts (seconds,
+[timespec])\&. Default is 1 second\&.
+.IP "\fB\f(CWforever\fP\fP"
+Performs an unlimited number of retry attempts\&.
+.PP
+.br
+.PP
+\fI\fBTUN option group\fP\fP
+.PP
+Options that control Linux TUN/TAP interface device addresses\&.
+.PP
+.IP "\fB\f(CWtun-device=<device-file>\fP\fP"
+Instructs socat to take another path for the TUN clone device\&. Default is
+\f(CW/dev/net/tun\fP\&.
+.IP "\fB\f(CWtun-name=<if-name>\fP\fP"
+Gives the resulting network interface a specific name instead of the system
+generated (tun0, tun1, etc\&.)
+.IP "\fB\f(CWtun-type=[tun|tap]\fP\fP"
+Sets the type of the TUN device; use this option to generate a TAP
+device\&. See the Linux docu for the difference between these types\&.
+When you try to establish a tunnel between two TUN devices, their types
+should be the same\&.
+.IP "\fB\f(CWiff-no-pi\fP\fP"
+Sets the IFF_NO_PI flag which controls if the device includes additional
+packet information in the tunnel\&.
+When you try to establish a tunnel between two TUN devices, these flags
+should have the same values\&.
+.IP "\fB\f(CWiff-up\fP\fP"
+Sets the TUN network interface status UP\&. Strongly recommended\&.
+.IP "\fB\f(CWiff-broadcast\fP\fP"
+Sets the BROADCAST flag of the TUN network interface\&.
+.IP "\fB\f(CWiff-debug\fP\fP"
+Sets the DEBUG flag of the TUN network interface\&.
+.IP "\fB\f(CWiff-loopback\fP\fP"
+Sets the LOOPBACK flag of the TUN network interface\&.
+.IP "\fB\f(CWiff-pointopoint\fP\fP"
+Sets the POINTOPOINT flag of the TUN device\&.
+.IP "\fB\f(CWiff-notrailers\fP\fP"
+Sets the NOTRAILERS flag of the TUN device\&.
+.IP "\fB\f(CWiff-running\fP\fP"
+Sets the RUNNING flag of the TUN device\&.
+.IP "\fB\f(CWiff-noarp\fP\fP"
+Sets the NOARP flag of the TUN device\&.
+.IP "\fB\f(CWiff-promisc\fP\fP"
+Sets the PROMISC flag of the TUN device\&.
+.IP "\fB\f(CWiff-allmulti\fP\fP"
+Sets the ALLMULTI flag of the TUN device\&.
+.IP "\fB\f(CWiff-master\fP\fP"
+Sets the MASTER flag of the TUN device\&.
+.IP "\fB\f(CWiff-slave\fP\fP"
+Sets the SLAVE flag of the TUN device\&.
+.IP "\fB\f(CWiff-multicast\fP\fP"
+Sets the MULTICAST flag of the TUN device\&.
+.IP "\fB\f(CWiff-portsel\fP\fP"
+Sets the PORTSEL flag of the TUN device\&.
+.IP "\fB\f(CWiff-automedia\fP\fP"
+Sets the AUTOMEDIA flag of the TUN device\&.
+.IP "\fB\f(CWiff-dynamic\fP\fP"
+Sets the DYNAMIC flag of the TUN device\&.
+.PP
+.br
+.PP
+.SH "DATA VALUES"
+.PP
+This section explains the different data types that address parameters and
+address options can take\&.
+.PP
+.IP "address-range"
+Is currently only implemented for IPv4 and IPv6\&. See address-option
+`range\'
+.IP "bool"
+"0" or "1"; if value is omitted, "1" is taken\&.
+.IP "byte"
+An unsigned int number, read with \f(CWstrtoul()\fP, lower or equal to
+\f(CWUCHAR_MAX\fP\&.
+.IP "command-line"
+A string specifying a program name and its arguments, separated by single
+spaces\&.
+.IP "data"
+A raw data specification following \fIdalan\fP syntax\&. The only documented
+form is a string starting with \'x\' followed by an even number of hex digits\&.
+.IP "directory"
+A string with usual UN*X directory name semantics\&.
+.IP "facility"
+The name of a syslog facility in lower case characters\&.
+.IP "fdnum"
+An unsigned int type, read with \f(CWstrtoul()\fP, specifying a UN*X file
+descriptor\&.
+.IP "filename"
+A string with usual UN*X filename semantics\&.
+.IP "group"
+If the first character is a decimal digit, the value is read with
+\f(CWstrtoul()\fP as unsigned integer specifying a group id\&. Otherwise, it
+must be an existing group name\&.
+.IP "int"
+A number following the rules of the \f(CWstrtol()\fP function with base
+"0", i\&.e\&. decimal number, octal number with leading "0", or hexadecimal
+number with leading "0x"\&. The value must fit into a C int\&.
+.IP "interface"
+A string specifying the device name of a network interface, e\&.g\&. "eth0"\&.
+.IP "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
+IPv6 address\&.
+.br
+Examples: 127\&.0\&.0\&.1, [::1], www\&.dest-unreach\&.org, dns1
+.IP "IPv4 address"
+An IPv4 address in numbers-and-dots notation or a hostname that resolves to
+an IPv4 address\&.
+.br
+Examples: 127\&.0\&.0\&.1, www\&.dest-unreach\&.org, dns2
+.IP "IPv6 address"
+An iPv6 address in hexnumbers-and-colons notation enclosed in brackets, or a
+hostname that resolves to an IPv6 address\&.
+.br
+Examples: [::1], [1234:5678:9abc:def0:1234:5678:9abc:def0],
+ip6name\&.domain\&.org
+.IP "long"
+A number read with \f(CWstrtol()\fP\&. The value must fit into a C long\&.
+.IP "long long"
+A number read with \f(CWstrtoll()\fP\&. The value must fit into a C long long\&.
+.IP "off_t"
+An implementation dependend signed number, usually 32 bits, read with strtol
+or strtoll\&.
+.IP "off64_t"
+An implementation dependend signed number, usually 64 bits, read with strtol
+or strtoll\&.
+.IP "mode_t"
+An unsigned integer, read with \f(CWstrtoul()\fP, specifying mode (permission)
+bits\&.
+.IP "pid_t"
+A number, read with \f(CWstrtol()\fP, specifying a process id\&.
+.IP "port"
+A uint16_t (16 bit unsigned number) specifying a TCP or UDP port, read
+with \f(CWstrtoul()\fP\&.
+.IP "protocol"
+An unsigned 8 bit number, read with \f(CWstrtoul()\fP\&.
+.IP "size_t"
+An unsigned number with size_t limitations, read with \f(CWstrtoul\fP\&.
+.IP "sockname"
+A socket address\&. See address-option `bind\'
+.IP "string"
+A sequence of characters, not containing \'\e0\' and, depending on
+the position within the command line, \':\', \',\', or "!!"\&. Note
+that you might have to escape shell meta characters in the command line\&.
+.IP "TCP service"
+A service name, not starting with a digit, that is resolved by
+\f(CWgetservbyname()\fP, or an unsigned int 16 bit number read with
+\f(CWstrtoul()\fP\&.
+.IP "timeval"
+A double float specifying seconds; the number is mapped into a
+struct timeval, consisting of seconds and microseconds\&.
+.IP "timespec"
+A double float specifying seconds; the number is mapped into a
+struct timespec, consisting of seconds and nanoseconds\&.
+.IP "UDP service"
+A service name, not starting with a digit, that is resolved by
+\f(CWgetservbyname()\fP, or an unsigned int 16 bit number read with
+\f(CWstrtoul()\fP\&.
+.IP "unsigned int"
+A number read with \f(CWstrtoul()\fP\&. The value must fit into a C unsigned
+int\&.
+.IP "user"
+If the first character is a decimal digit, the value is read with
+\f(CWstrtoul()\fP as unsigned integer specifying a user id\&. Otherwise, it must
+be an existing user name\&.
+.PP
+.SH "EXAMPLES"
+.PP
+.IP
+.IP "\fB\f(CWsocat - TCP4:www\&.domain\&.org:80\fP\fP"
+.IP
+Transfers data between STDIO (-) and a
+TCP4 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
+close the relay with ^D or abort it with ^C\&.
+.IP
+\.LP
+\.nf
+\fBsocat -d -d READLINE,history=$HOME/.http_history \\
+TCP4:www.domain.org:www,crnl\fP
+\.fi
+.IP
+.IP
+This is similar to the previous example, but you can edit the current line in a
+bash like manner (READLINE) and use the
+history file \&.http_history; \fBsocat\fP
+prints messages about progress (-d -d)\&. The port is specified by service name
+(www), and correct network line termination characters (crnl) instead of NL
+are used\&.
+.IP
+.IP "\fB\f(CWsocat TCP4-LISTEN:www TCP4:www\&.domain\&.org:www\fP\fP"
+.IP
+Installs a simple TCP port forwarder\&. With
+TCP4-LISTEN it listens on local port "www" until a
+connection comes in, accepts it, then connects to the remote host
+(TCP4) and starts data transfer\&. It will not accept a
+second connection\&.
+.IP
+\.LP
+\.nf
+\fBsocat -d -d -lmlocal2 \\
+TCP4-LISTEN:80,bind=myaddr1,reuseaddr,fork,su=nobody,range=10.0.0.0/8 \\
+TCP4:www.domain.org:80,bind=myaddr2\fP
+\.fi
+.IP
+.IP
+TCP port forwarder, each side bound to another local IP address
+(bind)\&. This example handles an almost
+arbitrary number of parallel or consecutive connections by
+fork\'ing a new
+process after each \f(CWaccept()\fP\&. It provides a little security by
+su\'ing to user
+nobody after forking; it only permits connections from the private 10 network (range);
+due to reuseaddr, it allows immediate restart after master process\'s
+termination, even if some child sockets are not completely shut down\&.
+With -lmlocal2, socat logs to stderr until successfully
+reaching the accept loop\&. Further logging is directed to syslog with facility
+local2\&.
+.IP
+\.LP
+\.nf
+\fBsocat TCP4-LISTEN:5555,fork,tcpwrap=script \\
+EXEC:/bin/myscript,chroot=/home/sandbox,su-d=sandbox,pty,stderr\fP
+\.fi
+.IP
+.IP
+A simple server that accepts connections
+(TCP4-LISTEN) and 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
+/etc/hosts\&.allow and /etc/hosts\&.deny, otherwise it is refused access (see "man
+5 hosts_access")\&.
+For EXEC\'uting the program, the child process
+chroot\'s
+to \fB/home/sandbox\fP, su\'s to user sandbox, and then starts
+the program \fB/home/sandbox/bin/myscript\fP\&. \fBSocat\fP and
+myscript communicate via a pseudo tty (pty); myscript\'s
+stderr is redirected to stdout,
+so its error messages are transferred via \fBsocat\fP to the connected client\&.
+.IP
+\.LP
+\.nf
+\fBsocat EXEC:"mail.sh target@domain.com",fdin=3,fdout=4 \\
+TCP4:mail.relay.org:25,crnl,bind=alias1.server.org,mss=512\fP
+\.fi
+.IP
+.IP
+\fBmail\&.sh\fP is a shell script, distributed with \fBsocat\fP, that implements a
+simple
+SMTP client\&. It is programmed to "speak" SMTP on its FDs 3 (in) and 4 (out)\&.
+The fdin and fdout options tell \fBsocat\fP
+to use these FDs for communication with
+the program\&. Because mail\&.sh inherits stdin and stdout while \fBsocat\fP does not
+use them, the script can read a
+mail body from stdin\&. \fBSocat\fP makes alias1 your local source address
+(bind), cares for correct network line termination
+(crnl) and sends
+at most 512 data bytes per packet (mss)\&.
+.IP
+.IP "\fB\f(CWsocat - /dev/ttyS0,raw,echo=0,crnl\fP\fP"
+.IP
+Opens an interactive connection via the serial line, e\&.g\&. for talking with a
+modem\&. raw and echo set ttyS0\'s terminal
+parameters to practicable values, crnl
+converts to correct newline characters\&. Consider using
+READLINE instead of `-\'\&.
+.IP
+\.LP
+\.nf
+\fBsocat UNIX-LISTEN:/tmp/.X11-unix/X1,fork \\
+SOCKS4:host.victim.org:127.0.0.1:6000,socksuser=nobody,sourceport=20\fP
+\.fi
+.IP
+.IP
+With UNIX-LISTEN, \fBsocat\fP opens a listening
+UNIX domain socket \fB/tmp/\&.X11-unix/X1\fP\&. This path corresponds
+to local XWindow display :1 on your machine, so XWindow client connections to
+DISPLAY=:1 are accepted\&. \fBSocat\fP then speaks with
+the SOCKS4 server host\&.victim\&.org that might permit
+sourceport 20 based connections due to an FTP related
+weakness in its static IP filters\&. \fBSocat\fP
+pretends to be invoked by socksuser nobody, and
+requests to be connected to
+loopback port 6000 (only weak sockd configurations will allow this)\&. So we get
+a connection to the victims XWindow server and, if it does not require MIT
+cookies or Kerberos authentication, we can start work\&. Please note that there
+can only be one connection at a time, because TCP can establish only one
+session with a given set of addresses and ports\&.
+.IP
+.IP "\fB\f(CWsocat -u /tmp/readdata,seek-end=0,ignoreeof -\fP\fP"
+.IP
+This is an example for unidirectional data transfer
+(-u)\&. \fBSocat\fP transfers data
+from file /tmp/readdata (implicit address GOPEN), starting
+at its current end (seek-end=0 lets \fBsocat\fP start
+reading at current end of file; use seek=0 or no
+seek option to first read the existing data) in a "tail -f" like mode
+(ignoreeof)\&. The "file"
+might also be a listening UNIX domain socket (do not use a seek option then)\&.
+.IP
+\.LP
+\.nf
+\fB(sleep 5; echo PASSWORD; sleep 5; echo ls; sleep 1) |
+socat - EXEC:'ssh -l user server',pty,setsid,ctty\fP
+\.fi
+.IP
+.IP
+EXEC\'utes an ssh session to server\&. Uses a pty for communication between \fBsocat\fP and
+ssh, makes it ssh\'s controlling tty (ctty),
+and makes this pty the owner of
+a new process group (setsid), so ssh accepts the password from \fBsocat\fP\&.
+.IP
+\.LP
+\.nf
+\fBsocat -u TCP4-LISTEN:3334,reuseaddr,fork \\
+OPEN:/tmp/in.log,creat,append\fP
+\.fi
+.IP
+.IP
+Implements a simple network based message collector\&.
+For each client connecting to port 3334, a new child process is generated (option fork)\&.
+All data sent by the clients are append\'ed to the file /tmp/in\&.log\&.
+If the file does not exist, socat creat\'s it\&.
+Option reuseaddr allows immediate restart of the server
+process\&.
+.IP
+.IP
+.IP "\fB\f(CWsocat READLINE,noecho=\'[Pp]assword:\' EXEC:\'ftp ftp\&.server\&.com\',pty,setsid,ctty\fP\fP"
+.IP
+Wraps a command line history (READLINE) around the 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!
+pty is required to have ftp issue a prompt\&.
+Nevertheless, there may occur some confusion with the password and FTP
+prompts\&.
+.IP
+(\fB\f(CWsocat PTY,link=$HOME/dev/vmodem0,raw,echo=0,waitslave EXEC:\'"ssh modemserver\&.us\&.org socat - /dev/ttyS0,nonblock,raw,echo=0"\'\fP\fP)
+.IP
+Generates a pseudo terminal
+device (PTY) on the client that can be reached under the
+symbolic link \fB$HOME/dev/vmodem0\fP\&.
+An application that expects a serial line or modem
+can be configured to use \fB$HOME/dev/vmodem0\fP; its traffic will be directed
+to a modemserver via ssh where another socat instance links it with
+\fB/dev/ttyS0\fP\&.
+.IP
+\.LP
+\.nf
+\fBsocat TCP4-LISTEN:2022,reuseaddr,fork \\
+PROXY:proxy:www.domain.org:22,proxyport=3128,proxyauth=user:pass\fP
+\.fi
+.IP
+.IP
+starts a forwarder that accepts connections on port 2022, and directs them
+through the proxy daemon listening on port 3128
+(proxyport) on host proxy, using the
+CONNECT method, where they are authenticated as "user" with "pass" (proxyauth)\&. The proxy
+should establish connections to host www\&.domain\&.org on port 22 then\&.
+.IP
+.IP "\fB\f(CWsocat - SSL:server:4443,cafile=server\&.crt,cert=client\&.pem\fP\fP"
+.IP
+is an OpenSSL client that tries to establish a secure connection to an SSL
+server\&. Option cafile specifies a file that
+contains trust certificates: we trust the server only when it presents one of
+these certificates and proofs that it owns the related private key\&.
+Otherwise the connection is terminated\&.
+With cert a file containing the client certificate
+and the associated private key is specified\&. This is required in case the
+server wishes a client authentication; many Internet servers do not\&.
+.br
+The first address (\'-\') can be replaced by almost any other socat address\&.
+.IP
+.IP "\fB\f(CWsocat SSL-LISTEN:4443,reuseaddr,pf=ip4,fork,cert=server\&.pem,cafile=client\&.crt PIPE\fP\fP"
+.IP
+is an OpenSSL server that accepts TCP connections, presents the certificate
+from the file server\&.pem and forces the client to present a certificate that is
+verified against cafile\&.crt\&.
+.br
+The second address (\'PIPE\') can be replaced by almost any other socat
+address\&.
+.br
+For instructions on generating and distributing OpenSSL keys and certificates
+see the additional socat docu \f(CWsocat-openssl\&.txt\fP\&.
+.IP
+.IP "\fB\f(CWecho |socat -u - file:/tmp/bigfile,create,largefile,seek=100000000000\fP\fP"
+.IP
+creates a 100GB sparse file; this requires a file system type that
+supports this (ext2, ext3, reiserfs, jfs; not minix, vfat)\&. The operation of
+writing 1 byte might take long (reiserfs: some minutes; ext2: "no" time), and
+the resulting file can consume some disk space with just its inodes (reiserfs:
+2MB; ext2: 16KB)\&.
+.IP
+.IP "\fB\f(CWsocat tcp-l:7777,reuseaddr,fork system:\'filan -i 0 -s >&2\',nofork\fP\fP"
+.IP
+listens for incoming TCP connections on port 7777\&. For each accepted
+connection, invokes a shell\&. This shell has its stdin and stdout directly
+connected to the TCP socket (nofork)\&. The shell starts filan and lets it print the socket addresses to
+stderr (your terminal window)\&.
+.IP
+.IP "\fB\f(CWecho -e "\e0\e14\e0\e0\ec" |socat -u - file:/usr/bin/squid\&.exe,seek=0x00074420\fP\fP"
+.IP
+functions as primitive binary editor: it writes the 4 bytes 000 014 000 000 to
+the executable /usr/bin/squid at offset 0x00074420 (this is a real world patch
+to make the squid executable from Cygwin run under Windows, actual per May 2004)\&.
+.IP
+.IP "\fB\f(CWsocat - tcp:www\&.blackhat\&.org:31337,readbytes=1000\fP\fP"
+.IP
+connects to an unknown service and prevents being flooded\&.
+.IP
+.IP "\fB\f(CWsocat -U TCP:target:9999,end-close TCP-L:8888,reuseaddr,fork\fP\fP"
+.IP
+merges data arriving from different TCP streams on port 8888 to just one stream
+to target:9999\&. The end-close option prevents the child
+processes forked off by the second address from terminating the shared
+connection to 9999 (close(2) just unlinks the inode which stays active as long
+as the parent process lives; shutdown(2) would actively terminate the
+connection)\&.
+.IP
+.IP "\fB\f(CWsocat - UDP4-DATAGRAM:192\&.168\&.1\&.0:123,sp=123,broadcast,range=192\&.168\&.1\&.0/24\fP\fP"
+.IP
+sends a broadcast to the network 192\&.168\&.1\&.0/24 and receives the replies of the
+timeservers there\&. Ignores NTP packets from hosts outside this network\&.
+.IP
+.IP "\fB\f(CWsocat - IP4-DATAGRAM:255\&.255\&.255\&.255:44,broadcast,range=10\&.0\&.0\&.0/8\fP\fP"
+.IP
+sends a broadcast to the local network(s) using protocol 44\&. Accepts replies
+from the private address range only\&.
+.IP
+.IP "\fB\f(CWsocat - UDP4-DATAGRAM:224\&.255\&.0\&.1:6666,bind=:6666,ip-add-membership=224\&.255\&.0\&.1:eth0\fP\fP"
+.IP
+transfers data from stdin to the specified multicast address using UDP\&. Both
+local and remote ports are 6666\&. Tells the interface eth0 to also accept
+multicast packets of the given group\&. Multiple hosts on the local network can
+run this command, so all data sent by any of the hosts will be received
+by all the other ones\&. Note that there are many possible reasons for failure,
+including IP-filters, routing issues, wrong interface selection by the
+operating system, bridges, or a badly configured switch\&.
+.IP
+.IP "\fB\f(CWsocat TCP:host2:4443 TUN:192\&.168\&.255\&.1/24,up\fP\fP"
+.IP
+establishes one side of a virtual (but not private!) network with host2 where a
+similar process might run, with TCP-L and tun address 192\&.168\&.255\&.2\&. They
+can reach each other using the addresses 192\&.168\&.255\&.1 and
+192\&.168\&.255\&.2\&. Substitute the TCP link with an SSL connection protected by
+client and server authentication (see OpenSSL
+client and
+server)\&.
+.IP
+.PP
+.SH "DIAGNOSTICS"
+.PP
+\fBSocat\fP uses a logging mechanism that allows to filter messages by severity\&. The
+severities provided are more or less compatible to the appropriate syslog
+priority\&. With one or up to four occurrences of the -d command line option, the
+lowest priority of messages that are issued can be selected\&. Each message
+contains a single uppercase character specifying the messages severity (one of
+F, E, W, N, I, or D)
+.PP
+.IP "FATAL:"
+Conditions that require unconditional and immediate program termination\&.
+.IP "ERROR:"
+Conditions that prevent proper program processing\&. Usually the
+program is terminated (see option -s)\&.
+.IP "WARNING:"
+Something did not function correctly or is in a state where
+correct further processing cannot be guaranteed, but might be possible\&.
+.IP "NOTICE:"
+Interesting actions of the program, e\&.g\&. for supervising \fBsocat\fP in some kind of server mode\&.
+.IP "INFO:"
+Description of what the program does, and maybe why it
+happens\&. Allows to monitor the lifecycles of file descriptors\&.
+.IP "DEBUG:"
+Description of how the program works, all system or library calls and their results\&.
+.PP
+Log messages can be written to stderr, to a file, or to syslog\&.
+.PP
+On exit, \fBsocat\fP gives status 0 if it terminated due to EOF or inactivity
+timeout, with a positive value on error, and with a negative value on fatal
+error\&.
+.PP
+.SH "FILES"
+.PP
+/usr/bin/socat
+.br
+/usr/bin/filan
+.br
+/usr/bin/procan
+.PP
+.SH "ENVIRONMENT VARIABLES"
+.PP
+.IP "\fBSOCAT_DEFAULT_LISTEN_IP\fP"
+(Values 4 or 6) Sets the IP version to be used
+for listen, recv, and recvfrom addresses if no pf
+(protocol-family) option is given\&. Is overridden by socat options
+-4 or -6\&.
+.IP
+.IP "\fBSOCAT_PREFERRED_RESOLVE_IP\fP"
+(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 pf (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\&.
+.IP
+.IP "\fBSOCAT_FORK_WAIT\fP"
+Specifies the time (seconds) to sleep the parent and
+child processes after successful fork()\&. Useful for debugging\&.
+.IP
+.IP "\fBHOSTNAME\fP"
+Is used to determine the hostname for logging (see
+-lh)\&.
+.IP
+.IP "\fBLOGNAME\fP"
+Is used as name for the socks client user name if no
+socksuser is given\&.
+.br
+With options su and
+su-d, LOGNAME is set to the given user name\&.
+.IP
+.IP "\fBUSER\fP"
+Is used as name for the socks client user name if no
+socksuser is given and LOGNAME is empty\&.
+.br
+With options su and
+su-d, USER is set to the given user name\&.
+.IP
+.IP "\fBSHELL\fP"
+With options su and
+su-d, SHELL is set to the login shell of the
+given user\&.
+.IP
+.IP "\fBPATH\fP"
+Can be set with option path for exec and
+system addresses\&.
+.IP
+.IP "\fBHOME\fP"
+With options su and
+su-d, HOME is set to the home directory of the
+given user\&.
+.IP
+.PP
+.SH "CREDITS"
+.PP
+The work of the following groups and organizations was invaluable for this
+project:
+.PP
+The \fIFSF\fP (GNU, http://www\&.fsf\&.org/ project
+with their free and portable development software and
+lots of other useful tools and libraries\&.
+.PP
+The \fILinux developers community\fP (http://www\&.linux\&.org/) for providing a free, open source operating
+system\&.
+.PP
+The \fIOpen Group\fP (http://www\&.unix-systems\&.org/) for making their
+standard specifications available on the Internet for free\&.
+.PP
+.SH "VERSION"
+.PP
+This man page describes version 1\&.6\&.0 of \fBsocat\fP\&.
+.PP
+.SH "BUGS"
+.PP
+Addresses cannot be nested, so a single socat process cannot, e\&.g\&., drive ssl
+over socks\&.
+.PP
+Address option ftruncate without value uses default 1 instead of 0\&.
+.PP
+Verbose modes (-x and/or -v) display line termination characters inconsistently
+when address options cr or crnl are used: They show the data \fIafter\fP
+conversion in either direction\&.
+.PP
+The data transfer blocksize setting (-b) is ignored with address readline\&.
+.PP
+Send bug reports to <socat@dest-unreach\&.org>
+.PP
+.SH "SEE ALSO"
+.PP
+nc(1), netcat6(1), sock(1), rinetd(8), cage(1), socks\&.conf(5), openssl(1),
+stunnel(8), pty(1), rlwrap(1), setsid(1)
+.PP
+\fBSocat\fP home page http://www\&.dest-unreach\&.org/socat/
+.PP
+.SH "AUTHOR"
+.PP
+Gerhard Rieger <rieger@dest-unreach\&.org>
diff --git a/doc/socat.html b/doc/socat.html
new file mode 100644
index 0000000..47e02fb
--- /dev/null
+++ b/doc/socat.html
@@ -0,0 +1,2686 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<html><head><title>socat</title>
+
+<link rev="made" href="mailto:socat@dest-unreach.org">
+</head>
+<body>
+
+<hr>
+
+<h1>socat</h1>
+<h2>socat</h2>
+<h2>March 2007</h2>
+
+
+
+<p>
+<a name="CONTENTS"></a>
+<h2>CONTENTS</h2>
+
+<a href="socat.html#NAME">NAME</a><br>
+<a href="socat.html#SYNOPSIS">SYNOPSIS</a><br>
+<a href="socat.html#DESCRIPTION">DESCRIPTION</a><br>
+<a href="socat.html#OPTIONS">OPTIONS</a><br>
+<a href="socat.html#ADDRESS_SPECIFICATIONS">ADDRESS SPECIFICATIONS</a><br>
+<a href="socat.html#ADDRESS_TYPES">ADDRESS TYPES</a><br>
+<a href="socat.html#ADDRESS_OPTIONS">ADDRESS OPTIONS</a><br>
+<a href="socat.html#VALUES">DATA VALUES</a><br>
+<a href="socat.html#EXAMPLES">EXAMPLES</a><br>
+<a href="socat.html#DIAGNOSTICS">DIAGNOSTICS</a><br>
+<a href="socat.html#FILES">FILES</a><br>
+<a href="socat.html#ENVIRONMENT_VARIABLES">ENVIRONMENT VARIABLES</a><br>
+<a href="socat.html#CREDITS">CREDITS</a><br>
+<a href="socat.html#VERSION">VERSION</a><br>
+<a href="socat.html#BUGS">BUGS</a><br>
+<a href="socat.html#SEEALSO">SEE ALSO</a><br>
+<p><a name="NAME"></a>
+<h2>NAME</h2>
+ socat - Multipurpose relay (SOcket CAT)
+<p><a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<code>socat [options] <address> <address></code><br>
+<code>socat -V</code><br>
+<code>socat -h[h[h]] | -?[?[?]]</code><br>
+<code>filan</code><br>
+<code>procan</code>
+<p><a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<p><strong>Socat</strong> is a command line based utility that establishes two bidirectional byte
+streams and transfers data between them. Because the streams can be constructed
+from a large set of different types of data sinks and sources
+(see <a href="socat.html#ADDRESS_TYPES">address types</a>), and because lots of
+<a href="socat.html#ADDRESS_OPTIONS">address options</a> may be applied to the streams, socat can
+be used for many different purposes.
+It might be one of the tools that one `has already needed'.
+<p><strong>Filan</strong> is a utility that prints information about its active file
+descriptors to stdout. It has been written for debugging <strong>socat</strong>, but might be
+useful for other purposes too. Use the -h option to find more infos.
+<p><strong>Procan</strong> is a utility that prints information about process parameters to
+stdout. It has been written to better understand
+some UNIX process properties and for debugging <strong>socat</strong>, but might be
+useful for other purposes too.
+<p>The life cycle of a <strong>socat</strong> instance typically consists of four phases.
+<p>In the <em>init</em> phase, the command line options are parsed and logging is
+initialized.
+<p>During the <em>open</em> phase, <strong>socat</strong> opens the first address and afterwards the
+second address. These steps are usually blocking; thus, especially for complex address types like socks,
+connection requests or authentication dialogs must be completed before the next
+step is started.
+<p>In the <em>transfer</em> phase, <strong>socat</strong> watches both streams' read and write file
+descriptors via <code>select()</code>, and, when data is available on one side <em>and</em>
+can be written to the other side, socat reads it, performs newline
+character conversions if required, and writes the data to the write file
+descriptor of the other stream, then continues waiting for more data in both
+directions.
+<p>When one of the streams effectively reaches EOF, the <em>closing</em> phase
+begins. <strong>Socat</strong> transfers the EOF condition to the other stream,
+i.e. tries to shutdown only its write stream, giving it a chance to
+terminate gracefully. For a defined time <strong>socat</strong> continues to transfer data in
+the other direction, but then closes all remaining channels and terminates.
+<p><a name="OPTIONS"></a>
+<h2>OPTIONS</h2>
+
+<p><strong>Socat</strong> provides some command line options that modify the behaviour of the
+program. They have nothing to do with so called
+<a href="socat.html#ADDRESS_OPTIONS">address options</a> that are used as parts of <a href="socat.html#ADDRESS_SPECIFICATIONS">address specifications</a>.
+<p><dl>
+<p></p><dt><strong><strong><code>-V</code></strong></strong><dd>
+ Print version and available feature information to stdout, and exit.
+<p></p><dt><strong><strong><code>-h | -?</code></strong></strong><dd>
+ Print a help text to stdout describing command line options and available address
+ types, and exit.
+<p></p><dt><strong><strong><code>-hh | -??</code></strong></strong><dd>
+ Like -h, plus a list of the short names of all available address options. Some options are
+ platform dependend, so this output is helpful for checking the particular
+ implementation.
+<p></p><dt><strong><strong><code>-hhh | -???</code></strong></strong><dd>
+ Like -hh, plus a list of all available address option names.
+<a name="option_d"></a><p></p><dt><strong><strong><code>-d</code></strong></strong><dd>
+ Without this option, only fatal and error messages are generated; applying
+ this option also prints warning messages. See <a href="socat.html#DIAGNOSTICS">DIAGNOSTICS</a>
+ for more information.
+<a name="option_d_d"></a><p></p><dt><strong><strong><code>-d -d</code></strong></strong><dd> Prints fatal, error, warning, and notice messages.
+<p></p><dt><strong><strong><code>-d -d -d</code></strong></strong><dd> Prints fatal, error, warning, notice, and info messages.
+<p></p><dt><strong><strong><code>-d -d -d -d</code></strong></strong><dd> Prints fatal, error, warning, notice, info, and debug
+ messages.
+<p></p><dt><strong><strong><code>-D</code></strong></strong><dd>
+ Logs information about file descriptors before starting the transfer phase.
+<p></p><dt><strong><strong><code>-ly[<facility>]</code></strong></strong><dd>
+ Writes messages to syslog instead of stderr; severity as defined with -d
+ option. With optional <a href="socat.html#TYPE_FACILITY"><facility></a>, the syslog type can
+ be selected, default is "daemon".
+<p></p><dt><strong><strong><code>-lf</code></strong><code> <logfile></code></strong><dd>
+ Writes messages to <logfile> [<a href="socat.html#TYPE_FILENAME">filename</a>] instead of
+ stderr.
+<p></p><dt><strong><strong><code>-ls</code></strong></strong><dd>
+ Writes messages to stderr (this is the default).
+<a name="option_lp"></a><p></p><dt><strong><strong><code>-lp</code></strong><code><progname></code></strong><dd>
+ Overrides the program name printed in error messages.
+<p></p><dt><strong><strong><code>-lu</code></strong></strong><dd>
+ Extends the timestamp of error messages to microsecond resolution. Does not
+ work when logging to syslog.
+<a name="option_lm"></a><p></p><dt><strong><strong><code>-lm[<facility>]</code></strong></strong><dd>
+ Mixed log mode. During startup messages are printed to stderr; when <strong>socat</strong>
+ starts the transfer phase loop or daemon mode (i.e. after opening all
+ streams and before starting data transfer, or, with listening sockets with
+ fork option, before the first accept call), it switches logging to syslog.
+ With optional <a href="socat.html#TYPE_FACILITY"><facility></a>, the syslog type can be
+ selected, default is "daemon".
+<a name="option_lh"></a><p></p><dt><strong><strong><code>-lh</code></strong></strong><dd>
+ Adds hostname to log messages. Uses the value from environment variable
+ HOSTNAME or the value retrieved with <code>uname()</code> if HOSTNAME is not set.
+<p></p><dt><strong><strong><code>-v</code></strong></strong><dd>
+ Writes the transferred data not only to their target streams, but also to
+ stderr. The output format is text with some conversions for readability, and
+ prefixed with "> " or "< " indicating flow directions.
+<p></p><dt><strong><strong><code>-x</code></strong></strong><dd>
+ Writes the transferred data not only to their target streams, but also to
+ stderr. The output format is hexadecimal, prefixed with "> " or "< "
+ indicating flow directions. Can be combined with <code>-v</code>.
+<a name="option_b"></a><p></p><dt><strong><strong><code>-b</code></strong><code><size></code></strong><dd>
+ Sets the data transfer block <size> [<a href="socat.html#TYPE_SIZE_T">size_t</a>].
+ At most <size> bytes are transferred per step. Default is 8192 bytes.
+<a name="option_s"></a><p></p><dt><strong><strong><code>-s</code></strong></strong><dd>
+ By default, <strong>socat</strong> terminates when an error occurred to prevent the process
+ from running when some option could not be applied. With this
+ option, <strong>socat</strong> is sloppy with errors and tries to continue. Even with this
+ option, socat will exit on fatals, and will abort connection attempts when
+ security checks failed.
+<a name="option_t"></a><p></p><dt><strong><strong><code>-t</code></strong><code><timeout></code></strong><dd>
+ When one channel has reached EOF, the write part of the other channel is shut
+ down. Then, <strong>socat</strong> waits <timeout> [<a href="socat.html#TYPE_TIMEVAL">timeval</a>] seconds
+ before terminating. Default is 0.5 seconds. This timeout only applies to
+ addresses where write and read part can be closed independently. When during
+ the timeout intervall the read part gives EOF, socat terminates without
+ awaiting the timeout.
+<a name="option_T"></a><p></p><dt><strong><strong><code>-T</code></strong><code><timeout></code></strong><dd>
+ Total inactivity timeout: when socat is already in the transfer loop and
+ nothing has happened for <timeout> [<a href="socat.html#TYPE_TIMEVAL">timeval</a>] seconds
+ (no data arrived, no interrupt occurred...) then it terminates.
+ Useful with protocols like UDP that cannot transfer EOF.
+<a name="option_u"></a><p></p><dt><strong><strong><code>-u</code></strong></strong><dd>
+ Uses unidirectional mode. The first address is only used for reading, and the
+ second address is only used for writing (<a href="socat.html#EXAMPLE_option_u">example</a>).
+<a name="option_U"></a><p></p><dt><strong><strong><code>-U</code></strong></strong><dd>
+ Uses unidirectional mode in reverse direction. The first address is only
+ used for writing, and the second address is only used for reading.
+<a name="option_g"></a><p></p><dt><strong><strong><code>-g</code></strong></strong><dd>
+ During address option parsing, don't check if the option is considered
+ useful in the given address environment. Use it if you want to force, e.g.,
+ appliance of a socket option to a serial device.
+<a name="option_L"></a><p></p><dt><strong><strong><code>-L</code></strong><code><lockfile></code></strong><dd>
+ If lockfile exists, exits with error. If lockfile does not exist, creates it
+ and continues, unlinks lockfile on exit.
+<a name="option_W"></a><p></p><dt><strong><strong><code>-W</code></strong><code><lockfile></code></strong><dd>
+ If lockfile exists, waits until it disappears. When lockfile does not exist,
+ creates it and continues, unlinks lockfile on exit.
+<a name="option_4"></a><p></p><dt><strong><strong><code>-4</code></strong></strong><dd>
+ Use IP version 4 in case that the addresses do not implicitly or explicitly
+ specify a version; this is the default.
+<a name="option_6"></a><p></p><dt><strong><strong><code>-6</code></strong></strong><dd>
+ Use IP version 6 in case that the addresses do not implicitly or explicitly
+ specify a version.
+</dl>
+<p><a name="ADDRESS_SPECIFICATIONS"></a>
+<h2>ADDRESS SPECIFICATIONS</h2>
+
+<p>With the address command line arguments, the user gives <strong>socat</strong> instructions and
+the necessary information for establishing the byte streams.
+<p>An address specification usually consists of an address type
+keyword, zero or more required address parameters separated by ':' from the keyword and
+from each
+other, and zero or more address options separated by ','.
+<p>The keyword specifies the address type (e.g., TCP4, OPEN, EXEC). For some
+keywords there exist synonyms ('-' for STDIO, TCP for TCP4). Keywords are case
+insensitive.
+For a few special address types, the keyword may be omitted:
+Address specifications starting with a number are assumed to be FD (raw file
+descriptor) addresses;
+if a '/' is found before the first ':' or ',', GOPEN (generic file open) is
+assumed.
+<p>The required number and type of address parameters depend on the address
+type. E.g., TCP4 requires a server specification (name or address), and a port
+specification (number or service name).
+<p>Zero or more address options may be given with each address. They influence the
+address in some ways.
+Options consist of an option keyword or an option keyword and a value,
+separated by '='. Option keywords are case insensitive.
+For filtering the options that are useful with an address
+type, each option is member of one option group. For
+each address type there is a set of option groups allowed. Only options
+belonging to one of these address groups may be used (except with <a href="socat.html#option_g">option -g</a>).
+<p><a name="ADDRESS_DUAL"></a>
+Address specifications following the above schema are also called <em>single</em>
+address specifications.
+Two single addresses can be combined with "!!" to form a <em>dual</em> type
+address for one channel. Here, the first address is used by <strong>socat</strong> for reading
+data, and the
+second address for writing data. There is no way to specify an option only once
+for being applied to both single addresses.
+<p>Usually, addresses are opened in read/write
+mode. When an address is part of a dual address specification, or when
+<a href="socat.html#option_u">option -u</a> or <a href="socat.html#option_U">-U</a> is used, an address might be
+used only for reading or for writing. Considering this is important with some
+address types.
+<p>With socat version 1.5.0 and higher, the lexical analysis tries to handle
+quotes and parenthesis meaningfully and allows escaping of special characters.
+If one of the characters ( { [ ' is found, the corresponding closing
+character - ) } ] ' - is looked for; they may also be nested. Within these
+constructs, socats special characters and strings : , !! are not handled
+specially. All those characters and strings can be escaped with \ or within ""
+<p><a name="ADDRESS_TYPES"></a>
+<h2>ADDRESS TYPES</h2>
+
+<p>This section describes the available address types with their keywords,
+parameters, and semantics.
+<p><dl>
+<a name="ADDRESS_CREAT"></a><p></p><dt><strong><strong><code>CREATE:<filename></code></strong></strong><dd>
+ Opens <a href="socat.html#TYPE_FILENAME"><filename></a> with <code>creat()</code> and uses the file
+ descriptor for writing.
+ This address type requires write-only context, because a file opened with
+ <code>creat</code> cannot be read from.
+ <filename> must be a valid existing or not existing path.
+ If <filename> is a named pipe, <code>creat()</code> might block;
+ if <filename> refers to a socket, this is an error.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_REG">REG</a>,<a href="socat.html#GROUP_NAMED">NAMED</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_MODE">mode</a>,
+ <a href="socat.html#OPTION_USER">user</a>,
+ <a href="socat.html#OPTION_GROUP">group</a>,
+ <a href="socat.html#OPTION_UNLINK_EARLY">unlink-early</a>,
+ <a href="socat.html#OPTION_UNLINK_LATE">unlink-late</a>,
+ <a href="socat.html#OPTION_APPEND">append</a><br>
+ See also: <a href="socat.html#ADDRESS_OPEN">OPEN</a>, <a href="socat.html#ADDRESS_GOPEN">GOPEN</a>
+<a name="ADDRESS_EXEC"></a><p></p><dt><strong><strong><code>EXEC:<command-line></code></strong></strong><dd>
+ Forks a sub process that establishes communication with its parent process
+ and invokes the specified program with <code>execvp()</code>.
+ <a href="socat.html#TYPE_COMMAND_LINE"><command-line></a> is a simple command
+ with arguments separated by single spaces. If the program name
+ contains a '/', the part after the last '/' is taken as ARGV[0]. If the
+ program name is a relative
+ path, the <code>execvp()</code> semantics for finding the program via
+ <code>$PATH</code>
+ apply. After successful program start, <strong>socat</strong> writes data to stdin of the
+ process and reads from its stdout using a UNIX domain socket generated by
+ <code>socketpair()</code> per default. (<a href="socat.html#EXAMPLE_ADDRESS_EXEC">example</a>) <br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_EXEC">EXEC</a>,<a href="socat.html#GROUP_FORK">FORK</a>,<a href="socat.html#GROUP_TERMIOS">TERMIOS</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_PATH">path</a>,
+ <a href="socat.html#OPTION_FDIN">fdin</a>,
+ <a href="socat.html#OPTION_FDOUT">fdout</a>,
+ <a href="socat.html#OPTION_CHROOT">chroot</a>,
+ <a href="socat.html#OPTION_SUBSTUSER">su</a>,
+ <a href="socat.html#OPTION_SUBSTUSER_DELAYED">su-d</a>,
+ <a href="socat.html#OPTION_NOFORK">nofork</a>,
+ <a href="socat.html#OPTION_PTY">pty</a>,
+ <a href="socat.html#OPTION_STDERR">stderr</a>,
+ <a href="socat.html#OPTION_CTTY">ctty</a>,
+ <a href="socat.html#OPTION_SETSID">setsid</a>,
+ <a href="socat.html#OPTION_PIPES">pipes</a>,
+ <a href="socat.html#OPTION_LOGIN">login</a>,
+ <a href="socat.html#OPTION_SIGINT">sigint</a>,
+ <a href="socat.html#OPTION_SIGQUIT">sigquit</a><br>
+ See also: <a href="socat.html#ADDRESS_SYSTEM">SYSTEM</a>
+<a name="ADDRESS_FD"></a><p></p><dt><strong><strong><code>FD:<fdnum></code></strong></strong><dd>
+ Uses the file descriptor <a href="socat.html#TYPE_FDNUM"><fdnum></a>. It must already exist as
+ valid UN*X file descriptor.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a> (<a href="socat.html#GROUP_TERMIOS">TERMIOS</a>,<a href="socat.html#GROUP_REG">REG</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>) <br>
+ See also:
+ <a href="socat.html#ADDRESS_STDIO">STDIO</a>,
+ <a href="socat.html#ADDRESS_STDIN">STDIN</a>,
+ <a href="socat.html#ADDRESS_STDOUT">STDOUT</a>,
+ <a href="socat.html#ADDRESS_STDERR">STDERR</a>
+<a name="ADDRESS_GOPEN"></a><p></p><dt><strong><strong><code>GOPEN:<filename></code></strong></strong><dd>
+ (Generic open) This address type tries to handle any file system entry
+ except directories usefully. <a href="socat.html#TYPE_FILENAME"><filename></a> may be a
+ relative or absolute path. If it already exists, its type is checked.
+ In case of a UNIX domain socket, <strong>socat</strong> connects; if connecting fails,
+ <strong>socat</strong> assumes a datagram socket and uses <code>sendto()</code> calls.
+ If the entry is not a socket, <strong>socat</strong> opens it applying the <code>O_APPEND</code>
+ flag.
+ If it does not exist, it is opened with flag
+ <code>O_CREAT</code> as a regular file (<a href="socat.html#EXAMPLE_ADDRESS_GOPEN">example</a>).<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_REG">REG</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_NAMED">NAMED</a>,<a href="socat.html#GROUP_OPEN">OPEN</a> <br>
+ See also:
+ <a href="socat.html#ADDRESS_OPEN">OPEN</a>,
+ <a href="socat.html#ADDRESS_CREAT">CREATE</a>,
+ <a href="socat.html#ADDRESS_UNIX_CONNECT">UNIX-CONNECT</a>
+<p><a name="ADDRESS_IP_SENDTO"></a><p></p><dt><strong><strong><code>IP-SENDTO:<host>:<protocol></code></strong></strong><dd>
+ Opens a raw IP socket. Depending on host specification or option <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>, IP procotol version
+ 4 or 6 is used. It uses <a href="socat.html#TYPE_PROTOCOL"><protocol></a> to send packets
+ to <host> [<a href="socat.html#TYPE_IP_ADDRESS">IP address</a>] and receives packets from
+ host, ignores packets from other hosts.
+ Protocol 255 uses the raw socket with the IP header being part of the
+ data.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>,
+ <a href="socat.html#OPTION_TTL">ttl</a>
+ See also:
+ <a href="socat.html#ADDRESS_IP4_SENDTO">IP4-SENDTO</a>,
+ <a href="socat.html#ADDRESS_IP6_SENDTO">IP6-SENDTO</a>,
+ <a href="socat.html#ADDRESS_IP_RECVFROM">IP-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_IP_RECV">IP-RECV</a>,
+ <a href="socat.html#ADDRESS_UDP_SENDTO">UDP-SENDTO</a>
+ <a href="socat.html#ADDRESS_UNIX_SENDTO">UNIX-SENDTO</a>
+<a name="ADDRESS_IP4_SENDTO"></a><p></p><dt><strong><strong><code>IP4-SENDTO:<host>:<protocol></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_IP_SENDTO">IP-SENDTO</a>, but always uses IPv4.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a> <br>
+<a name="ADDRESS_IP6_SENDTO"></a><p></p><dt><strong><strong><code>IP6-SENDTO:<host>:<protocol></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_IP_SENDTO">IP-SENDTO</a>, but always uses IPv6.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP6">IP6</a> <br>
+<p><a name="ADDRESS_IP_DATAGRAM"></a><p></p><dt><strong><strong><code>IP-DATAGRAM:<address>:<protocol></code></strong></strong><dd>
+ Sends outgoing data to the specified address which may in particular be a
+ broadcast or multicast address. Packets arriving on the local socket are
+ checked if their source addresses match
+ eventual <a href="socat.html#OPTION_RANGE">RANGE</a> or <a href="socat.html#OPTION_TCPWRAPPERS">TCPWRAP</a>
+ options. This address type can for example be used for implementing
+ symmetric or asymmetric broadcast or multicast communications.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>, <a href="socat.html#GROUP_SOCKET">SOCKET</a>,
+ <a href="socat.html#GROUP_IP4">IP4</a>, <a href="socat.html#GROUP_IP6">IP6</a>, <a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_RANGE">range</a>,
+ <a href="socat.html#OPTION_TCPWRAPPERS">tcpwrap</a>,
+ <a href="socat.html#OPTION_SO_BROADCAST">broadcast</a>,
+ <a href="socat.html#OPTION_IP_MULTICAST_LOOP">ip-multicast-loop</a>,
+ <a href="socat.html#OPTION_IP_MULTICAST_TTL">ip-multicast-ttl</a>,
+ <a href="socat.html#OPTION_IP_MULTICAST_IF">ip-multicast-if</a>,
+ <a href="socat.html#OPTION_IP_ADD_MEMBERSHIP">ip-add-membership</a>,
+ <a href="socat.html#OPTION_TTL">ttl</a>,
+ <a href="socat.html#OPTION_TOS">tos</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_IP4_DATAGRAM">IP4-DATAGRAM</a>,
+ <a href="socat.html#ADDRESS_IP6_DATAGRAM">IP6-DATAGRAM</a>,
+ <a href="socat.html#ADDRESS_IP_SENDTO">IP-SENDTO</a>,
+ <a href="socat.html#ADDRESS_IP_RECVFROM">IP-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_IP_RECV">IP-RECV</a>,
+ <a href="socat.html#ADDRESS_UDP_DATAGRAM">UDP-DATAGRAM</a>
+<a name="ADDRESS_IP4_DATAGRAM"></a><p></p><dt><strong><strong><code>IP4-DATAGRAM:<host>:<protocol></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_IP_DATAGRAM">IP-DATAGRAM</a>, but always uses IPv4.
+ (<a href="socat.html#EXAMPLE_ADDRESS_IP4_BROADCAST_CLIENT">example</a>)<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>, <a href="socat.html#GROUP_SOCKET">SOCKET</a>,
+ <a href="socat.html#GROUP_IP4">IP4</a>, <a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+<a name="ADDRESS_IP6_DATAGRAM"></a><p></p><dt><strong><strong><code>IP6-DATAGRAM:<host>:<protocol></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_IP_DATAGRAM">IP-DATAGRAM</a>, but always uses IPv6. Please
+ note that IPv6 does not know broadcasts.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>, <a href="socat.html#GROUP_SOCKET">SOCKET</a>,
+ <a href="socat.html#GROUP_IP6">IP6</a>, <a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+<p><a name="ADDRESS_IP_RECVFROM"></a><p></p><dt><strong><strong><code>IP-RECVFROM:<protocol></code></strong></strong><dd>
+ Opens a raw IP socket of <a href="socat.html#TYPE_PROTOCOL"><protocol></a>. Depending on option <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>, IP procotol version
+ 4 or 6 is used. It receives one packet from an unspecified peer and may send one or more answer packets to that peer.
+ This mode is particularly useful with fork option where each arriving packet - from arbitrary peers - is handled by its own sub process.
+ This allows a behaviour similar to typical UDP based servers like ntpd or named.
+ This address works well with IP-SENDTO address peers (see above).
+ Protocol 255 uses the raw socket with the IP header being part of the
+ data.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>,
+ <a href="socat.html#OPTION_FORK">fork</a>,
+ <a href="socat.html#OPTION_RANGE">range</a>,
+ <a href="socat.html#OPTION_TTL">ttl</a>,
+ <a href="socat.html#OPTION_SO_BROADCAST">broadcast</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_IP4_RECVFROM">IP4-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_IP6_RECVFROM">IP6-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_IP_SENDTO">IP-SENDTO</a>,
+ <a href="socat.html#ADDRESS_IP_RECV">IP-RECV</a>,
+ <a href="socat.html#ADDRESS_UDP_RECVFROM">UDP-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_UNIX_RECVFROM">UNIX-RECVFROM</a>
+<a name="ADDRESS_IP4_RECVFROM"></a><p></p><dt><strong><strong><code>IP4-RECVFROM:<protocol></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_IP_RECVFROM">IP-RECVFROM</a>, but always uses IPv4.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+<a name="ADDRESS_IP6_RECVFROM"></a><p></p><dt><strong><strong><code>IP6-RECVFROM:<protocol></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_IP_RECVFROM">IP-RECVFROM</a>, but always uses IPv6.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+<p><a name="ADDRESS_IP_RECV"></a><p></p><dt><strong><strong><code>IP-RECV:<protocol></code></strong></strong><dd>
+ Opens a raw IP socket of <a href="socat.html#TYPE_PROTOCOL"><protocol></a>. Depending on option <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>, IP procotol version
+ 4 or 6 is used. It receives packets from multiple unspecified peers and merges the data.
+ No replies are possible.
+ It can be, e.g., addressed by socat IP-SENDTO address peers.
+ Protocol 255 uses the raw socket with the IP header being part of the
+ data.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>,
+ <a href="socat.html#OPTION_RANGE">range</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_IP4_RECV">IP4-RECV</a>,
+ <a href="socat.html#ADDRESS_IP6_RECV">IP6-RECV</a>,
+ <a href="socat.html#ADDRESS_IP_SENDTO">IP-SENDTO</a>,
+ <a href="socat.html#ADDRESS_IP_RECVFROM">IP-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_UDP_RECV">UDP-RECV</a>,
+ <a href="socat.html#ADDRESS_UNIX_RECV">UNIX-RECV</a>
+<a name="ADDRESS_IP4_RECV"></a><p></p><dt><strong><strong><code>IP4-RECV:<protocol></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_IP_RECV">IP-RECV</a>, but always uses IPv4.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+<a name="ADDRESS_IP6_RECV"></a><p></p><dt><strong><strong><code>IP6-RECV:<protocol></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_IP_RECV">IP-RECV</a>, but always uses IPv6.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+<p><a name="ADDRESS_OPEN"></a><p></p><dt><strong><strong><code>OPEN:<filename></code></strong></strong><dd>
+ Opens <a href="socat.html#TYPE_FILENAME"><filename></a> using the <code>open()</code> system call
+ (<a href="socat.html#EXAMPLE_ADDRESS_OPEN">example</a>).
+ This operation fails on UNIX domain sockets. <br>
+ Note: This address type is rarly useful in bidirectional mode.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_REG">REG</a>,<a href="socat.html#GROUP_NAMED">NAMED</a>,<a href="socat.html#GROUP_OPEN">OPEN</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_CREAT">creat</a>,
+ <a href="socat.html#OPTION_EXCL">excl</a>,
+ <a href="socat.html#OPTION_O_NOATIME">noatime</a>,
+ <a href="socat.html#OPTION_NOFOLLOW">nofollow</a>,
+ <a href="socat.html#OPTION_APPEND">append</a>,
+ <a href="socat.html#OPTION_RDONLY">rdonly</a>,
+ <a href="socat.html#OPTION_WRONLY">wronly</a>,
+ <a href="socat.html#OPTION_LOCK">lock</a>,
+ <a href="socat.html#OPTION_READBYTES">readbytes</a>,
+ <a href="socat.html#OPTION_IGNOREEOF">ignoreeof</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_CREAT">CREATE</a>,
+ <a href="socat.html#ADDRESS_GOPEN">GOPEN</a>,
+ <a href="socat.html#ADDRESS_UNIX_CONNECT">UNIX-CONNECT</a>
+<a name="ADDRESS_OPENSSL_CONNECT"></a><p></p><dt><strong><strong><code>OPENSSL:<host>:<port></code></strong></strong><dd>
+ Tries to establish a SSL connection to <port> [<a href="socat.html#TYPE_TCP_SERVICE">TCP
+ service</a>] on
+ <host> [<a href="socat.html#TYPE_IP_ADDRESS">IP address</a>] using TCP/IP version 4 or 6
+ depending on address specification, name resolution, or option
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>.<br>
+ NOTE: The server certificate is only checked for validity against
+ <a href="socat.html#OPTION_OPENSSL_CAFILE">cafile</a> or <a href="socat.html#OPTION_OPENSSL_CAPATH">capath</a>,
+ but not for match with the server's name or its IP address!<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_TCP">TCP</a>,<a href="socat.html#GROUP_OPENSSL">OPENSSL</a>,<a href="socat.html#GROUP_RETRY">RETRY</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_OPENSSL_CIPHERLIST">cipher</a>,
+ <a href="socat.html#OPTION_OPENSSL_METHOD">method</a>,
+ <a href="socat.html#OPTION_OPENSSL_VERIFY">verify</a>,
+ <a href="socat.html#OPTION_OPENSSL_CAFILE">cafile</a>,
+ <a href="socat.html#OPTION_OPENSSL_CAPATH">capath</a>,
+ <a href="socat.html#OPTION_OPENSSL_CERTIFICATE">certificate</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>,
+ <a href="socat.html#OPTION_CONNECT_TIMEOUT">connect-timeout</a>,
+ <a href="socat.html#OPTION_SOURCEPORT">sourceport</a>,
+ <a href="socat.html#OPTION_RETRY">retry</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_OPENSSL_LISTEN">OPENSSL-LISTEN</a>,
+ <a href="socat.html#ADDRESS_TCP_CONNECT">TCP</a>
+<a name="ADDRESS_OPENSSL_LISTEN"></a><p></p><dt><strong><strong><code>OPENSSL-LISTEN:<port></code></strong></strong><dd>
+ Listens on tcp <port> [<a href="socat.html#TYPE_TCP_SERVICE">TCP service</a>].
+ The IP version is 4 or the one specified with
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>. When a
+ connection is accepted, this address behaves as SSL server.<br>
+ Note: You probably want to use the <a href="socat.html#OPTION_OPENSSL_CERTIFICATE">certificate</a> option with this address.<br>
+ NOTE: The client certificate is only checked for validity against
+ <a href="socat.html#OPTION_OPENSSL_CAFILE">cafile</a> or <a href="socat.html#OPTION_OPENSSL_CAPATH">capath</a>,
+ but not for match with the client's name or its IP address!<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_TCP">TCP</a>,<a href="socat.html#GROUP_LISTEN">LISTEN</a>,<a href="socat.html#GROUP_OPENSSL">OPENSSL</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>,<a href="socat.html#GROUP_RETRY">RETRY</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>,
+ <a href="socat.html#OPTION_OPENSSL_CIPHERLIST">cipher</a>,
+ <a href="socat.html#OPTION_OPENSSL_METHOD">method</a>,
+ <a href="socat.html#OPTION_OPENSSL_VERIFY">verify</a>,
+ <a href="socat.html#OPTION_OPENSSL_CAFILE">cafile</a>,
+ <a href="socat.html#OPTION_OPENSSL_CAPATH">capath</a>,
+ <a href="socat.html#OPTION_OPENSSL_CERTIFICATE">certificate</a>,
+ <a href="socat.html#OPTION_FORK">fork</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_RANGE">range</a>,
+ <a href="socat.html#OPTION_TCPWRAPPERS">tcpwrap</a>,
+ <a href="socat.html#OPTION_SUBSTUSER">su</a>,
+ <a href="socat.html#OPTION_REUSEADDR">reuseaddr</a>,
+ <a href="socat.html#OPTION_RETRY">retry</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_OPENSSL_CONNECT">OPENSSL</a>,
+ <a href="socat.html#ADDRESS_TCP_CONNECT">TCP</a>
+<a name="ADDRESS_NAMED_PIPE"></a><p></p><dt><strong><strong><code>PIPE:<filename></code></strong></strong><dd>
+ If <a href="socat.html#TYPE_FILENAME"><filename></a> already exists, it is opened.
+ If is does not exist, a named pipe is created and opened. Beginning with
+ socat version 1.4.3, the named pipe is removed when the address is closed
+ (but see option <a href="socat.html#OPTION_UNLINK_CLOSE">unlink-close</a><br>
+ Note: When a pipe is used for both reading and writing, it works
+ as echo service.<br>
+ Note: When a pipe is used for both reading and writing, and socat tries
+ to write more bytes than the pipe can buffer (Linux 2.4: 2048 bytes), socat
+ might block. Consider using socat option, e.g., <code>-b 2048</code> <br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_NAMED">NAMED</a>,<a href="socat.html#GROUP_OPEN">OPEN</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_RDONLY">rdonly</a>,
+ <a href="socat.html#OPTION_NONBLOCK">nonblock</a>,
+ <a href="socat.html#OPTION_GROUP">group</a>,
+ <a href="socat.html#OPTION_USER">user</a>,
+ <a href="socat.html#OPTION_MODE">mode</a>,
+ <a href="socat.html#OPTION_UNLINK_EARLY">unlink-early</a><br>
+ See also: <a href="socat.html#ADDRESS_UNNAMED_PIPE">unnamed pipe</a>
+<a name="ADDRESS_UNNAMED_PIPE"></a><p></p><dt><strong><strong><code>PIPE</code></strong></strong><dd>
+ Creates an unnamed pipe and uses it for reading and writing. It works as an
+ echo, because everything written
+ to it appeares immediately as read data.<br>
+ Note: When socat tries to write more bytes than the pipe can queue (Linux
+ 2.4: 2048 bytes), socat might block. Consider, e.g., using
+ option <code>-b 2048</code> <br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a> <br>
+ See also: <a href="socat.html#ADDRESS_NAMED_PIPE">named pipe</a>
+<a name="ADDRESS_PROXY_CONNECT"></a><p></p><dt><strong><strong><code>PROXY:<proxy>:<hostname>:<port></code></strong></strong><dd>
+ Connects to an HTTP proxy server on port 8080 using TCP/IP version 4 or 6
+ depending on address specification, name resolution, or option
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>, and sends a CONNECT
+ request for hostname:port. If the proxy grants access and succeeds to
+ connect to the target, data transfer between socat and the target can
+ start. Note that the traffic need not be HTTP but can be an arbitrary
+ protocol. <br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_TCP">TCP</a>,<a href="socat.html#GROUP_HTTP">HTTP</a>,<a href="socat.html#GROUP_RETRY">RETRY</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_PROXYPORT">proxyport</a>,
+ <a href="socat.html#OPTION_IGNORECR">ignorecr</a>,
+ <a href="socat.html#OPTION_PROXY_AUTHORIZATION">proxyauth</a>,
+ <a href="socat.html#OPTION_PROXY_RESOLVE">resolve</a>,
+ <a href="socat.html#OPTION_CRNL">crnl</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_CONNECT_TIMEOUT">connect-timeout</a>,
+ <a href="socat.html#OPTION_MSS">mss</a>,
+ <a href="socat.html#OPTION_SOURCEPORT">sourceport</a>,
+ <a href="socat.html#OPTION_RETRY">retry</a> <br>
+ See also: <a href="socat.html#ADDRESS_SOCKS4">SOCKS</a>, <a href="socat.html#ADDRESS_TCP_CONNECT">TCP</a>
+<a name="ADDRESS_PTY"></a><p></p><dt><strong><strong><code>PTY</code></strong></strong><dd>
+ Generates a pseudo terminal (pty) and uses its master side. Another process
+ may open the pty's slave side using it like a serial line or terminal.
+ (<a href="socat.html#EXAMPLE_ADDRESS_PTY">example</a>). If
+ both the ptmx and the openpty mechanisms are available, ptmx is used
+ (POSIX).<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_NAMED">NAMED</a>,<a href="socat.html#GROUP_PTY">PTY</a>,<a href="socat.html#GROUP_TERMIOS">TERMIOS</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_SYMBOLIC_LINK">link</a>,
+ <a href="socat.html#OPTION_OPENPTY">openpty</a>,
+ <a href="socat.html#OPTION_PTY_WAIT_SLAVE">wait-slave</a>,
+ <a href="socat.html#OPTION_MODE">mode</a>,
+ <a href="socat.html#OPTION_USER">user</a>,
+ <a href="socat.html#OPTION_GROUP">group</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_UNIX_LISTEN">UNIX-LISTEN</a>,
+ <a href="socat.html#ADDRESS_NAMED_PIPE">PIPE</a>,
+ <a href="socat.html#ADDRESS_EXEC">EXEC</a>, <a href="socat.html#ADDRESS_SYSTEM">SYSTEM</a>
+<a name="ADDRESS_READLINE"></a><p></p><dt><strong><strong><code>READLINE</code></strong></strong><dd>
+ Uses GNU readline and history on stdio to allow editing and reusing input
+ lines (<a href="socat.html#EXAMPLE_ADDRESS_READLINE">example</a>). This requires the GNU readline and
+ history libraries. Note that stdio should be a (pseudo) terminal device,
+ otherwise readline does not seem to work.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_READLINE">READLINE</a>,<a href="socat.html#GROUP_TERMIOS">TERMIOS</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_HISTORY">history</a>,
+ <a href="socat.html#OPTION_NOECHO">noecho</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_STDIO">STDIO</a>
+<a name="ADDRESS_SOCKS4"></a><p></p><dt><strong><strong><code>SOCKS4:<socks-server>:<host>:<port></code></strong></strong><dd>
+ Connects via <socks-server> [<a href="socat.html#TYPE_IP_ADDRESS">IP address</a>]
+ to <host> [<a href="socat.html#TYPE_IPV4_ADDRESS">IPv4 address</a>]
+ on <port> [<a href="socat.html#TYPE_TCP_SERVICE">TCP service</a>],
+ using socks version 4 protocol over IP version 4 or 6 depending on address specification, name resolution, or option
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a> (<a href="socat.html#EXAMPLE_ADDRESS_SOCKS4">example</a>).<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_TCP">TCP</a>,<a href="socat.html#GROUP_SOCKS">SOCKS4</a>,<a href="socat.html#GROUP_RETRY">RETRY</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_SOCKSUSER">socksuser</a>,
+ <a href="socat.html#OPTION_SOCKSPORT">socksport</a>,
+ <a href="socat.html#OPTION_SOURCEPORT">sourceport</a>,
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>,
+ <a href="socat.html#OPTION_RETRY">retry</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_SOCKS4A">SOCKS4A</a>,
+ <a href="socat.html#ADDRESS_PROXY_CONNECT">PROXY</a>,
+ <a href="socat.html#ADDRESS_TCP_CONNECT">TCP</a>
+<a name="ADDRESS_SOCKS4A"></a><p></p><dt><strong><strong><code>SOCKS4A:<socks-server>:<host>:<port></code></strong></strong><dd>
+ like <a href="socat.html#ADDRESS_SOCKS4">SOCKS4</a>, but uses socks protocol version 4a, thus
+ leaving host name resolution to the socks server.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_TCP">TCP</a>,<a href="socat.html#GROUP_SOCKS">SOCKS4</a>,<a href="socat.html#GROUP_RETRY">RETRY</a> <br>
+<a name="ADDRESS_STDERR"></a><p></p><dt><strong><strong><code>STDERR</code></strong></strong><dd>
+ Uses file descriptor 2.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a> (<a href="socat.html#GROUP_TERMIOS">TERMIOS</a>,<a href="socat.html#GROUP_REG">REG</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>) <br>
+ See also: <a href="socat.html#ADDRESS_FD">FD</a>
+<a name="ADDRESS_STDIN"></a><p></p><dt><strong><strong><code>STDIN</code></strong></strong><dd>
+ Uses file descriptor 0.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a> (<a href="socat.html#GROUP_TERMIOS">TERMIOS</a>,<a href="socat.html#GROUP_REG">REG</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>) <br>
+ Useful options:
+ <a href="socat.html#OPTION_READBYTES">readbytes</a><br>
+ See also: <a href="socat.html#ADDRESS_FD">FD</a>
+<a name="ADDRESS_STDIO"></a><p></p><dt><strong><strong><code>STDIO</code></strong></strong><dd>
+ Uses file descriptor 0 for reading, and 1 for writing.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a> (<a href="socat.html#GROUP_TERMIOS">TERMIOS</a>,<a href="socat.html#GROUP_REG">REG</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>) <br>
+ Useful options:
+ <a href="socat.html#OPTION_READBYTES">readbytes</a><br>
+ See also: <a href="socat.html#ADDRESS_FD">FD</a>
+<a name="ADDRESS_STDOUT"></a><p></p><dt><strong><strong><code>STDOUT</code></strong></strong><dd>
+ Uses file descriptor 1.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a> (<a href="socat.html#GROUP_TERMIOS">TERMIOS</a>,<a href="socat.html#GROUP_REG">REG</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>) <br>
+ See also: <a href="socat.html#ADDRESS_FD">FD</a>
+<a name="ADDRESS_SYSTEM"></a><p></p><dt><strong><strong><code>SYSTEM:<shell-command></code></strong></strong><dd>
+ Forks a sub process that establishes communication with its parent process
+ and invokes the specified program with <code>system()</code>. Please note that
+ <shell-command> [<a href="socat.html#TYPE_STRING">string</a>] must
+ not contain ',' or "!!", and that shell meta characters may have to be
+ protected.
+ After successful program start, <strong>socat</strong> writes data to stdin of the
+ process and reads from its stdout.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_EXEC">EXEC</a>,<a href="socat.html#GROUP_FORK">FORK</a>,<a href="socat.html#GROUP_TERMIOS">TERMIOS</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_PATH">path</a>,
+ <a href="socat.html#OPTION_FDIN">fdin</a>,
+ <a href="socat.html#OPTION_FDOUT">fdout</a>,
+ <a href="socat.html#OPTION_CHROOT">chroot</a>,
+ <a href="socat.html#OPTION_SUBSTUSER">su</a>,
+ <a href="socat.html#OPTION_SUBSTUSER_DELAYED">su-d</a>,
+ <a href="socat.html#OPTION_NOFORK">nofork</a>,
+ <a href="socat.html#OPTION_PTY">pty</a>,
+ <a href="socat.html#OPTION_STDERR">stderr</a>,
+ <a href="socat.html#OPTION_CTTY">ctty</a>,
+ <a href="socat.html#OPTION_SETSID">setsid</a>,
+ <a href="socat.html#OPTION_PIPES">pipes</a>,
+ <a href="socat.html#OPTION_SIGINT">sigint</a>,
+ <a href="socat.html#OPTION_SIGQUIT">sigquit</a><br>
+ See also: <a href="socat.html#ADDRESS_EXEC">EXEC</a>
+<a name="ADDRESS_TCP_CONNECT"></a><p></p><dt><strong><strong><code>TCP:<host>:<port></code></strong></strong><dd>
+ Connects to <port> [<a href="socat.html#TYPE_TCP_SERVICE">TCP service</a>] on
+ <host> [<a href="socat.html#TYPE_IP_ADDRESS">IP address</a>] using TCP/IP version 4 or 6
+ depending on address specification, name resolution, or option
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_TCP">TCP</a>,<a href="socat.html#GROUP_RETRY">RETRY</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_CRNL">crnl</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>,
+ <a href="socat.html#OPTION_CONNECT_TIMEOUT">connect-timeout</a>,
+ <a href="socat.html#OPTION_TOS">tos</a>,
+ <a href="socat.html#OPTION_MTUDISCOVER">mtudiscover</a>,
+ <a href="socat.html#OPTION_MSS">mss</a>,
+ <a href="socat.html#OPTION_NODELAY">nodelay</a>,
+ <a href="socat.html#OPTION_NONBLOCK">nonblock</a>,
+ <a href="socat.html#OPTION_SOURCEPORT">sourceport</a>,
+ <a href="socat.html#OPTION_RETRY">retry</a>,
+ <a href="socat.html#OPTION_READBYTES">readbytes</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_TCP4_CONNECT">TCP4</a>,
+ <a href="socat.html#ADDRESS_TCP6_CONNECT">TCP6</a>,
+ <a href="socat.html#ADDRESS_TCP_LISTEN">TCP-LISTEN</a>,
+ <a href="socat.html#ADDRESS_UDP_CONNECT">UDP</a>,
+ <a href="socat.html#ADDRESS_UNIX_CONNECT">UNIX-CONNECT</a>
+<a name="ADDRESS_TCP4_CONNECT"></a><p></p><dt><strong><strong><code>TCP4:<host>:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_TCP_CONNECT">TCP</a>, but only supports IPv4 protocol (<a href="socat.html#EXAMPLE_ADDRESS_TCP4_CONNECT">example</a>).<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_TCP">TCP</a>,<a href="socat.html#GROUP_RETRY">RETRY</a> <br>
+<a name="ADDRESS_TCP6_CONNECT"></a><p></p><dt><strong><strong><code>TCP6:<host>:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_TCP_CONNECT">TCP</a>, but only supports IPv6 protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_TCP">TCP</a>,<a href="socat.html#GROUP_RETRY">RETRY</a> <br>
+<a name="ADDRESS_TCP_LISTEN"></a><p></p><dt><strong><strong><code>TCP-LISTEN:<port></code></strong></strong><dd>
+ Listens on <port> [<a href="socat.html#TYPE_TCP_SERVICE">TCP service</a>] and accepts a
+ TCP/IP connection. The IP version is 4 or the one specified with
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>.
+ Note that opening
+ this address usually blocks until a client connects.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_LISTEN">LISTEN</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_TCP">TCP</a>,<a href="socat.html#GROUP_RETRY">RETRY</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_CRNL">crnl</a>,
+ <a href="socat.html#OPTION_FORK">fork</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_RANGE">range</a>,
+ <a href="socat.html#OPTION_TCPWRAPPERS">tcpwrap</a>,
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>,
+ <a href="socat.html#OPTION_BACKLOG">backlog</a>,
+ <a href="socat.html#OPTION_MSS">mss</a>,
+ <a href="socat.html#OPTION_SUBSTUSER">su</a>,
+ <a href="socat.html#OPTION_REUSEADDR">reuseaddr</a>,
+ <a href="socat.html#OPTION_RETRY">retry</a>,
+ <a href="socat.html#OPTION_COOL_WRITE">retry</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_TCP4_CONNECT">TCP4-LISTEN</a>,
+ <a href="socat.html#ADDRESS_TCP6_LISTEN">TCP6-LISTEN</a>,
+ <a href="socat.html#ADDRESS_UDP_LISTEN">UDP-LISTEN</a>,
+ <a href="socat.html#ADDRESS_UNIX_LISTEN">UNIX-LISTEN</a>,
+ <a href="socat.html#ADDRESS_OPENSSL_LISTEN">OPENSSL-LISTEN</a>
+<a name="ADDRESS_TCP4_LISTEN"></a><p></p><dt><strong><strong><code>TCP4-LISTEN:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_TCP_LISTEN">TCP-LISTEN</a>, but only supports IPv4
+ protocol (<a href="socat.html#EXAMPLE_ADDRESS_TCP4_LISTEN">example</a>).<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_LISTEN">LISTEN</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_TCP">TCP</a>,<a href="socat.html#GROUP_RETRY">RETRY</a> <br>
+<a name="ADDRESS_TCP6_LISTEN"></a><p></p><dt><strong><strong><code>TCP6-LISTEN:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_TCP_LISTEN">TCP-LISTEN</a>, but only supports IPv6
+ protocol.<br>
+ Additional useful option:
+ <a href="socat.html#OPTION_IPV6_V6ONLY">ipv6only</a><br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_LISTEN">LISTEN</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_TCP">TCP</a>,<a href="socat.html#GROUP_RETRY">RETRY</a> <br>
+<a name="ADDRESS_TUN"></a><p></p><dt><strong><strong><code>TUN:<if-addr>/<bits></code></strong></strong><dd>
+ Creates a Linux TUN/TAP device and assignes to it the address and netmask
+ defined by the parameters. The resulting network interface is ready for use
+ by other processes; socat serves its "wire side". This address requires read
+ and write access to the tunnel cloning device, usually <code>/dev/net/tun</code>.
+ <br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_NAMED">NAMED</a>,<a href="socat.html#GROUP_OPEN">OPEN</a>,<a href="socat.html#GROUP_TUN">TUN</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_IFF_UP">iff-up</a>,
+ <a href="socat.html#OPTION_TUN_DEVICE">tun-device</a>,
+ <a href="socat.html#OPTION_TUN_NAME">tun-name</a>,
+ <a href="socat.html#OPTION_TUN_TYPE">tun-type</a>,
+ <a href="socat.html#OPTION_IFF_NO_PI">iff-no-pi</a> <br>
+ See also:
+ <a href="socat.html#ADDRESS_IP_RECV">ip-recv</a>
+<a name="ADDRESS_UDP_CONNECT"></a><p></p><dt><strong><strong><code>UDP:<host>:<port></code></strong></strong><dd>
+ Connects to <port> [<a href="socat.html#TYPE_UDP_SERVICE">UDP service</a>] on
+ <host> [<a href="socat.html#TYPE_IP_ADDRESS">IP address</a>] using UDP/IP version 4 or 6
+ depending on address specification, name resolution, or option
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>.<br>
+ Please note that,
+ due to UDP protocol properties, no real connection is established; data has
+ to be sent for `connecting' to the server, and no end-of-file condition can
+ be transported.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_TTL">ttl</a>,
+ <a href="socat.html#OPTION_TOS">tos</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_SOURCEPORT">sourceport</a>,
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_UDP4_CONNECT">UDP4</a>,
+ <a href="socat.html#ADDRESS_UDP6_CONNECT">UDP6</a>,
+ <a href="socat.html#ADDRESS_UDP_LISTEN">UDP-LISTEN</a>,
+ <a href="socat.html#ADDRESS_TCP_CONNECT">TCP</a>,
+ <a href="socat.html#ADDRESS_IP_SENDTO">IP</a>
+<a name="ADDRESS_UDP4_CONNECT"></a><p></p><dt><strong><strong><code>UDP4:<host>:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_CONNECT">UDP</a>, but only supports IPv4 protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a> <br>
+<a name="ADDRESS_UDP6_CONNECT"></a><p></p><dt><strong><strong><code>UDP6:<host>:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_CONNECT">UDP</a>, but only supports IPv6 protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP6">IP6</a> <br>
+<a name="ADDRESS_UDP_DATAGRAM"></a><p></p><dt><strong><strong><code>UDP-DATAGRAM:<address>:<port></code></strong></strong><dd>
+ Sends outgoing data to the specified address which may in particular be a
+ broadcast or multicast address. Packets arriving on the local socket are
+ checked for the correct remote port and if their source addresses match
+ eventual <a href="socat.html#OPTION_RANGE">RANGE</a> or <a href="socat.html#OPTION_TCPWRAPPERS">TCPWRAP</a>
+ options. This address type can for example be used for implementing
+ symmetric or asymmetric broadcast or multicast communications.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_RANGE">range</a>,
+ <a href="socat.html#OPTION_TCPWRAPPERS">tcpwrap</a>,
+ <a href="socat.html#OPTION_SO_BROADCAST">broadcast</a>,
+ <a href="socat.html#OPTION_IP_MULTICAST_LOOP">ip-multicast-loop</a>,
+ <a href="socat.html#OPTION_IP_MULTICAST_TTL">ip-multicast-ttl</a>,
+ <a href="socat.html#OPTION_IP_MULTICAST_IF">ip-multicast-if</a>,
+ <a href="socat.html#OPTION_IP_ADD_MEMBERSHIP">ip-add-membership</a>,
+ <a href="socat.html#OPTION_TTL">ttl</a>,
+ <a href="socat.html#OPTION_TOS">tos</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_SOURCEPORT">sourceport</a>,
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_UDP4_DATAGRAM">UDP4-DATAGRAM</a>,
+ <a href="socat.html#ADDRESS_UDP6_DATAGRAM">UDP6-DATAGRAM</a>,
+ <a href="socat.html#ADDRESS_UDP_SENDTO">UDP-SENDTO</a>,
+ <a href="socat.html#ADDRESS_UDP_RECVFROM">UDP-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_UDP_RECV">UDP-RECV</a>,
+ <a href="socat.html#ADDRESS_UDP_CONNECT">UDP-CONNECT</a>,
+ <a href="socat.html#ADDRESS_UDP_LISTEN">UDP-LISTEN</a>,
+ <a href="socat.html#ADDRESS_IP_DATAGRAM">IP-DATAGRAM</a>
+<a name="ADDRESS_UDP4_DATAGRAM"></a><p></p><dt><strong><strong><code>UDP4-DATAGRAM:<address>:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_DATAGRAM">UDP-DATAGRAM</a>, but only supports IPv4
+ protocol (<a href="socat.html#EXAMPLE_ADDRESS_UDP4_BROADCAST_CLIENT">example1</a>,
+ <a href="socat.html#EXAMPLE_ADDRESS_UDP4_MULTICAST">example2</a>).<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>, <a href="socat.html#GROUP_SOCKET">SOCKET</a>,
+ <a href="socat.html#GROUP_IP4">IP4</a>, <a href="socat.html#GROUP_RANGE">RANGE</a>
+<a name="ADDRESS_UDP6_DATAGRAM"></a><p></p><dt><strong><strong><code>UDP6-DATAGRAM:<address>:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_DATAGRAM">UDP-DATAGRAM</a>, but only supports IPv6
+ protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,
+ <a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>
+<a name="ADDRESS_UDP_LISTEN"></a><p></p><dt><strong><strong><code>UDP-LISTEN:<port></code></strong></strong><dd>
+ Waits for a UDP/IP packet arriving on <port>
+ [<a href="socat.html#TYPE_UDP_SERVICE">UDP service</a>] and `connects' back to sender.
+ The accepted IP version is 4 or the one specified with option
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>.
+ Please note that,
+ due to UDP protocol properties, no real connection is established; data has
+ to arrive from the peer first, and no end-of-file condition can be
+ transported. Note that opening
+ this address usually blocks until a client connects.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_LISTEN">LISTEN</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_FORK">fork</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_RANGE">range</a>,
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a> <br>
+ See also:
+ <a href="socat.html#ADDRESS_UDP_CONNECT">UDP</a>,
+ <a href="socat.html#ADDRESS_UDP4_LISTEN">UDP4-LISTEN</a>,
+ <a href="socat.html#ADDRESS_UDP6_LISTEN">UDP6-LISTEN</a>,
+ <a href="socat.html#ADDRESS_TCP_LISTEN">TCP-LISTEN</a>
+<a name="ADDRESS_UDP4_LISTEN"></a><p></p><dt><strong><strong><code>UDP4-LISTEN:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_LISTEN">UDP-LISTEN</a>, but only support IPv4
+ protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_LISTEN">LISTEN</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>,<a href="socat.html#GROUP_IP4">IP4</a> <br>
+<a name="ADDRESS_UDP6_LISTEN"></a><p></p><dt><strong><strong><code>UDP6-LISTEN:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_LISTEN">UDP-LISTEN</a>, but only support IPv6
+ protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_LISTEN">LISTEN</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>,<a href="socat.html#GROUP_IP6">IP6</a> <br>
+<a name="ADDRESS_UDP_SENDTO"></a><p></p><dt><strong><strong><code>UDP-SENDTO:<host>:<port></code></strong></strong><dd>
+ Communicates with the specified peer socket, defined by <port> [<a href="socat.html#TYPE_UDP_SERVICE">UDP
+ service</a>] on
+ <host> [<a href="socat.html#TYPE_IP_ADDRESS">IP address</a>], using UDP/IP version 4 or 6
+ depending on address specification, name resolution, or option
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>. It sends packets to and receives packets
+ from that peer socket only.
+ This address effectively implements a datagram client.
+ It works well with socat UDP-RECVFROM and UDP-RECV address peers.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_TTL">ttl</a>,
+ <a href="socat.html#OPTION_TOS">tos</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_SOURCEPORT">sourceport</a>,
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_UDP4_SENDTO">UDP4-SENDTO</a>,
+ <a href="socat.html#ADDRESS_UDP6_SENDTO">UDP6-SENDTO</a>,
+ <a href="socat.html#ADDRESS_UDP_RECVFROM">UDP-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_UDP_RECV">UDP-RECV</a>,
+ <a href="socat.html#ADDRESS_UDP_CONNECT">UDP-CONNECT</a>,
+ <a href="socat.html#ADDRESS_UDP_LISTEN">UDP-LISTEN</a>,
+ <a href="socat.html#ADDRESS_IP_SENDTO">IP-SENDTO</a>
+<a name="ADDRESS_UDP4_SENDTO"></a><p></p><dt><strong><strong><code>UDP4-SENDTO:<host>:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_SENDTO">UDP-SENDTO</a>, but only supports IPv4
+ protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>
+<a name="ADDRESS_UDP6_SENDTO"></a><p></p><dt><strong><strong><code>UDP6-SENDTO:<host>:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_SENDTO">UDP-SENDTO</a>, but only supports IPv6
+ protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP6">IP6</a>
+<p><a name="ADDRESS_UDP_RECVFROM"></a><p></p><dt><strong><strong><code>UDP-RECVFROM:<port></code></strong></strong><dd>
+ Creates a UDP socket on <port> [<a href="socat.html#TYPE_UDP_SERVICE">UDP service</a>] using
+ UDP/IP version 4 or 6
+ depending on option <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>.
+ It receives one packet from an unspecified peer and may send one or more
+ answer packets to that peer. This mode is particularly useful with fork
+ option
+ where each arriving packet - from arbitrary peers - is handled by its own sub
+ process. This allows a behaviour similar to typical UDP based servers like ntpd
+ or named. This address works well with socat SENDTO address peers.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_FORK">fork</a>,
+ <a href="socat.html#OPTION_TTL">ttl</a>,
+ <a href="socat.html#OPTION_TOS">tos</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_SOURCEPORT">sourceport</a>,
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_UDP4_RECVFROM">UDP4-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_UDP6_RECVFROM">UDP6-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_UDP_SENDTO">UDP-SENDTO</a>,
+ <a href="socat.html#ADDRESS_UDP_RECV">UDP-RECV</a>,
+ <a href="socat.html#ADDRESS_UDP_CONNECT">UDP-CONNECT</a>,
+ <a href="socat.html#ADDRESS_UDP_LISTEN">UDP-LISTEN</a>,
+ <a href="socat.html#ADDRESS_IP_RECVFROM">IP-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_UNIX_RECVFROM">UNIX-RECVFROM</a>
+<a name="ADDRESS_UDP4_RECVFROM"></a><p></p><dt><strong><strong><code>UDP4-RECVFROM:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_RECVFROM">UDP-RECVFROM</a>, but only supports IPv4 protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>
+<a name="ADDRESS_UDP6_RECVFROM"></a><p></p><dt><strong><strong><code>UDP6-RECVFROM:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_RECVFROM">UDP-RECVFROM</a>, but only supports IPv6 protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>
+<p><a name="ADDRESS_UDP_RECV"></a><p></p><dt><strong><strong><code>UDP-RECV:<port></code></strong></strong><dd>
+ Creates a UDP socket on <port> [<a href="socat.html#TYPE_UDP_SERVICE">UDP service</a>] using UDP/IP version 4 or 6
+ depending on option <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>.
+ It receives packets from multiple unspecified peers and merges the data.
+ No replies are possible. It works well with, e.g., socat UDP-SENDTO address peers; it behaves similar to a syslog server.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_RANGE">RANGE</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_FORK">fork</a>,
+ <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>,
+ <a href="socat.html#OPTION_BIND">bind</a>,
+ <a href="socat.html#OPTION_SOURCEPORT">sourceport</a>,
+ <a href="socat.html#OPTION_TTL">ttl</a>,
+ <a href="socat.html#OPTION_TOS">tos</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_UDP4_RECV">UDP4-RECV</a>,
+ <a href="socat.html#ADDRESS_UDP6_RECV">UDP6-RECV</a>,
+ <a href="socat.html#ADDRESS_UDP_SENDTO">UDP-SENDTO</a>,
+ <a href="socat.html#ADDRESS_UDP_RECVFROM">UDP-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_UDP_CONNECT">UDP-CONNECT</a>,
+ <a href="socat.html#ADDRESS_UDP_LISTEN">UDP-LISTEN</a>,
+ <a href="socat.html#ADDRESS_IP_RECV">IP-RECV</a>,
+ <a href="socat.html#ADDRESS_UNIX_RECV">UNIX-RECV</a>
+<a name="ADDRESS_UDP4_RECV"></a><p></p><dt><strong><strong><code>UDP4-RECV:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_RECV">UDP-RECV</a>, but only supports IPv4 protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP4">IP4</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>
+<a name="ADDRESS_UDP6_RECV"></a><p></p><dt><strong><strong><code>UDP6-RECV:<port></code></strong></strong><dd>
+ Like <a href="socat.html#ADDRESS_UDP_RECV">UDP-RECV</a>, but only supports IPv6 protocol.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,<a href="socat.html#GROUP_IP6">IP6</a>,<a href="socat.html#GROUP_RANGE">RANGE</a>
+<p><a name="ADDRESS_UNIX_CONNECT"></a><p></p><dt><strong><strong><code>UNIX-CONNECT:<filename></code></strong></strong><dd>
+ Connects to <a href="socat.html#TYPE_FILENAME"><filename></a> assuming it is a UNIX domain
+ socket.
+ If <filename> does not exist, this is an error;
+ if <filename> is not a UNIX domain socket, this is an error;
+ if <filename> is a UNIX domain socket, but no process is listening, this is
+ an error.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,
+ <a href="socat.html#GROUP_NAMED">NAMED</a>,<a href="socat.html#GROUP_RETRY">RETRY</a>,
+ <a href="socat.html#GROUP_SOCK_UNIX">UNIX</a> <br>)
+ Useful options:
+ <a href="socat.html#OPTION_BIND">bind</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_UNIX_LISTEN">UNIX-LISTEN</a>,
+ <a href="socat.html#ADDRESS_UNIX_SENDTO">UNIX-SENDTO</a>,
+ <a href="socat.html#ADDRESS_TCP_CONNECT">TCP</a>
+<p><a name="ADDRESS_UNIX_LISTEN"></a><p></p><dt><strong><strong><code>UNIX-LISTEN:<filename></code></strong></strong><dd>
+ Listens on <a href="socat.html#TYPE_FILENAME"><filename></a> using a UNIX domain stream
+ socket and accepts a connection.
+ If <filename> exists and is not a socket, this is an error.
+ If <filename> exists and is a UNIX domain socket, binding to the address
+ fails (use option <a href="socat.html#OPTION_UNLINK_EARLY">unlink-early</a>!).
+ Note that opening this address usually blocks until a client connects.
+ Beginning with socat version 1.4.3, the file system entry is removed when
+ this address is closed (but see option <a href="socat.html#OPTION_UNLINK_CLOSE">unlink-close</a>) (<a href="socat.html#EXAMPLE_ADDRESS_UNIX_LISTEN">example</a>).<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,
+ <a href="socat.html#GROUP_NAMED">NAMED</a>,<a href="socat.html#GROUP_LISTEN">LISTEN</a>,
+ <a href="socat.html#GROUP_CHILD">CHILD</a>,<a href="socat.html#GROUP_RETRY">RETRY</a>,
+ <a href="socat.html#GROUP_SOCK_UNIX">UNIX</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_FORK">fork</a>,
+ <a href="socat.html#OPTION_UMASK">umask</a>,
+ <a href="socat.html#OPTION_MODE">mode</a>,
+ <a href="socat.html#OPTION_USER">user</a>,
+ <a href="socat.html#OPTION_GROUP">group</a>,
+ <a href="socat.html#OPTION_UNLINK_EARLY">unlink-early</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_UNIX_CONNECT">UNIX-CONNECT</a>,
+ <a href="socat.html#ADDRESS_UNIX_RECVFROM">UNIX-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_UNIX_RECV">UNIX-RECV</a>,
+ <a href="socat.html#ADDRESS_TCP4_LISTEN">TCP-LISTEN</a>
+<p><a name="ADDRESS_UNIX_SENDTO"></a><p></p><dt><strong><strong><code>UNIX-SENDTO:<filename></code></strong></strong><dd>
+ Communicates with the specified peer socket, defined by [<a href="socat.html#TYPE_FILENAME"><filename></a>] assuming it is a UNIX domain datagram socket.
+ It sends packets to and receives packets from that peer socket only.
+ It works well with socat UNIX-RECVFROM and UNIX-RECV address peers.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,
+ <a href="socat.html#GROUP_NAMED">NAMED</a>,<a href="socat.html#GROUP_SOCK_UNIX">UNIX</a><br>
+ Useful options:
+ <a href="socat.html#OPTION_BIND">bind</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_UNIX_RECVFROM">UNIX-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_UNIX_RECV">UNIX-RECV</a>,
+ <a href="socat.html#ADDRESS_UNIX_CONNECT">UNIX-CONNECT</a>,
+ <a href="socat.html#ADDRESS_UDP_SENDTO">UDP-SENDTO</a>,
+ <a href="socat.html#ADDRESS_IP_SENDTO">IP-SENDTO</a>
+<p><a name="ADDRESS_UNIX_RECVFROM"></a><p></p><dt><strong><strong><code>UNIX-RECVFROM:<filename></code></strong></strong><dd>
+ Creates a UNIX domain datagram socket [<a href="socat.html#TYPE_FILENAME"><filename></a>].
+ Receives one packet and may send one or more answer packets to that peer.
+ This mode is particularly useful with fork option where each arriving packet - from arbitrary peers - is handled by its own sub process.
+ This address works well with socat UNIX-SENDTO address peers.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,
+ <a href="socat.html#GROUP_NAMED">NAMED</a>,<a href="socat.html#GROUP_CHILD">CHILD</a>,
+ <a href="socat.html#GROUP_SOCK_UNIX">UNIX</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_FORK">fork</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_UNIX_SENDTO">UNIX-SENDTO</a>,
+ <a href="socat.html#ADDRESS_UNIX_RECV">UNIX-RECV</a>,
+ <a href="socat.html#ADDRESS_UNIX_LISTEN">UNIX-LISTEN</a>,
+ <a href="socat.html#ADDRESS_UDP_RECVFROM">UDP-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_IP_RECVFROM">IP-RECVFROM</a>
+<p><a name="ADDRESS_UNIX_RECV"></a><p></p><dt><strong><strong><code>UNIX-RECV:<filename></code></strong></strong><dd>
+ Creates a UNIX domain datagram socket [<a href="socat.html#TYPE_FILENAME"><filename></a>].
+ Receives packets from multiple unspecified peers and merges the data.
+ No replies are possible. It can be, e.g., addressed by socat UNIX-SENDTO address peers.
+ It behaves similar to a syslog server.
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,
+ <a href="socat.html#GROUP_NAMED">NAMED</a>,<a href="socat.html#GROUP_SOCK_UNIX">UNIX</a> <br>
+ See also:
+ <a href="socat.html#ADDRESS_UNIX_SENDTO">UNIX-SENDTO</a>,
+ <a href="socat.html#ADDRESS_UNIX_RECVFROM">UNIX-RECVFROM</a>,
+ <a href="socat.html#ADDRESS_UNIX_LISTEN">UNIX-LISTEN</a>,
+ <a href="socat.html#ADDRESS_UDP_RECV">UDP-RECV</a>,
+ <a href="socat.html#ADDRESS_IP_RECV">IP-RECV</a>
+<p><a name="ADDRESS_UNIX_CLIENT"></a><p></p><dt><strong><strong><code>UNIX-CLIENT:<filename></code></strong></strong><dd>
+ Communicates with the specified peer socket, defined by
+ [<a href="socat.html#TYPE_FILENAME"><filename></a>] assuming it is a UNIX domain socket.
+ It first tries to connect and, if that fails, assumes it is a datagram
+ socket, thus supporting both types.<br>
+ Option groups: <a href="socat.html#GROUP_FD">FD</a>,<a href="socat.html#GROUP_SOCKET">SOCKET</a>,
+ <a href="socat.html#GROUP_NAMED">NAMED</a>,<a href="socat.html#GROUP_SOCK_UNIX">UNIX</a> <br>
+ Useful options:
+ <a href="socat.html#OPTION_BIND">bind</a><br>
+ See also:
+ <a href="socat.html#ADDRESS_UNIX_CONNECT">UNIX-CONNECT</a>,
+ <a href="socat.html#ADDRESS_UNIX_SENDTO">UNIX-SENDTO</a>,
+ <a href="socat.html#ADDRESS_GOPEN">GOPEN</a>
+<p><p></p><dt><strong><strong><code>ABSTRACT-CONNECT:<string></code></strong></strong><dd>
+<p></p><dt><strong><strong><code>ABSTRACT-LISTEN:<string></code></strong></strong><dd>
+<p></p><dt><strong><strong><code>ABSTRACT-SENDTO:<string></code></strong></strong><dd>
+<p></p><dt><strong><strong><code>ABSTRACT-RECVFROM:<string></code></strong></strong><dd>
+<p></p><dt><strong><strong><code>ABSTRACT-RECV:<string></code></strong></strong><dd>
+<p></p><dt><strong><strong><code>ABSTRACT-CLIENT:<string></code></strong></strong><dd>
+ The ABSTRACT addresses are almost identical to the related UNIX addresses
+ except that they do not address file system based sockets but an alternate
+ UNIX domain address space. To archieve this the socket address strings are
+ prefixed with "\0" internally. This feature is available (only?) on Linux.
+ Option groups are the same as with the related UNIX addresses, except that
+ the ABSTRACT addresses are not member of the NAMED group.
+</dl>
+<p><a name="ADDRESS_OPTIONS"></a>
+<h2>ADDRESS OPTIONS</h2>
+
+<p>Address options can be applied to address specifications to influence the
+process of opening the addresses and the
+properties of the resulting data channels.
+<p>For technical reasons not every option can be
+applied to every address type; e.g., applying a socket option to a regular file
+will fail. To catch most useless combinations as early as in the open phase,
+the concept of <em>option groups</em> was introduced. Each option belongs to one
+or more option groups. Options can be used only with address types that support
+at least one of their option groups (but see <a href="socat.html#option_g">option -g</a>).
+<p>Address options have data types that their values must conform to.
+Every address option consists of just a keyword or a keyword followed by
+"=value", where value must conform to the options type.
+
+Some address options manipulate parameters of system calls;
+e.g., option sync sets the <code>O_SYNC</code> flag with the <code>open()</code> call.
+Other options cause a system or library call; e.g., with option `ttl=value'
+the <code>setsockopt(fd, SOL_IP, IP_TTL, value, sizeof(int))</code> call is applied.
+Other
+options set internal <strong>socat</strong> variables that are used during data transfer;
+e.g., `crnl' causes explicit character conversions.
+A few options have more complex implementations; e.g., su-d
+(substuser-delayed) inquires some user and group infos, stores them, and
+applies them later after a possible <code>chroot()</code> call.
+<p>If multiple options are given to an address, their sequence in the address specification has (almost) no
+effect on the sequence of their execution/application. Instead, <strong>socat</strong> has
+built in an <em>option phase</em> model that tries to bring the options in a useful
+order. Some options exist in different forms (e.g.,
+unlink, unlink-early, unlink-late) to control the time of their execution.
+<p>If the same option is specified more than once within one address
+specification, with equal or different values, the effect depends on the kind of option. Options
+resulting in function calls like <code>setsockopt()</code> cause multiple
+invocations. With options that set parameters for a required call like
+<code>open()</code>
+or set internal flags, the value of the last option occurrence is effective.
+<p>The existence or semantics of many options are system dependent. <strong>Socat</strong>
+usually does NOT try to emulate missing libc or kernel features, it just
+provides an
+interface to the underlying system. So, if an operating system lacks a feature,
+the related option is simply not available on this platform.
+<p>The following paragraphs introduce just the more common address options. For
+a more comprehensive reference and to find information about canonical option
+names, alias names, option phases, and platforms see file <strong>xio.help</strong>.
+<br> <br>
+<p><dl></dl><br>
+<p><a name="GROUP_FD"></a><em><strong>FD option group</strong></em>
+<p>This option group contains options that are applied to a UN*X
+style file descriptor, no matter how it was generated.
+Because all current <strong>socat</strong> address types are file descriptor based, these
+options may be applied to any address. <br>
+Note: Some of these options are also member of another option group, that
+provides an other, non-fd based mechanism.
+For these options, it depends on the actual address type and its option groups
+which mechanism is used. The second, non-fd based mechanism is prioritized.
+<dl>
+<a name="OPTION_CLOEXEC"></a><p></p><dt><strong><strong><code>cloexec=<bool></code></strong></strong><dd>
+ Sets the <code>FD_CLOEXEC</code> flag with the <code>fcntl()</code> system call to value
+ <a href="socat.html#TYPE_BOOL"><bool></a>. If set,
+ the file descriptor is closed on <code>exec()</code> family function calls. <strong>Socat</strong>
+ internally handles
+ this flag for the fds it controls, so in most cases there will be no need to
+ apply this option.
+<a name="OPTION_SETLK_WR"></a><p></p><dt><strong><strong><code>setlk</code></strong></strong><dd>
+ Tries to set a discretionary write lock to the whole file using the <code>fcntl(fd,
+ F_SETLK, ...)</code> system call. If the file is already locked, this call results
+ in an error.
+ On Linux, when the file permissions for group are "S" (g-x,g+s), and the
+ file system is locally mounted with the "mand" option, the lock is
+ mandatory, i.e. prevents other processes from opening the file.
+<a name="OPTION_SETLKW_WR"></a><p></p><dt><strong><strong><code>setlkw</code></strong></strong><dd>
+ Tries to set a discretionary waiting write lock to the whole file using the
+ <code>fcntl(fd, F_SETLKW, ...)</code> system call. If the file is already locked,
+ this call blocks.
+ See option <a href="socat.html#OPTION_SETLK_WR">setlk</a> for information about making this
+ lock mandatory.
+<a name="OPTION_SETLK_RD"></a><p></p><dt><strong><strong><code>setlk-rd</code></strong></strong><dd>
+ Tries to set a discretionary read lock to the whole file using the <code>fcntl(fd,
+ F_SETLK, ...)</code> system call. If the file is already write locked, this call
+ results in an error.
+ See option <a href="socat.html#OPTION_SETLK_WR">setlk</a> for information about making this
+ lock mandatory.
+<a name="OPTION_SETLKW_RD"></a><p></p><dt><strong><strong><code>setlkw-rd</code></strong></strong><dd>
+ Tries to set a discretionary waiting read lock to the whole file using the
+ <code>fcntl(fd, F_SETLKW, ...)</code> system call. If the file is already write
+ locked, this call blocks.
+ See option <a href="socat.html#OPTION_SETLK_WR">setlk</a> for information about making this
+ lock mandatory.
+<a name="OPTION_FLOCK_EX"></a><p></p><dt><strong><strong><code>flock-ex</code></strong></strong><dd>
+ Tries to set a blocking exclusive advisory lock to the file using the
+ <code>flock(fd, LOCK_EX)</code> system call. <strong>Socat</strong> hangs in this call if the file
+ is locked by another process.
+<a name="OPTION_FLOCK_EX_NB"></a><p></p><dt><strong><strong><code>flock-ex-nb</code></strong></strong><dd>
+ Tries to set a nonblocking exclusive advisory lock to the file using the
+ <code>flock(fd, LOCK_EX|LOCK_NB)</code> system call. If the file is already locked,
+ this option results in an error.
+<a name="OPTION_FLOCK_SH"></a><p></p><dt><strong><strong><code>flock-sh</code></strong></strong><dd>
+ Tries to set a blocking shared advisory lock to the file using the
+ <code>flock(fd, LOCK_SH)</code> system call. <strong>Socat</strong> hangs in this call if the file
+ is locked by another process.
+<a name="OPTION_FLOCK_SH_NB"></a><p></p><dt><strong><strong><code>flock-sh-nb</code></strong></strong><dd>
+ Tries to set a nonblocking shared advisory lock to the file using the
+ <code>flock(fd, LOCK_SH|LOCK_NB)</code> system call. If the file is already locked,
+ this option results in an error.
+<a name="OPTION_LOCK"></a><p></p><dt><strong><strong><code>lock</code></strong></strong><dd>
+ Sets a blocking lock on the file. Uses the setlk or flock mechanism
+ depending on availability on the particular platform. If both are available,
+ the POSIX variant (setlkw) is used.
+<a name="OPTION_USER"></a><p></p><dt><strong><strong><code>user=<user></code></strong></strong><dd>
+ Sets the <a href="socat.html#TYPE_USER"><user></a> (owner) of the stream.
+ If the address is member of the NAMED option group,
+ <strong>socat</strong> uses the <code>chown()</code> system call after opening the
+ file or binding to the UNIX domain socket (race condition!).
+ Without filesystem entry, <strong>socat</strong> sets the user of the stream
+ using the <code>fchown()</code> system call.
+ These calls might require root privilege.
+<a name="OPTION_USER_LATE"></a><p></p><dt><strong><strong><code>user-late=<user></code></strong></strong><dd>
+ Sets the owner of the fd to <a href="socat.html#TYPE_USER"><user></a> with the <code>fchown()</code>
+ system call after opening
+ or connecting the channel.
+ This is useful only on file system entries.
+<a name="OPTION_GROUP"></a><p></p><dt><strong><strong><code>group=<group></code></strong></strong><dd>
+ Sets the <a href="socat.html#TYPE_GROUP"><group></a> of the stream.
+ If the address is member of the NAMED option group,
+ <strong>socat</strong> uses the <code>chown()</code> system call after opening the
+ file or binding to the UNIX domain socket (race condition!).
+ Without filesystem entry, <strong>socat</strong> sets the group of the stream
+ with the <code>fchown()</code> system call.
+ These calls might require group membership or root privilege.
+<a name="OPTION_GROUP_LATE"></a><p></p><dt><strong><strong><code>group-late=<group></code></strong></strong><dd>
+ Sets the group of the fd to <a href="socat.html#TYPE_GROUP"><group></a> with the
+ <code>fchown()</code> system call after opening
+ or connecting the channel.
+ This is useful only on file system entries.
+<a name="OPTION_MODE"></a><p></p><dt><strong><strong><code>mode=<mode></code></strong></strong><dd>
+ Sets the <mode> [<a href="socat.html#TYPE_MODE_T">mode_t</a>] (permissions) of the stream.
+ If the address is member of the NAMED option group and
+ uses the <code>open()</code> or <code>creat()</code> call, the mode is applied with these.
+ If the address is member of the NAMED option group without using these
+ system calls, <strong>socat</strong> uses the <code>chmod()</code> system call after opening the
+ filesystem entry or binding to the UNIX domain socket (race condition!).
+ Otherwise, <strong>socat</strong> sets the mode of the stream
+ using <code>fchmod()</code>.
+ These calls might require ownership or root privilege.
+<a name="OPTION_PERM_LATE"></a><p></p><dt><strong><strong><code>perm-late=<mode></code></strong></strong><dd>
+ Sets the permissions of the fd to value <mode>
+ [<a href="socat.html#TYPE_MODE_T">mode_t</a>] using the <code>fchmod()</code> system call after
+ opening or connecting the channel.
+ This is useful only on file system entries.
+<a name="OPTION_APPEND"></a><p></p><dt><strong><strong><code>append=<bool></code></strong></strong><dd>
+ Always writes data to the actual end of file.
+ If the address is member of the OPEN option group,
+ <strong>socat</strong> uses the <code>O_APPEND</code> flag with the <code>open()</code> system call
+ (<a href="socat.html#EXAMPLE_OPTION_APPEND">example</a>).
+ Otherwise, <strong>socat</strong> applies the <code>fcntl(fd, F_SETFL, O_APPEND)</code> call.
+<a name="OPTION_NONBLOCK"></a><p></p><dt><strong><strong><code>nonblock=<bool></code></strong></strong><dd>
+ Tries to open or use file in nonblocking mode. Its only effects are that the
+ <code>connect()</code> call of TCP addresses does not block, and that opening a
+ named pipe for reading does not block.
+ If the address is member of the OPEN option group,
+ <strong>socat</strong> uses the <code>O_NONBLOCK</code> flag with the <code>open()</code> system call.
+ Otherwise, <strong>socat</strong> applies the <code>fcntl(fd, F_SETFL, O_NONBLOCK)</code> call.
+
+
+<a name="OPTION_O_BINARY"></a><p></p><dt><strong><strong><code>binary</code></strong></strong><dd>
+ Opens the file in binary mode to avoid implicit line terminator
+ conversions (Cygwin).
+<a name="OPTION_O_TEXT"></a><p></p><dt><strong><strong><code>text</code></strong></strong><dd>
+ Opens the file in text mode to force implicit line terminator conversions
+ (Cygwin).
+<a name="OPTION_O_NOINHERIT"></a><p></p><dt><strong><strong><code>noinherit</code></strong></strong><dd>
+ Does not keep this file open in a spawned process (Cygwin).
+<a name="OPTION_COOL_WRITE"></a><p></p><dt><strong><strong><code>cool-write</code></strong></strong><dd>
+ Takes it easy when write fails with EPIPE or ECONNRESET and logs the message
+ with <em>notice</em> level instead of <em>error</em>.
+ This prevents the log file from being filled with useless error messages
+ when socat is used as a high volume server or proxy where clients often
+ abort the connection.<br>
+ This option is experimental.
+<a name="OPTION_END_CLOSE"></a><p></p><dt><strong><strong><code>end-close</code></strong></strong><dd>
+ Changes the (address dependent) method of ending a connection to just close
+ the file descriptors. This is useful when the connection is to be reused by
+ or shared with other processes (<a href="socat.html#EXAMPLE_END_CLOSE">example</a>).<br>
+ Normally, socket connections will be ended with <code>shutdown(2)</code> which
+ terminates the socket even if it is shared by multiple processes.
+ <code>close(2)</code> "unlinks" the socket from the process but keeps it active as
+ long as there are still links from other processes.<br>
+ Similarly, when an address of type EXEC or SYSTEM is ended, socat usually
+ will explicitely kill the sub process. With this option, it will just close
+ the file descriptors.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_NAMED"></a><em><strong>NAMED option group</strong></em>
+<p>These options work on file system entries.<br>
+See also options <a href="socat.html#OPTION_USER">user</a>, <a href="socat.html#OPTION_GROUP">group</a>, and
+<a href="socat.html#OPTION_MODE">mode</a>.
+<p><dl>
+<a name="OPTION_USER_EARLY"></a><p></p><dt><strong><strong><code>user-early=<user></code></strong></strong><dd>
+ Changes the <a href="socat.html#TYPE_USER"><user></a> (owner) of the file system entry before
+ accessing it, using the
+ <code>chown()</code> system call. This call might require root privilege.
+<a name="OPTION_GROUP_EARLY"></a><p></p><dt><strong><strong><code>group-early=<group></code></strong></strong><dd>
+ Changes the <a href="socat.html#TYPE_GROUP"><group></a> of the file system entry before
+ accessing it, using the
+ <code>chown()</code> system call. This call might require group membership or root
+ privilege.
+<a name="OPTION_PERM_EARLY"></a><p></p><dt><strong><strong><code>perm-early=<mode></code></strong></strong><dd>
+ Changes the <mode> [<a href="socat.html#TYPE_MODE_T">mode_t</a>] of the file system entry
+ before accessing it, using the
+ <code>chmod()</code> system call. This call might require ownership or root
+ privilege.
+<a name="OPTION_UMASK"></a><p></p><dt><strong><strong><code>umask=<mode></code></strong></strong><dd>
+ Sets the umask of the process to <mode> [<a href="socat.html#TYPE_MODE_T">mode_t</a>] before
+ accessing the file system entry (useful
+ with UNIX domain sockets!). This call might affect all further operations
+ of the <strong>socat</strong> process!
+<a name="OPTION_UNLINK_EARLY"></a><p></p><dt><strong><strong><code>unlink-early</code></strong></strong><dd>
+ Unlinks (removes) the file before opening it and even before applying
+ user-early etc.
+<a name="OPTION_UNLINK"></a><p></p><dt><strong><strong><code>unlink</code></strong></strong><dd>
+ Unlinks (removes) the file before accessing it, but after user-early etc.
+<a name="OPTION_UNLINK_LATE"></a><p></p><dt><strong><strong><code>unlink-late</code></strong></strong><dd>
+ Unlinks (removes) the file after opening it to make it inaccessible for
+ other processes after a short race condition.
+<a name="OPTION_UNLINK_CLOSE"></a><p></p><dt><strong><strong><code>unlink-close</code></strong></strong><dd>
+ Removes the addresses file system entry when closing the address.
+ For <a href="socat.html#ADDRESS_NAMED_PIPE">named pipes</a>,
+ <a href="socat.html#ADDRESS_UNIX_LISTEN">listening unix domain sockets</a>,
+ and the <a href="socat.html#OPTION_SYMBOLIC_LINK">symbolic links</a> of <a href="socat.html#ADDRESS_PTY">pty addresses</a>,
+ the default is 1; for <a href="socat.html#ADDRESS_CREAT">created files</a>,
+ <a href="socat.html#ADDRESS_OPEN">opened files</a>,
+ <a href="socat.html#ADDRESS_GOPEN">generic opened files</a>, and
+ <a href="socat.html#ADDRESS_UNIX_CONNECT">client unix domain sockets</a> the default is 0.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_OPEN"></a><em><strong>OPEN option group</strong></em>
+<p>The OPEN group options allow to set flags with the <code>open()</code> system call.
+E.g., option `creat' sets the <code>O_CREAT</code> flag.<br>
+See also options <a href="socat.html#OPTION_APPEND">append</a> and
+<a href="socat.html#OPTION_NONBLOCK">nonblock</a>.
+<dl>
+<a name="OPTION_CREAT"></a><p></p><dt><strong><strong><code>creat=<bool></code></strong></strong><dd>
+ Creates the file if it does not exist (<a href="socat.html#EXAMPLE_OPTION_CREAT">example</a>).
+<a name="OPTION_DSYNC"></a><p></p><dt><strong><strong><code>dsync=<bool></code></strong></strong><dd>
+ Blocks <code>write()</code> calls until metainfo is physically written to media.
+<a name="OPTION_EXCL"></a><p></p><dt><strong><strong><code>excl=<bool></code></strong></strong><dd>
+ With option creat, if file exists this is an error.
+<a name="OPTION_LARGEFILE"></a><p></p><dt><strong><strong><code>largefile=<bool></code></strong></strong><dd>
+ On 32 bit systems, allows a file larger than 2^31 bytes.
+<a name="OPTION_O_NOATIME"></a><p></p><dt><strong><strong><code>noatime</code></strong></strong><dd>
+ Sets the O_NOATIME options, so reads do not change the access timestamp.
+<a name="OPTION_NOCTTY"></a><p></p><dt><strong><strong><code>noctty=<bool></code></strong></strong><dd>
+ Does not make this file the controlling terminal.
+<a name="OPTION_NOFOLLOW"></a><p></p><dt><strong><strong><code>nofollow=<bool></code></strong></strong><dd>
+ Does not follow symbolic links.
+<a name="OPTION_NSHARE"></a><p></p><dt><strong><strong><code>nshare=<bool></code></strong></strong><dd>
+ Does not allow to share this file with other processes.
+<a name="OPTION_RSHARE"></a><p></p><dt><strong><strong><code>rshare=<bool></code></strong></strong><dd>
+ Does not allow other processes to open this file for writing.
+<a name="OPTION_RSYNC"></a><p></p><dt><strong><strong><code>rsync=<bool></code></strong></strong><dd>
+ Blocks <code>write()</code> until metainfo is physically written to media.
+<a name="OPTION_SYNC"></a><p></p><dt><strong><strong><code>sync=<bool></code></strong></strong><dd>
+ Blocks <code>write()</code> until data is physically written to media.
+
+
+
+
+<a name="OPTION_RDONLY"></a><p></p><dt><strong><strong><code>rdonly=<bool></code></strong></strong><dd>
+ Opens the file for reading only.
+
+<a name="OPTION_WRONLY"></a><p></p><dt><strong><strong><code>wronly=<bool></code></strong></strong><dd>
+ Opens the file for writing only.
+<a name="OPTION_TRUNC"></a><p></p><dt><strong><strong><code>trunc</code></strong></strong><dd>
+ Truncates the file to size 0 during opening it.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_REG"></a><em><strong>REG and BLK option group</strong></em>
+<p>These options are usually applied to a UN*X file descriptor, but their
+semantics make sense only on a file supporting random access.
+<dl>
+<a name="OPTION_SEEK"></a><p></p><dt><strong><strong><code>seek=<offset></code></strong></strong><dd>
+ Applies the <code>lseek(fd, <offset>, SEEK_SET)</code> (or <code>lseek64</code>) system
+ call, thus positioning the file pointer absolutely to <offset>
+ [<a href="socat.html#TYPE_OFF">off_t</a> or <a href="socat.html#TYPE_OFF64">off64_t</a>].
+<a name="OPTION_SEEK_CUR"></a><p></p><dt><strong><strong><code>seek-cur=<offset></code></strong></strong><dd>
+ Applies the <code>lseek(fd, <offset>, SEEK_CUR)</code> (or <code>lseek64</code>) system
+ call, thus positioning the file pointer <offset> [<a href="socat.html#TYPE_OFF">off_t</a> or
+ <a href="socat.html#TYPE_OFF64">off64_t</a>] bytes relatively to its current position (which
+ is usually 0).
+<a name="OPTION_SEEK_END"></a><p></p><dt><strong><strong><code>seek-end=<offset></code></strong></strong><dd>
+ Applies the <code>lseek(fd, <offset>, SEEK_END)</code> (or <code>lseek64</code>) system
+ call, thus positioning the file pointer <offset> [<a href="socat.html#TYPE_OFF">off_t</a> or
+ <a href="socat.html#TYPE_OFF64">off64_t</a>] bytes relatively to the files current end.
+<a name="OPTION_FTRUNCATE"></a><p></p><dt><strong><strong><code>ftruncate=<offset></code></strong></strong><dd>
+ Applies the <code>ftruncate(fd, <offset>)</code>
+ (or <code>ftruncate64</code> if available) system call, thus
+ truncating the file at the position <offset> [<a href="socat.html#TYPE_OFF">off_t</a> or
+ <a href="socat.html#TYPE_OFF64">off64_t</a>].
+<p><a name="OPTION_EXT2_SECRM_FL"></a><p></p><dt><strong><strong><code>secrm=<bool></code></strong></strong><dd>
+<a name="OPTION_EXT2_UNRM"></a><p></p><dt><strong><strong><code>unrm=<bool></code></strong></strong><dd>
+<a name="OPTION_EXT2_COMPR"></a><p></p><dt><strong><strong><code>compr=<bool></code></strong></strong><dd>
+<a name="OPTION_EXT2_SYNC"></a><p></p><dt><strong><strong><code>ext2-sync=<bool></code></strong></strong><dd>
+<a name="OPTION_EXT2_IMMUTABLE"></a><p></p><dt><strong><strong><code>immutable=<bool></code></strong></strong><dd>
+<a name="OPTION_EXT2_APPEND"></a><p></p><dt><strong><strong><code>ext2-append=<bool></code></strong></strong><dd>
+<a name="OPTION_EXT2_NODUMP"></a><p></p><dt><strong><strong><code>nodump=<bool></code></strong></strong><dd>
+<a name="OPTION_EXT2_NOATIME"></a><p></p><dt><strong><strong><code>ext2-noatime=<bool></code></strong></strong><dd>
+<a name="OPTION_EXT2_JOURNAL_DATA"></a><p></p><dt><strong><strong><code>journal-data=<bool></code></strong></strong><dd>
+<a name="OPTION_EXT2_NOTAIL"></a><p></p><dt><strong><strong><code>notail=<bool></code></strong></strong><dd>
+<a name="OPTION_EXT2_DIRSYNC"></a><p></p><dt><strong><strong><code>dirsync=<bool></code></strong></strong><dd>
+ These options change non standard file attributes on operating systems and
+ file systems that support these features, like Linux with ext2fs,
+ ext3fs, or reiserfs. See man 1 chattr for information on these options.
+ Please note that there might be a race condition between creating the file
+ and applying these options.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_PROCESS"></a><em><strong>PROCESS option group</strong></em>
+<p>Options of this group change the process properties instead of just affecting
+one data channel.
+For EXEC and SYSTEM addresses and for LISTEN and CONNECT type addresses with
+option FORK,
+these options apply to the child processes instead of the main socat process.
+<dl>
+<a name="OPTION_CHROOT"></a><p></p><dt><strong><strong><code>chroot=<directory></code></strong></strong><dd>
+ Performs a <code>chroot()</code> operation to <a href="socat.html#TYPE_DIRECTORY"><directory></a>
+ after processing the address (<a href="socat.html#EXAMPLE_OPTION_CHROOT">example</a>). This call might require root privilege.
+<a name="OPTION_CHROOT_EARLY"></a><p></p><dt><strong><strong><code>chroot-early=<directory></code></strong></strong><dd>
+ Performs a <code>chroot()</code> operation to <a href="socat.html#TYPE_DIRECTORY"><directory></a>
+ before opening the address. This call might require root privilege.
+<a name="OPTION_SETGID"></a><p></p><dt><strong><strong><code>setgid=<group></code></strong></strong><dd>
+ Changes the primary <a href="socat.html#TYPE_GROUP"><group></a> of the process after
+ processing the address. This call might require root privilege.
+<a name="OPTION_SETGID_EARLY"></a><p></p><dt><strong><strong><code>setgid-early=<group></code></strong></strong><dd>
+ Changes the primary <a href="socat.html#TYPE_GROUP"><group></a> of the process before opening
+ the address. This call might require root privilege.
+<a name="OPTION_SETUID"></a><p></p><dt><strong><strong><code>setuid=<user></code></strong></strong><dd>
+ Changes the <a href="socat.html#TYPE_USER"><user></a> (owner) of the process after processing
+ the address. This call might require root privilege.
+<a name="OPTION_SETUID_EARLY"></a><p></p><dt><strong><strong><code>setuid-early=<user></code></strong></strong><dd>
+ Changes the <a href="socat.html#TYPE_USER"><user></a> (owner) of the process before opening
+ the address. This call might require root privilege.
+<a name="OPTION_SUBSTUSER"></a><p></p><dt><strong><strong><code>su=<user></code></strong></strong><dd>
+ Changes the <a href="socat.html#TYPE_USER"><user></a> (owner) and groups of the process after
+ processing the address (<a href="socat.html#EXAMPLE_OPTION_SUBSTUSER">example</a>). This call might require root privilege.
+<a name="OPTION_SUBSTUSER_DELAYED"></a><p></p><dt><strong><strong><code>su-d=<user></code></strong></strong><dd>
+ Short name for <strong><code>substuser-delayed</code></strong>.
+ Changes the <a href="socat.html#TYPE_USER"><user></a>
+ (owner) and groups of the process after processing the address (<a href="socat.html#EXAMPLE_OPTION_SUBSTUSER_DELAYED">example</a>).
+ The user and his groups are retrieved <em>before</em> a possible
+ <code>chroot()</code>. This call might require root privilege.
+<a name="OPTION_SETPGID"></a><p></p><dt><strong><strong><code>setpgid=<pid_t></code></strong></strong><dd>
+ Makes the process a member of the specified process group
+ <a href="socat.html#TYPE_PID_T"><pid_t></a>. If no value
+ is given, or if the value is 0 or 1, the process becomes leader of a new
+ process group.
+<a name="OPTION_SETSID"></a><p></p><dt><strong><strong><code>setsid</code></strong></strong><dd>
+ Makes the process the leader of a new session (<a href="socat.html#EXAMPLE_OPTION_SETSID">example</a>).
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_READLINE"></a><em><strong>READLINE option group</strong></em>
+<p>These options apply to the readline address type.
+<dl>
+<a name="OPTION_HISTORY"></a><p></p><dt><strong><strong><code>history=<filename></code></strong></strong><dd>
+ Reads and writes history from/to <a href="socat.html#TYPE_FILENAME"><filename></a> (<a href="socat.html#EXAMPLE_OPTION_HISTORY">example</a>).
+<a name="OPTION_NOPROMPT"></a><p></p><dt><strong><strong><code>noprompt</code></strong></strong><dd>
+ Since version 1.4.0, socat per default tries to determine a prompt -
+ that is then passed to the readline call - by remembering the last
+ incomplete line of the output. With this option, socat does not pass a
+ prompt to readline, so it begins line editing in the first column
+ of the terminal.
+<a name="OPTION_NOECHO"></a><p></p><dt><strong><strong><code>noecho=<pattern></code></strong></strong><dd>
+ Specifies a regular pattern for a prompt that prevents the following input
+ line from being displayed on the screen and from being added to the history.
+ The prompt is defined as the text that was output to the readline address
+ after the lastest newline character and before an input character was
+ typed. The pattern is a regular expression, e.g.
+ "^[Pp]assword:.*$" or "([Uu]ser:|[Pp]assword:)". See regex(7) for details.
+ (<a href="socat.html#EXAMPLE_OPTION_NOECHO">example</a>)
+<a name="OPTION_PROMPT"></a><p></p><dt><strong><strong><code>prompt=<string></code></strong></strong><dd>
+ Passes the string as prompt to the readline function. readline prints this
+ prompt when stepping through the history. If this string matches a constant
+ prompt issued by an interactive program on the other socat address,
+ consistent look and feel can be archieved.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_APPLICATION"></a><em><strong>APPLICATION option group</strong></em>
+<p>This group contains options that work at data level.
+Note that these options only apply to the "raw" data transferred by socat,
+but not to protocol data used by addresses like
+<a href="socat.html#ADDRESS_PROXY_CONNECT">PROXY</a>.
+<dl>
+<a name="OPTION_CR"></a><p></p><dt><strong><strong><code>cr</code></strong></strong><dd>
+ Converts the default line termination character NL ('\n', 0x0a) to/from CR
+ ('\r', 0x0d) when writing/reading on this channel.
+<a name="OPTION_CRNL"></a><p></p><dt><strong><strong><code>crnl</code></strong></strong><dd>
+ Converts the default line termination character NL ('\n', 0x0a) to/from CRNL
+ ("\r\n", 0x0d0a) when writing/reading on this channel (<a href="socat.html#EXAMPLE_OPTION_CRNL">example</a>).
+ Note: socat simply strips all CR characters.
+<a name="OPTION_IGNOREEOF"></a><p></p><dt><strong><strong><code>ignoreeof</code></strong></strong><dd>
+ When EOF occurs on this channel, <strong>socat</strong> ignores it and tries to read more
+ data (like "tail -f") (<a href="socat.html#EXAMPLE_OPTION_IGNOREEOF">example</a>).
+<a name="OPTION_READBYTES"></a><p></p><dt><strong><strong><code>readbytes=<bytes></code></strong></strong><dd>
+ <strong>socat</strong> reads only so many bytes from this address (the address provides
+ only so many bytes for transfer and pretends to be at EOF afterwards).
+ Must be greater than 0.
+<a name="OPTION_LOCKFILE"></a><p></p><dt><strong><strong><code>lockfile=<filename></code></strong></strong><dd>
+ If lockfile exists, exits with error. If lockfile does not exist, creates it
+ and continues, unlinks lockfile on exit.
+<a name="OPTION_WAITLOCK"></a><p></p><dt><strong><strong><code>waitlock=<filename></code></strong></strong><dd>
+ If lockfile exists, waits until it disappears. When lockfile does not exist,
+ creates it and continues, unlinks lockfile on exit.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_SOCKET"></a><em><strong>SOCKET option group</strong></em>
+<p>These options are intended for all kinds of sockets, e.g. IP or UNIX domain. Most are applied with a <code>setsockopt()</code> call.
+<dl>
+<a name="OPTION_BIND"></a><p></p><dt><strong><strong><code>bind=<sockname></code></strong></strong><dd>
+ Binds the socket to the given socket address using the <code>bind()</code> system
+ call. The form of <sockname> is socket domain dependent:
+ IP4 and IP6 allow the form [hostname|hostaddress][:(service|port)] (<a href="socat.html#EXAMPLE_OPTION_BIND_TCP4">example</a>),
+ UNIX domain sockets require <a href="socat.html#TYPE_FILENAME"><filename></a>.
+<a name="OPTION_CONNECT_TIMEOUT"></a><p></p><dt><strong><strong><code>connect-timeout=<seconds></code></strong></strong><dd>
+ Abort the connection attempt after <seconds> [<a href="socat.html#TYPE_TIMEVAL">timeval</a>]
+ with error status.
+<a name="OPTION_INTERFACE"></a><p></p><dt><strong><strong><code>interface=<interface></code></strong></strong><dd>
+ Binds the socket to the given <a href="socat.html#TYPE_INTERFACE"><interface></a>.
+ This option might require root privilege.
+<a name="OPTION_SO_BROADCAST"></a><p></p><dt><strong><strong><code>broadcast</code></strong></strong><dd>
+ For datagram sockets, allows sending to broadcast addresses and receiving
+ packets addressed to broadcast addresses.
+<a name="OPTION_BSDCOMPAT"></a><p></p><dt><strong><strong><code>bsdcompat</code></strong></strong><dd>
+ Emulates some (old?) bugs of the BSD socket implementation.
+<a name="OPTION_DEBUG"></a><p></p><dt><strong><strong><code>debug</code></strong></strong><dd>
+ Enables socket debugging.
+<a name="OPTION_DONTROUTE"></a><p></p><dt><strong><strong><code>dontroute</code></strong></strong><dd>
+ Only communicates with directly connected peers, does not use routers.
+<a name="OPTION_KEEPALIVE"></a><p></p><dt><strong><strong><code>keepalive</code></strong></strong><dd>
+ Enables sending keepalives on the socket.
+<a name="OPTION_LINGER"></a><p></p><dt><strong><strong><code>linger=<seconds></code></strong></strong><dd>
+ Blocks <code>shutdown()</code> or <code>close()</code> until data transfers have finished
+ or the given timeout [<a href="socat.html#TYPE_INT">int</a>] expired.
+
+<a name="OPTION_OOBINLINE"></a><p></p><dt><strong><strong><code>oobinline</code></strong></strong><dd>
+ Places out-of-band data in the input data stream.
+<a name="OPTION_PRIORITY"></a><p></p><dt><strong><strong><code>priority=<priority></code></strong></strong><dd>
+ Sets the protocol defined <priority> [<a href="socat.html#TYPE_INT"><int></a>] for outgoing
+ packets.
+<a name="OPTION_RCVBUF"></a><p></p><dt><strong><strong><code>rcvbuf=<bytes></code></strong></strong><dd>
+ Sets the size of the receive buffer after the <code>socket()</code> call to
+ <bytes> [<a href="socat.html#TYPE_INT">int</a>]. With TCP
+ sockets, this value corresponds to the socket's maximal window size.
+<a name="OPTION_RCVBUF_LATE"></a><p></p><dt><strong><strong><code>rcvbuf-late=<bytes></code></strong></strong><dd>
+ Sets the size of the receive buffer when the socket is already
+ connected to <bytes> [<a href="socat.html#TYPE_INT">int</a>].
+ With TCP sockets, this value corresponds to the socket's
+ maximal window size.
+<a name="OPTION_RCVLOWAT"></a><p></p><dt><strong><strong><code>rcvlowat=<bytes></code></strong></strong><dd>
+ Specifies the minimum number of received bytes [<a href="socat.html#TYPE_INT">int</a>] until
+ the socket layer will pass the buffered data to <strong>socat</strong>.
+<a name="OPTION_RCVTIMEO"></a><p></p><dt><strong><strong><code>rcvtimeo=<seconds></code></strong></strong><dd>
+ Sets the receive timeout [<a href="socat.html#TYPE_TIMEVAL">timeval</a>].
+<a name="OPTION_REUSEADDR"></a><p></p><dt><strong><strong><code>reuseaddr</code></strong></strong><dd>
+ Allows other sockets to bind to an address even if parts of it (e.g. the
+ local port) are already in use by <strong>socat</strong> (<a href="socat.html#EXAMPLE_OPTION_REUSEADDR">example</a>).
+<a name="OPTION_SNDBUF"></a><p></p><dt><strong><strong><code>sndbuf=<bytes></code></strong></strong><dd>
+ Sets the size of the send buffer after the <code>socket()</code> call to
+ <bytes> [<a href="socat.html#TYPE_INT">int</a>].
+<a name="OPTION_SNDBUF_LATE"></a><p></p><dt><strong><strong><code>sndbuf-late=<bytes></code></strong></strong><dd>
+ Sets the size of the send buffer when the socket is connected to
+ <bytes> [<a href="socat.html#TYPE_INT">int</a>].
+<a name="OPTION_SNDLOWAT"></a><p></p><dt><strong><strong><code>sndlowat=<bytes></code></strong></strong><dd>
+ Specifies the minimum number of bytes in the send buffer until the socket
+ layer will send the data to <bytes> [<a href="socat.html#TYPE_INT">int</a>].
+<a name="OPTION_SNDTIMEO"></a><p></p><dt><strong><strong><code>sndtimeo=<seconds></code></strong></strong><dd>
+ Sets the send timeout to seconds [<a href="socat.html#TYPE_TIMEVAL">timeval</a>].
+<a name="OPTION_TYPE"></a><p></p><dt><strong><strong><code>type=<type></code></strong></strong><dd>
+ Sets the type of the socket, usually as argument to the <code>socket()</code> or
+ <code>socketpair()</code> call, to <type> [<a href="socat.html#TYPE_INT">int</a>].
+ Under Linux, 1 means stream oriented socket, 2 means datagram socket, and 3
+ means raw socket.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<a name="OPTION_PROTOCOL_FAMILY"></a><p></p><dt><strong><strong><code>pf=<string></code></strong></strong><dd>
+ Forces the use of the specified IP version. <string> can be
+ something like "ip4" or "ip6".
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_SOCK_UNIX"></a><em><strong>UNIX option group</strong></em>
+<p>These options apply to UNIX domain based addresses.
+<dl>
+<a name="OPTION_UNIX_TIGHTSOCKLEN"></a><p></p><dt><strong><strong><code>unix-tightsocklen=[0|1]</code></strong></strong><dd>
+ On socket operations, pass a socket address length that does not include the
+ whole <code>struct sockaddr_un</code> record but (besides other components) only
+ the relevant part of the filename or abstract string. Default is 1.
+</dl>
+<p><a name="GROUP_IP4"></a>
+<a name="GROUP_IP"></a><em><strong>IP4 and IP6 option groups</strong></em>
+<p>These options can be used with IPv4 and IPv6 based sockets.
+<dl>
+<a name="OPTION_TOS"></a><p></p><dt><strong><strong><code>tos=<tos></code></strong></strong><dd>
+ Sets the TOS (type of service) field of outgoing packets to <tos>
+ [<a href="socat.html#TYPE_BYTE">byte</a>] (see RFC 791).
+<a name="OPTION_TTL"></a><p></p><dt><strong><strong><code>ttl=<ttl></code></strong></strong><dd>
+ Sets the TTL (time to live) field of outgoing packets to <ttl>
+ [<a href="socat.html#TYPE_BYTE">byte</a>].
+<a name="OPTION_IPOPTIONS"></a><p></p><dt><strong><strong><code>ipoptions=<data></code></strong></strong><dd>
+ 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</code>.<br>
+ IP options are defined in RFC 791. <br>
+
+<a name="OPTION_MTUDISCOVER"></a><p></p><dt><strong><strong><code>mtudiscover=<0|1|2></code></strong></strong><dd>
+ Takes 0, 1, 2 to never, want, or always use path MTU discover on this
+ socket.
+
+
+
+
+
+
+
+
+
+
+
+<a name="OPTION_IP_ADD_MEMBERSHIP"></a>
+<p></p><dt><strong><strong><code>ip-add-membership=<multicast-address:interface-address></code></strong></strong><dd>
+<p></p><dt><strong><strong><code>ip-add-membership=<multicast-address:interface-name></code></strong></strong><dd>
+<p></p><dt><strong><strong><code>ip-add-membership=<multicast-address:interface-index></code></strong></strong><dd>
+<p></p><dt><strong><strong><code>ip-add-membership=<multicast-address:interface-address:interface-name></code></strong></strong><dd>
+<p></p><dt><strong><strong><code>ip-add-membership=<multicast-address:interface-address:interface-index></code></strong></strong><dd>
+ Makes the socket member of the specified multicast group. This is currently
+ only implemented for IPv4. The option takes the IP address of the multicast
+ group and info about the desired network interface. The most common syntax
+ is the first one, while the others are only available on systems that
+ provide <code>struct mreqn</code> (Linux).<br>
+ The indices of active network interfaces can be shown using the utility
+ <strong>procan</strong>.
+<a name="OPTION_IP_MULTICAST_IF"></a>
+dif(<strong><code>ip-multicast-if=<hostname></code></strong>)
+ Specifies hostname or address of the network interface to be used for
+ multicast traffic.
+<a name="OPTION_IP_MULTICAST_LOOP"></a>
+dif(<strong><code>ip-multicast-loop=<bool></code></strong>)
+ Specifies if outgoing multicast traffic should loop back to the interface.
+<a name="OPTION_IP_MULTICAST_TTL"></a>
+dif(<strong><code>ip-multicast-ttl=<byte></code></strong>)
+ Sets the TTL used for outgoing multicast traffic. Default is 1.
+<a name="OPTION_RES_DEBUG"></a><p></p><dt><strong><strong><code>res-debug</code></strong></strong><dd>
+<a name="OPTION_RES_AAONLY"></a><p></p><dt><strong><strong><code>res-aaonly</code></strong></strong><dd>
+<a name="OPTION_RES_USEVC"></a><p></p><dt><strong><strong><code>res-usevc</code></strong></strong><dd>
+<a name="OPTION_RES_PRIMARY"></a><p></p><dt><strong><strong><code>res-primary</code></strong></strong><dd>
+<a name="OPTION_RES_IGNTC"></a><p></p><dt><strong><strong><code>res-igntc</code></strong></strong><dd>
+<a name="OPTION_RES_RECURSE"></a><p></p><dt><strong><strong><code>res-recurse</code></strong></strong><dd>
+<a name="OPTION_RES_DEFNAMES"></a><p></p><dt><strong><strong><code>res-defnames</code></strong></strong><dd>
+<a name="OPTION_RES_STAYOPEN"></a><p></p><dt><strong><strong><code>res-stayopen</code></strong></strong><dd>
+<a name="OPTION_RES_DNSRCH"></a><p></p><dt><strong><strong><code>res-dnsrch</code></strong></strong><dd>
+ These options set the corresponding resolver (name resolution) option flags.
+ Append "=0" to clear a default option. See man resolver(5) for more
+ information on these options. Note: these options are valid only for the
+ address they are applied to.
+<p></dl>
+<p><dl></dl><br>
+<p><a name="GROUP_IP6"></a><em><strong>IP6 option group</strong></em>
+<p>These options can only be used on IPv6 based sockets. See <a href="socat.html#GROUP_IP">IP
+options</a> for options that can be applied to both IPv4 and IPv6
+sockets.
+<dl>
+<a name="OPTION_IPV6_V6ONLY"></a><p></p><dt><strong><strong><code>ipv6only=<bool></code></strong></strong><dd>
+ 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.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_TCP"></a><em><strong>TCP option group</strong></em>
+<p>These options may be applied to TCP sockets. They work by invoking <code>setsockopt()</code> with the appropriate parameters.
+<dl>
+<a name="OPTION_CORK"></a><p></p><dt><strong><strong><code>cork</code></strong></strong><dd>
+ Doesn't send packets smaller than MSS (maximal segment size).
+<a name="OPTION_DEFER-ACCEPT"></a><p></p><dt><strong><strong><code>defer-accept</code></strong></strong><dd>
+ While listening, accepts connections only when data from the peer arrived.
+<a name="OPTION_KEEPCNT"></a><p></p><dt><strong><strong><code>keepcnt=<count></code></strong></strong><dd>
+ Sets the number of keepalives before shutting down the socket to
+ <count> [<a href="socat.html#TYPE_INT">int</a>].
+<a name="OPTION_KEEPIDLE"></a><p></p><dt><strong><strong><code>keepidle=<seconds></code></strong></strong><dd>
+ Sets the idle time before sending the first keepalive to <seconds>
+ [<a href="socat.html#TYPE_INT">int</a>].
+<a name="OPTION_KEEPINTVL"></a><p></p><dt><strong><strong><code>keepintvl=<seconds></code></strong></strong><dd>
+ Sets the intervall between two keepalives to <seconds>
+ [<a href="socat.html#TYPE_INT">int</a>].
+<a name="OPTION_LINGER2"></a><p></p><dt><strong><strong><code>linger2=<seconds></code></strong></strong><dd>
+ Sets the time to keep the socket in FIN-WAIT-2 state to <seconds>
+ [<a href="socat.html#TYPE_INT">int</a>].
+<a name="OPTION_MSS"></a><p></p><dt><strong><strong><code>mss=<bytes></code></strong></strong><dd>
+ Sets the MSS (maximum segment size) after the <code>socket()</code> call to <bytes>
+ [<a href="socat.html#TYPE_INT">int</a>]. This
+ value is then proposed to the peer with the SYN or SYN/ACK packet
+ (<a href="socat.html#EXAMPLE_OPTION_MSS">example</a>).
+<a name="OPTION_MSS_LATE"></a><p></p><dt><strong><strong><code>mss-late=<bytes></code></strong></strong><dd>
+ Sets the MSS of the socket after connection has been established to <bytes>
+ [<a href="socat.html#TYPE_INT">int</a>].
+<a name="OPTION_NODELAY"></a><p></p><dt><strong><strong><code>nodelay</code></strong></strong><dd>
+ Turns off the Nagle algorithm for measuring the RTT (round trip time).
+<a name="OPTION_RFC1323"></a><p></p><dt><strong><strong><code>rfc1323</code></strong></strong><dd>
+ Enables RFC1323 TCP options: TCP window scale, round-trip time measurement
+ (RTTM), and protect against wrapped sequence numbers (PAWS) (AIX).
+<a name="OPTION_STDURG"></a><p></p><dt><strong><strong><code>stdurg</code></strong></strong><dd>
+ Enables RFC1122 compliant urgent pointer handling (AIX).
+<a name="OPTION_SYNCNT"></a><p></p><dt><strong><strong><code>syncnt=<count></code></strong></strong><dd>
+ Sets the maximal number of SYN retransmits during connect to <count>
+ [<a href="socat.html#TYPE_INT">int</a>].
+
+
+<a name="OPTION_TCP_MD5SIG"></a><p></p><dt><strong><strong><code>md5sig</code></strong></strong><dd>
+ Enables generation of MD5 digests on the packets (FreeBSD).
+<a name="OPTION_TCP_NOOPT"></a><p></p><dt><strong><strong><code>noopt</code></strong></strong><dd>
+ Disables use of TCP options (FreeBSD, MacOSX).
+<a name="OPTION_TCP_NOPUSH"></a><p></p><dt><strong><strong><code>nopush</code></strong></strong><dd>
+ sets the TCP_NOPUSH socket option (FreeBSD, MacOSX).
+<a name="OPTION_TCP_SACK_DISABLE"></a><p></p><dt><strong><strong><code>sack-disable</code></strong></strong><dd>
+ Disables use the selective acknowledge feature (OpenBSD).
+<a name="OPTION_TCP_SIGNATURE_ENABLE"></a><p></p><dt><strong><strong><code>signature-enable</code></strong></strong><dd>
+ Enables generation of MD5 digests on the packets (OpenBSD).
+<a name="OPTION_TCP_ABORT_THRESHOLD"></a><p></p><dt><strong><strong><code>abort-threshold=<milliseconds></code></strong></strong><dd>
+ Sets the time to wait for an answer of the peer on an established connection
+ (HP-UX).
+<a name="OPTION_TCP_CONN_ABORT_THRESHOLD"></a><p></p><dt><strong><strong><code>conn-abort-threshold=<milliseconds></code></strong></strong><dd>
+ Sets the time to wait for an answer of the server during the initial connect
+ (HP-UX).
+<a name="OPTION_TCP_KEEPINIT"></a><p></p><dt><strong><strong><code>keepinit</code></strong></strong><dd>
+ Sets the time to wait for an answer of the server during connect() before
+ giving up. Value in half seconds, default is 150 (75s) (Tru64).
+<a name="OPTION_TCP_PAWS"></a><p></p><dt><strong><strong><code>paws</code></strong></strong><dd>
+ Enables the "protect against wrapped sequence numbers" feature (Tru64).
+<a name="OPTION_TCP_SACKENA"></a><p></p><dt><strong><strong><code>sackena</code></strong></strong><dd>
+ Enables selective acknowledge (Tru64).
+<a name="OPTION_TCP_TSOPTENA"></a><p></p><dt><strong><strong><code>tsoptena</code></strong></strong><dd>
+ Enables the time stamp option that allows RTT recalculation on existing
+ connections (Tru64).
+</dl>
+<p><dl></dl><br>
+<p><em><strong>UDP and TCP option groups</strong></em>
+<p>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.
+<dl>
+<a name="OPTION_SOURCEPORT"></a><p></p><dt><strong><strong><code>sourceport=<port></code></strong></strong><dd>
+ For outgoing (client) TCP and UDP connections, it sets the source
+ <a href="socat.html#TYPE_PORT"><port></a> using an extra <code>bind()</code> call.
+ With TCP or UDP listen addresses, socat immediately shuts down the
+ connection if the client does not use this sourceport (<a href="socat.html#EXAMPLE_OPTION_SOURCEPORT">example</a>).
+<a name="OPTION_LOWPORT"></a><p></p><dt><strong><strong><code>lowport</code></strong></strong><dd>
+ Outgoing (client) TCP and UDP connections with this option use
+ an unused random source port between 640 and 1023 incl. On UNIX class operating
+ systems, this requires root privilege, and thus indicates that the
+ client process is authorized by local root.
+ TCP and UDP listen addresses with this option immediately shut down the
+ connection if the client does not use a sourceport <= 1023.
+ This mechanism can provide limited authorization under some circumstances.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_SOCKS"></a><em><strong>SOCKS option group</strong></em>
+<p>When using SOCKS type addresses, some socks specific options can be set.
+<dl>
+<a name="OPTION_SOCKSPORT"></a><p></p><dt><strong><strong><code>socksport=<tcp service></code></strong></strong><dd>
+ Overrides the default "socks" service or port 1080 for the socks server
+ port with <a href="socat.html#TYPE_TCP_SERVICE"><TCP service></a>.
+<a name="OPTION_SOCKSUSER"></a><p></p><dt><strong><strong><code>socksuser=<user></code></strong></strong><dd>
+ Sends the <user> [<a href="socat.html#TYPE_STRING">string</a>] in the username field to the
+ socks server. Default is the actual user name ($LOGNAME or $USER) (<a href="socat.html#EXAMPLE_OPTION_SOCKSUSER">example</a>).
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_HTTP"></a><em><strong>HTTP option group</strong></em>
+<p>Options that can be provided with HTTP type addresses. The only HTTP address
+currently implemented is <a href="socat.html#ADDRESS_PROXY_CONNECT">proxy-connect</a>.
+<p><dl>
+<a name="OPTION_PROXYPORT"></a><p></p><dt><strong><strong><code>proxyport=<TCP service></code></strong></strong><dd>
+ Overrides the default HTTP proxy port 8080 with
+ <a href="socat.html#TYPE_TCP_SERVICE"><TCP service></a>.
+<a name="OPTION_IGNORECR"></a><p></p><dt><strong><strong><code>ignorecr</code></strong></strong><dd>
+ The HTTP protocol requires the use of CR+NL as line terminator. When a proxy
+ server violates this standard, socat might not understand its answer.
+ This option directs socat to interprete NL as line terminator and
+ to ignore CR in the answer. Nevertheless, socat sends CR+NL to the proxy.
+<a name="OPTION_PROXY_AUTHORIZATION"></a><p></p><dt><strong><strong><code>proxyauth=<username>:<password></code></strong></strong><dd>
+ Provide "basic" authentication to the proxy server. The argument to the
+ option is used with a "Proxy-Authorization: Base" header in base64 encoded
+ form.<br>
+ Note: username and password are visible for every user on the local machine
+ in the process list; username and password are transferred to the proxy
+ server unencrypted (base64 encoded) and might be sniffed.
+<a name="OPTION_PROXY_RESOLVE"></a><p></p><dt><strong><strong><code>resolve</code></strong></strong><dd>
+ Per default, socat sends to the proxy a CONNECT request containing the
+ target hostname. With this option, socat resolves the hostname locally and
+ sends the IP address. Please note that, according to RFC 2396, only name
+ resolution to IPv4 addresses is implemented.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_RANGE"></a><em><strong>RANGE option group</strong></em>
+<p>These options check if a connecting client should be granted access. They can
+be applied to listening and receiving network sockets. tcp-wrappers options
+fall into this group.
+<dl>
+<a name="OPTION_RANGE"></a><p></p><dt><strong><strong><code>range=<address-range></code></strong></strong><dd>
+ After accepting a connection, tests if the peer is within <em>range</em>. For
+ IPv4 addresses, address-range takes the form address/bits, e.g.
+ 10.0.0.0/8, or address:mask, e.g. 10.0.0.0:255.0.0.0 (<a href="socat.html#EXAMPLE_OPTION_RANGE">example</a>); for IPv6, it is [ip6-address/bits], e.g. [::1/128].
+ If the client address does not match, <strong>socat</strong> issues a warning and keeps
+ listening/receiving.
+<a name="OPTION_TCPWRAPPERS"></a><p></p><dt><strong><strong><code>tcpwrap[=<name>]</code></strong></strong><dd>
+ Uses Wietse Venema's libwrap (tcpd) library to determine
+ if the client is allowed to connect. The configuration files are
+ /etc/hosts.allow and /etc/hosts.deny per default, see "man 5 hosts_access"
+ for more information. The optional <name> (type <a href="socat.html#TYPE_STRING">string</a>)
+ is passed to the wrapper functions as daemon process name (<a href="socat.html#EXAMPLE_OPTION_TCPWRAPPERS">example</a>).
+ If omitted, the basename of socats invocation (argv[0]) is passed.
+ If both tcpwrap and range options are applied to an address, both
+ conditions must be fulfilled to allow the connection.
+<a name="OPTION_TCPWRAP_HOSTS_ALLOW_TABLE"></a><p></p><dt><strong><strong><code>allow-table=<filename></code></strong></strong><dd>
+ Takes the specified file instead of /etc/hosts.allow.
+<a name="OPTION_TCPWRAP_HOSTS_DENY_TABLE"></a><p></p><dt><strong><strong><code>deny-table=<filename></code></strong></strong><dd>
+ Takes the specified file instead of /etc/hosts.deny.
+<a name="OPTION_TCPWRAP_ETC"></a><p></p><dt><strong><strong><code>tcpwrap-etc=<directoryname></code></strong></strong><dd>
+ Looks for hosts.allow and hosts.deny in the specified directory. Is
+ overridden by options <a href="socat.html#OPTION_TCPWRAP_HOSTS_ALLOW_TABLE">hosts-allow</a>
+ and <a href="socat.html#OPTION_TCPWRAP_HOSTS_DENY_TABLE">hosts-deny</a>.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_LISTEN"></a><em><strong>LISTEN option group</strong></em>
+<p>Options specific to listening sockets.
+<dl>
+<a name="OPTION_BACKLOG"></a><p></p><dt><strong><strong><code>backlog=<count></code></strong></strong><dd>
+ Sets the backlog value passed with the <code>listen()</code> system call to <count>
+ [<a href="socat.html#TYPE_INT">int</a>]. Default is 5.
+</dl>
+<dl></dl><br>
+<p><a name="GROUP_CHILD"></a><em><strong>CHILD option group</strong></em>
+<p>Options for addresses with multiple connections via child processes.
+<dl>
+<a name="OPTION_FORK"></a><p></p><dt><strong><strong><code>fork</code></strong></strong><dd>
+ After establishing a connection, handles its channel in a child process and
+ keeps the parent process attempting to produce more connections, either by
+ listening or by connecting in a loop (<a href="socat.html#EXAMPLE_OPTION_FORK">example</a>).<br>
+ SSL-CONNECT and SSL-LISTEN differ in when they actually fork off the child:
+SSL-LISTEN forks <em>before</em> the SSL handshake, while SSL-CONNECT forks
+<em>afterwards</em>.
+ RETRY and FOREVER options are not inherited by the child process.<br>
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_EXEC"></a><em><strong>EXEC option group</strong></em>
+<p>Options for addresses that invoke a program.
+<dl>
+<a name="OPTION_PATH"></a><p></p><dt><strong><strong><code>path=<string></code></strong></strong><dd>
+ Overrides the PATH environment variable for searching the program with
+ <a href="socat.html#TYPE_STRING"><string></a>. This
+ <code>$PATH</code> value is effective in the child process too.
+<a name="OPTION_LOGIN"></a><p></p><dt><strong><strong><code>login</code></strong></strong><dd>
+ Prefixes <code>argv[0]</code> for the <code>execvp()</code> call with '-', thus making a
+ shell behave as login shell.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_FORK"></a><em><strong>FORK option group</strong></em>
+<p>EXEC or SYSTEM addresses invoke a program using a child process and transfer data between <strong>socat</strong> and the program. The interprocess communication mechanism can be influenced with the following options. Per
+default, a <code>socketpair()</code> is created and assigned to stdin and stdout of
+the child process, while stderr is inherited from the <strong>socat</strong> process, and the
+child process uses file descriptors 0 and 1 for communicating with the main
+socat process.
+<dl>
+<a name="OPTION_NOFORK"></a><p></p><dt><strong><strong><code>nofork</code></strong></strong><dd>
+ Does not fork a subprocess for executing the program, instead calls execvp()
+ or system() directly from the actual socat instance. This avoids the
+ overhead of another process between the program and its peer,
+ but introduces a lot of restrictions:
+ <dl>
+ <li > this option can only be applied to the second <strong>socat</strong> address.
+ <li > it cannot be applied to a part of a <a href="socat.html#ADDRESS_DUAL">dual</a> address.
+ <li > the first socat address cannot be OPENSSL or READLINE
+ <li > socat options -b, -t, -D, -l, -v, -x become useless
+ <li > for both addresses, options ignoreeof, cr, and crnl become useless
+ <li > for the second address (the one with option nofork), options
+ append, <!--async,--> cloexec, flock, user, group, mode, nonblock,
+ perm-late, setlk, and setpgid cannot be applied. Some of these could be
+ used on the first address though.
+ </dl>
+<a name="OPTION_PIPES"></a><p></p><dt><strong><strong><code>pipes</code></strong></strong><dd>
+ Creates a pair of unnamed pipes for interprocess communication instead of a
+ socket pair.
+<a name="OPTION_OPENPTY"></a><p></p><dt><strong><strong><code>openpty</code></strong></strong><dd>
+ Establishes communication with the sub process using a pseudo terminal
+ created with <code>openpty()</code> instead of the default (socketpair or ptmx).
+<a name="OPTION_PTMX"></a><p></p><dt><strong><strong><code>ptmx</code></strong></strong><dd>
+ Establishes communication with the sub process using a pseudo terminal
+ created by opening <strong>/dev/ptmx</strong> or <strong>/dev/ptc</strong> instead of the default
+ (socketpair).
+<a name="OPTION_PTY"></a><p></p><dt><strong><strong><code>pty</code></strong></strong><dd>
+ Establishes communication with the sub process using a pseudo terminal
+ instead of a socket pair. Creates the pty with an available mechanism. If
+ openpty and ptmx are both available, it uses ptmx because this is POSIX
+ compliant (<a href="socat.html#EXAMPLE_OPTION_PTY">example</a>).
+<a name="OPTION_CTTY"></a><p></p><dt><strong><strong><code>ctty</code></strong></strong><dd>
+ Makes the pty the controlling tty of the sub process (<a href="socat.html#EXAMPLE_OPTION_CTTY">example</a>).
+<a name="OPTION_STDERR"></a><p></p><dt><strong><strong><code>stderr</code></strong></strong><dd>
+ Directs stderr of the sub process to its output channel by making stderr a
+ <code>dup()</code> of stdout (<a href="socat.html#EXAMPLE_OPTION_STDERR">example</a>).
+<a name="OPTION_FDIN"></a><p></p><dt><strong><strong><code>fdin=<fdnum></code></strong></strong><dd>
+ Assigns the sub processes input channel to its file descriptor
+ <a href="socat.html#TYPE_FDNUM"><fdnum></a>
+ instead of stdin (0). The program started from the subprocess has to use
+ this fd for reading data from <strong>socat</strong> (<a href="socat.html#EXAMPLE_OPTION_FDIN">example</a>).
+<a name="OPTION_FDOUT"></a><p></p><dt><strong><strong><code>fdout=<fdnum></code></strong></strong><dd>
+ Assigns the sub processes output channel to its file descriptor
+ <a href="socat.html#TYPE_FDNUM"><fdnum></a>
+ instead of stdout (1). The program started from the subprocess has to use
+ this fd for writing data to <strong>socat</strong> (<a href="socat.html#EXAMPLE_OPTION_FDOUT">example</a>).
+<a name="OPTION_SIGHUP"></a><a name="OPTION_SIGINT"></a><a name="OPTION_SIGQUIT"></a><p></p><dt><strong><strong><code>sighup</code></strong>, <strong><code>sigint</code></strong>, <strong><code>sigquit</code></strong></strong><dd>
+ Has <strong>socat</strong> pass an eventual signal of this type to the sub process.
+ If no address has this option, socat terminates on these signals.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_TERMIOS"></a><em><strong>TERMIOS option group</strong></em>
+<p>For addresses that work on a tty (e.g., stdio, file:/dev/tty, exec:...,pty), the terminal parameters defined in the UN*X termios mechanism are made available as address option parameters.
+Please note that changes of the parameters of your interactive terminal
+remain effective after <strong>socat</strong>'s termination, so you might have to enter "reset"
+or "stty sane" in your shell afterwards.
+For EXEC and SYSTEM addresses with option PTY,
+these options apply to the pty by the child processes.
+<p><dl>
+<a name="OPTION_B0"></a><p></p><dt><strong><strong><code>b0</code></strong></strong><dd>
+ Disconnects the terminal.
+<a name="OPTION_B19200"></a><p></p><dt><strong><strong><code>b19200</code></strong></strong><dd>
+ Sets the serial line speed to 19200 baud. Some other rates are possible; use
+something like <code>socat -hh |grep ' b[1-9]'</code> to find all speeds supported by
+your implementation.<br>
+Note: On some operating systems, these options may not be
+available. Use <a href="socat.html#OPTION_ISPEED">ispeed</a> or <a href="socat.html#OPTION_OSPEED">ospeed</a>
+instead.
+<a name="OPTION_ECHO"></a><p></p><dt><strong><strong><code>echo=<bool></code></strong></strong><dd>
+ Enables or disables local echo (<a href="socat.html#EXAMPLE_OPTION_ECHO">example</a>).
+<a name="OPTION_ICANON"></a><p></p><dt><strong><strong><code>icanon=<bool></code></strong></strong><dd>
+ Sets or clears canonical mode, enabling line buffering and some special
+ characters.
+<a name="OPTION_RAW"></a><p></p><dt><strong><strong><code>raw</code></strong></strong><dd>
+ Sets raw mode, thus passing input and output almost unprocessed (<a href="socat.html#EXAMPLE_OPTION_RAW">example</a>).
+<a name="OPTION_IGNBRK"></a><p></p><dt><strong><strong><code>ignbrk=<bool></code></strong></strong><dd>
+ Ignores or interpretes the BREAK character (e.g., ^C)
+<a name="OPTION_BRKINT"></a><p></p><dt><strong><strong><code>brkint=<bool></code></strong></strong><dd>
+<a name="OPTION_BS0"></a><p></p><dt><strong><strong><code>bs0</code></strong></strong><dd>
+<a name="OPTION_BS1"></a><p></p><dt><strong><strong><code>bs1</code></strong></strong><dd>
+<a name="OPTION_BSDLY"></a><p></p><dt><strong><strong><code>bsdly=<0|1></code></strong></strong><dd>
+<a name="OPTION_CLOCAL"></a><p></p><dt><strong><strong><code>clocal=<bool></code></strong></strong><dd>
+<p><a name="OPTION_CR0"></a><a name="OPTION_CR1"></a><a name="OPTION_CR2"></a><a name="OPTION_CR3"></a>
+
+
+
+
+
+<dt><code><strong>cr0</strong><br>
+<strong>cr1</strong><br>
+<strong>cr2</strong><br>
+<strong>cr3</strong></code><dd>
+ Sets the carriage return delay to 0, 1, 2, or 3, respectively.
+ 0 means no delay, the other values are terminal dependent.
+<p><a name="OPTION_CRDLY"></a><p></p><dt><strong><strong><code>crdly=<0|1|2|3></code></strong></strong><dd>
+<a name="OPTION_CREAD"></a><p></p><dt><strong><strong><code>cread=<bool></code></strong></strong><dd>
+<a name="OPTION_CRTSCTS"></a><p></p><dt><strong><strong><code>crtscts=<bool></code></strong></strong><dd>
+<p><a name="OPTION_CS5"></a><a name="OPTION_CS6"></a><a name="OPTION_CS7"></a><a name="OPTION_CS8"></a>
+
+
+
+
+
+<dt><code><strong>cs5</strong><br>
+<strong>cs6</strong><br>
+<strong>cs7</strong><br>
+<strong>cs8</strong></code><dd>
+ Sets the character size to 5, 6, 7, or 8 bits, respectively.
+<p><a name="OPTION_CSIZE"></a><p></p><dt><strong><strong><code>csize=<0|1|2|3></code></strong></strong><dd>
+<a name="OPTION_CSTOPB"></a><p></p><dt><strong><strong><code>cstopb=<bool></code></strong></strong><dd>
+ Sets two stop bits, rather than one.
+<a name="OPTION_VDSUSP"></a><p></p><dt><strong><strong><code>dsusp=<byte></code></strong></strong><dd>
+ Sets the value for the VDSUSP character that suspends the current foreground
+ process and reactivates the shell (all except Linux).
+<a name="OPTION_ECHOCTL"></a><p></p><dt><strong><strong><code>echoctl=<bool></code></strong></strong><dd>
+ Echos control characters in hat notation (e.g. ^A)
+<a name="OPTION_ECHOE"></a><p></p><dt><strong><strong><code>echoe=<bool></code></strong></strong><dd>
+<a name="OPTION_ECHOK"></a><p></p><dt><strong><strong><code>echok=<bool></code></strong></strong><dd>
+<a name="OPTION_ECHOKE"></a><p></p><dt><strong><strong><code>echoke=<bool></code></strong></strong><dd>
+<a name="OPTION_ECHONL"></a><p></p><dt><strong><strong><code>echonl=<bool></code></strong></strong><dd>
+<a name="OPTION_ECHOPRT"></a><p></p><dt><strong><strong><code>echoprt=<bool></code></strong></strong><dd>
+<a name="OPTION_EOF"></a><p></p><dt><strong><strong><code>eof=<byte></code></strong></strong><dd>
+<a name="OPTION_EOL"></a><p></p><dt><strong><strong><code>eol=<byte></code></strong></strong><dd>
+<a name="OPTION_EOL2"></a><p></p><dt><strong><strong><code>eol2=<byte></code></strong></strong><dd>
+<a name="OPTION_ERASE"></a><p></p><dt><strong><strong><code>erase=<byte></code></strong></strong><dd>
+<a name="OPTION_DISCARD"></a><p></p><dt><strong><strong><code>discard=<byte></code></strong></strong><dd>
+<a name="OPTION_FF0"></a><p></p><dt><strong><strong><code>ff0</code></strong></strong><dd>
+<a name="OPTION_FF1"></a><p></p><dt><strong><strong><code>ff1</code></strong></strong><dd>
+<a name="OPTION_FFDLY"></a><p></p><dt><strong><strong><code>ffdly=<bool></code></strong></strong><dd>
+<a name="OPTION_FLUSHO"></a><p></p><dt><strong><strong><code>flusho=<bool></code></strong></strong><dd>
+<a name="OPTION_HUPCL"></a><p></p><dt><strong><strong><code>hupcl=<bool></code></strong></strong><dd>
+<a name="OPTION_ICRNL"></a><p></p><dt><strong><strong><code>icrnl=<bool></code></strong></strong><dd>
+<a name="OPTION_IEXTEN"></a><p></p><dt><strong><strong><code>iexten=<bool></code></strong></strong><dd>
+<a name="OPTION_IGNCR"></a><p></p><dt><strong><strong><code>igncr=<bool></code></strong></strong><dd>
+<a name="OPTION_IGNPAR"></a><p></p><dt><strong><strong><code>ignpar=<bool></code></strong></strong><dd>
+<a name="OPTION_IMAXBEL"></a><p></p><dt><strong><strong><code>imaxbel=<bool></code></strong></strong><dd>
+<a name="OPTION_INLCR"></a><p></p><dt><strong><strong><code>inlcr=<bool></code></strong></strong><dd>
+<a name="OPTION_INPCK"></a><p></p><dt><strong><strong><code>inpck=<bool></code></strong></strong><dd>
+<a name="OPTION_INTR"></a><p></p><dt><strong><strong><code>intr=<byte></code></strong></strong><dd>
+<a name="OPTION_ISIG"></a><p></p><dt><strong><strong><code>isig=<bool></code></strong></strong><dd>
+<a name="OPTION_ISPEED"></a><p></p><dt><strong><strong><code>ispeed=<unsigned-int></code></strong></strong><dd>
+ Set the baud rate for incoming data on this line.<br>
+ See also: <a href="socat.html#OPTION_OSPEED">ospeed</a>, <a href="socat.html#OPTION_B19200">b19200</a>
+<a name="OPTION_ISTRIP"></a>dif(<strong><code>istrip=<bool></code></strong>)
+<a name="OPTION_IUCLC"></a><p></p><dt><strong><strong><code>iuclc=<bool></code></strong></strong><dd>
+<a name="OPTION_IXANY"></a><p></p><dt><strong><strong><code>ixany=<bool></code></strong></strong><dd>
+<a name="OPTION_IXOFF"></a><p></p><dt><strong><strong><code>ixoff=<bool></code></strong></strong><dd>
+<a name="OPTION_IXON"></a><p></p><dt><strong><strong><code>ixon=<bool></code></strong></strong><dd>
+<a name="OPTION_KILL"></a><p></p><dt><strong><strong><code>kill=<byte></code></strong></strong><dd>
+<a name="OPTION_LNEXT"></a><p></p><dt><strong><strong><code>lnext=<byte></code></strong></strong><dd>
+<a name="OPTION_MIN"></a><p></p><dt><strong><strong><code>min=<byte></code></strong></strong><dd>
+<a name="OPTION_NL0"></a><p></p><dt><strong><strong><code>nl0</code></strong></strong><dd>
+ Sets the newline delay to 0.
+<a name="OPTION_NL1"></a><p></p><dt><strong><strong><code>nl1</code></strong></strong><dd>
+<a name="OPTION_NLDLY"></a><p></p><dt><strong><strong><code>nldly=<bool></code></strong></strong><dd>
+<a name="OPTION_NOFLSH"></a><p></p><dt><strong><strong><code>noflsh=<bool></code></strong></strong><dd>
+<a name="OPTION_OCRNL"></a><p></p><dt><strong><strong><code>ocrnl=<bool></code></strong></strong><dd>
+<a name="OPTION_OFDEL"></a><p></p><dt><strong><strong><code>ofdel=<bool></code></strong></strong><dd>
+<a name="OPTION_OFILL"></a><p></p><dt><strong><strong><code>ofill=<bool></code></strong></strong><dd>
+<a name="OPTION_OLCUC"></a><p></p><dt><strong><strong><code>olcuc=<bool></code></strong></strong><dd>
+<a name="OPTION_ONLCR"></a><p></p><dt><strong><strong><code>onlcr=<bool></code></strong></strong><dd>
+<a name="OPTION_ONLRET"></a><p></p><dt><strong><strong><code>onlret=<bool></code></strong></strong><dd>
+<a name="OPTION_ONOCR"></a><p></p><dt><strong><strong><code>onocr=<bool></code></strong></strong><dd>
+<a name="OPTION_OPOST"></a><p></p><dt><strong><strong><code>opost=<bool></code></strong></strong><dd>
+ Enables or disables output processing; e.g., converts NL to CR-NL.
+<a name="OPTION_OSPEED"></a><p></p><dt><strong><strong><code>ospeed=<unsigned-int></code></strong></strong><dd>
+ Set the baud rate for outgoing data on this line.<br>
+ See also: <a href="socat.html#OPTION_ISPEED">ispeed</a>, <a href="socat.html#OPTION_B19200">b19200</a>
+<a name="OPTION_PARENB"></a><p></p><dt><strong><strong><code>parenb=<bool></code></strong></strong><dd>
+ Enable parity generation on output and parity checking for input.
+<a name="OPTION_PARMRK"></a><p></p><dt><strong><strong><code>parmrk=<bool></code></strong></strong><dd>
+<a name="OPTION_PARODD"></a><p></p><dt><strong><strong><code>parodd=<bool></code></strong></strong><dd>
+<a name="OPTION_PENDIN"></a><p></p><dt><strong><strong><code>pendin=<bool></code></strong></strong><dd>
+<a name="OPTION_QUIT"></a><p></p><dt><strong><strong><code>quit=<byte></code></strong></strong><dd>
+<a name="OPTION_REPRINT"></a><p></p><dt><strong><strong><code>reprint=<byte></code></strong></strong><dd>
+<a name="OPTION_SANE"></a><p></p><dt><strong><strong><code>sane</code></strong></strong><dd>
+ Brings the terminal to something like a useful default state.
+<a name="OPTION_START"></a><p></p><dt><strong><strong><code>start=<byte></code></strong></strong><dd>
+<a name="OPTION_STOP"></a><p></p><dt><strong><strong><code>stop=<byte></code></strong></strong><dd>
+<a name="OPTION_SUSP"></a><p></p><dt><strong><strong><code>susp=<byte></code></strong></strong><dd>
+<a name="OPTION_SWTC"></a><p></p><dt><strong><strong><code>swtc=<byte></code></strong></strong><dd>
+<a name="OPTION_TAB0"></a><p></p><dt><strong><strong><code>tab0</code></strong></strong><dd>
+<a name="OPTION_TAB1"></a><p></p><dt><strong><strong><code>tab1</code></strong></strong><dd>
+<a name="OPTION_TAB2"></a><p></p><dt><strong><strong><code>tab2</code></strong></strong><dd>
+<a name="OPTION_TAB3"></a><p></p><dt><strong><strong><code>tab3</code></strong></strong><dd>
+<a name="OPTION_TABDLY"></a><p></p><dt><strong><strong><code>tabdly=<unsigned-int></code></strong></strong><dd>
+<a name="OPTION_TIME"></a><p></p><dt><strong><strong><code>time=<byte></code></strong></strong><dd>
+<a name="OPTION_TOSTOP"></a><p></p><dt><strong><strong><code>tostop=<bool></code></strong></strong><dd>
+<a name="OPTION_VT0"></a><p></p><dt><strong><strong><code>vt0</code></strong></strong><dd>
+<a name="OPTION_VT1"></a><p></p><dt><strong><strong><code>vt1</code></strong></strong><dd>
+<a name="OPTION_VTDLY"></a><p></p><dt><strong><strong><code>vtdly=<bool></code></strong></strong><dd>
+<a name="OPTION_WERASE"></a><p></p><dt><strong><strong><code>werase=<byte></code></strong></strong><dd>
+<a name="OPTION_XCASE"></a><p></p><dt><strong><strong><code>xcase=<bool></code></strong></strong><dd>
+<a name="OPTION_XTABS"></a><p></p><dt><strong><strong><code>xtabs</code></strong></strong><dd>
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_PTY"></a><em><strong>PTY option group</strong></em>
+<p>These options are intended for use with the <a href="socat.html#ADDRESS_PTY">pty</a> address
+type.
+<p><dl>
+<a name="OPTION_SYMBOLIC_LINK"></a><p></p><dt><strong><strong><code>link=<filename></code></strong></strong><dd>
+ Generates a symbolic link that points to the actual pseudo terminal
+ (pty). This might help
+ to solve the problem that ptys are generated with more or less
+ unpredictable names, making it difficult to directly access the socat
+ generated pty automatically. With this option, the user can specify a "fix"
+ point in the file hierarchy that helps him to access the actual pty
+ (<a href="socat.html#EXAMPLE_OPTION_SYMBOLIC_LINK">example</a>).
+ Beginning with <strong>socat</strong> version 1.4.3, the symbolic link is removed when
+ the address is closed (but see option <a href="socat.html#OPTION_UNLINK_CLOSE">unlink-close</a>).
+<a name="OPTION_PTY_WAIT_SLAVE"></a><p></p><dt><strong><strong><code>wait-slave</code></strong></strong><dd>
+ Blocks the open phase until a process opens the slave side of the pty.
+ Usually, socat continues after generating the pty with opening the next
+ address or with entering the transfer loop. With the wait-slave option,
+ socat waits until some process opens the slave side of the pty before
+ continuing.
+ This option only works if the operating system provides the <code>poll()</code>
+ system call. And it depends on an undocumented behaviour of pty's, so it
+ does not work on all operating systems. It has successfully been tested on
+ Linux, FreeBSD, NetBSD, and on Tru64 with openpty.
+<a name="OPTION_PTY_INTERVALL"></a><p></p><dt><strong><strong><code>pty-intervall=<seconds></code></strong></strong><dd>
+ When the <a href="socat.html#OPTION_PTY_WAIT_SLAVE">wait-slave</a> option is set, socat
+ periodically checks the HUP condition using <code>poll()</code> to find if the pty's
+ slave side has been opened. The default polling intervall is 1s. Use the
+ pty-intervall option [<a href="socat.html#TYPE_TIMEVAL">timeval</a>] to change this value.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_OPENSSL"></a><em><strong>OPENSSL option group</strong></em>
+<p>These options apply to the <a href="socat.html#ADDRESS_OPENSSL_CONNECT">openssl</a> and
+<a href="socat.html#ADDRESS_OPENSSL_LISTEN">openssl-listen</a> address types.
+<p><dl>
+<a name="OPTION_OPENSSL_CIPHERLIST"></a><p></p><dt><strong><strong><code>cipher=<cipherlist></code></strong></strong><dd>
+ Selects the list of ciphers that may be used for the connection.
+ See the man page of <code>ciphers</code>, section <strong>CIPHER LIST FORMAT</strong>, for
+ detailed information about syntax, values, and default of <cipherlist>.<br>
+ Several cipher strings may be given, separated by ':'.
+ Some simple cipher strings:
+ <dl>
+ <p></p><dt><strong>3DES</strong><dd> Uses a cipher suite with triple DES.
+ <p></p><dt><strong>MD5</strong><dd> Uses a cipher suite with MD5.
+ <p></p><dt><strong>aNULL</strong><dd> Uses a cipher suite without authentication.
+ <p></p><dt><strong>NULL</strong><dd> Does not use encryption.
+ <p></p><dt><strong>HIGH</strong><dd> Uses a cipher suite with "high" encryption.
+ </dl>
+ Note that the peer must support the selected property, or the negotiation
+ will fail.
+<a name="OPTION_OPENSSL_METHOD"></a><p></p><dt><strong><strong><code>method=<ssl-method></code></strong></strong><dd>
+ Sets the protocol version to be used. Valid strings (not case sensitive)
+ are:
+ <dl>
+ <p></p><dt><strong><code>SSLv2</code></strong><dd> Select SSL protocol version 2.
+ <p></p><dt><strong><code>SSLv3</code></strong><dd> Select SSL protocol version 3.
+ <p></p><dt><strong><code>SSLv23</code></strong><dd> Select SSL protocol version 2 or 3. This is the default when
+ this option is not provided.
+ <p></p><dt><strong><code>TLSv1</code></strong><dd> Select TLS protocol version 1.
+ </dl>
+<a name="OPTION_OPENSSL_VERIFY"></a><p></p><dt><strong><strong><code>verify=<bool></code></strong></strong><dd>
+ Controls check of the peer's certificate. Default is 1 (true). Disabling
+ verify might open your socket for everyone, making the encryption useless!
+<a name="OPTION_OPENSSL_CERTIFICATE"></a><p></p><dt><strong><strong><code>cert=<filename></code></strong></strong><dd>
+ Specifies the file with the certificate and private key for authentication.
+ The certificate must be in OpenSSL format (*.pem).
+ With openssl-listen, use of this option is strongly
+ recommended. Except with cipher aNULL, "no shared ciphers" error will
+ occur when no certificate is given.
+<a name="OPTION_OPENSSL_KEY"></a><p></p><dt><strong><strong><code>key=<filename></code></strong></strong><dd>
+ Specifies the file with the private key. The private key may be in this
+ file or in the file given with the <a href="socat.html#OPTION_OPENSSL_CERTIFICATE">cert</a> option. The party that has
+ to proof that it is the owner of a certificate needs the private key.
+<a name="OPTION_OPENSSL_DHPARAMS"></a><p></p><dt><strong><strong><code>dhparams=<filename></code></strong></strong><dd>
+ Specifies the file with the Diffie Hellman parameters. These parameters may
+ also be in the file given with the <a href="socat.html#OPTION_OPENSSL_CERTIFICATE">cert</a>
+ option in which case the dhparams option is not needed.
+<a name="OPTION_OPENSSL_CAFILE"></a><p></p><dt><strong><strong><code>cafile=<filename></code></strong></strong><dd>
+ Specifies the file with the trusted (root) authority certificates. The file
+ must be in PEM format and should contain one or more certificates. The party
+ that checks the authentication of its peer trusts only certificates that are
+ in this file.
+<a name="OPTION_OPENSSL_CAPATH"></a><p></p><dt><strong><strong><code>capath=<dirname></code></strong></strong><dd>
+ Specifies the directory with the trusted (root) certificates. The directory
+ must contain certificates in PEM format and their hashes (see OpenSSL
+ documentation)
+<a name="OPTION_OPENSSL_EGD"></a><p></p><dt><strong><strong><code>egd=<filename></code></strong></strong><dd>
+ On some systems, openssl requires an explicit source of random data. Specify
+ the socket name where an entropy gathering daemon like egd provides random
+ data, e.g. /dev/egd-pool.
+<a name="OPTION_OPENSSL_PSEUDO"></a><p></p><dt><strong><strong><code>pseudo</code></strong></strong><dd>
+ On systems where openssl cannot find an entropy source and where no entropy
+ gathering daemon can be utilized, this option activates a mechanism for
+ providing pseudo entropy. This is archieved by taking the current time in
+ microseconds for feeding the libc pseudo random number generator with an
+ initial value. openssl is then feeded with output from random() calls.<br>
+ NOTE:This mechanism is not sufficient for generation of secure keys!
+<a name="OPTION_OPENSSL_FIPS"></a><p></p><dt><strong><strong><code>fips</code></strong></strong><dd>
+ Enables FIPS mode if compiled in. For info about the FIPS encryption
+ implementation standard see <a href="http://oss-institute.org/fips-faq.html">http://oss-institute.org/fips-faq.html</a>.
+ This mode might require that the involved certificates are generated with a
+ FIPS enabled version of openssl. Setting or clearing this option on one
+ socat address affects all OpenSSL addresses of this process.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_RETRY"></a><em><strong>RETRY option group</strong></em>
+<p>Options that control retry of some system calls, especially connection
+attempts.
+<p><dl>
+<a name="OPTION_RETRY"></a><p></p><dt><strong><strong><code>retry=<num></code></strong></strong><dd>
+ Number of retries before the connection or listen attempt is aborted.
+ Default is 0, which means just one attempt.
+<a name="OPTION_INTERVALL"></a><p></p><dt><strong><strong><code>intervall=<timespec></code></strong></strong><dd>
+ Time between consecutive attempts (seconds,
+ [<a href="socat.html#TYPE_TIMESPEC">timespec</a>]). Default is 1 second.
+<a name="OPTION_FOREVER"></a><p></p><dt><strong><strong><code>forever</code></strong></strong><dd>
+ Performs an unlimited number of retry attempts.
+</dl>
+<p><dl></dl><br>
+<p><a name="GROUP_TUN"></a><em><strong>TUN option group</strong></em>
+<p>Options that control Linux TUN/TAP interface device addresses.
+<p><dl>
+<a name="OPTION_TUN_DEVICE"></a><p></p><dt><strong><strong><code>tun-device=<device-file></code></strong></strong><dd>
+ Instructs socat to take another path for the TUN clone device. Default is
+ <code>/dev/net/tun</code>.
+<a name="OPTION_TUN_NAME"></a><p></p><dt><strong><strong><code>tun-name=<if-name></code></strong></strong><dd>
+ Gives the resulting network interface a specific name instead of the system
+ generated (tun0, tun1, etc.)
+<a name="OPTION_TUN_TYPE"></a><p></p><dt><strong><strong><code>tun-type=[tun|tap]</code></strong></strong><dd>
+ Sets the type of the TUN device; use this option to generate a TAP
+ device. See the Linux docu for the difference between these types.
+ When you try to establish a tunnel between two TUN devices, their types
+ should be the same.
+<a name="OPTION_IFF_NO_PI"></a><p></p><dt><strong><strong><code>iff-no-pi</code></strong></strong><dd>
+ Sets the IFF_NO_PI flag which controls if the device includes additional
+ packet information in the tunnel.
+ When you try to establish a tunnel between two TUN devices, these flags
+ should have the same values.
+<a name="OPTION_IFF_UP"></a><p></p><dt><strong><strong><code>iff-up</code></strong></strong><dd>
+ Sets the TUN network interface status UP. Strongly recommended.
+<a name="OPTION_IFF_BROADCAST"></a><p></p><dt><strong><strong><code>iff-broadcast</code></strong></strong><dd>
+ Sets the BROADCAST flag of the TUN network interface.
+<a name="OPTION_IFF_DEBUG"></a><p></p><dt><strong><strong><code>iff-debug</code></strong></strong><dd>
+ Sets the DEBUG flag of the TUN network interface.
+<a name="OPTION_IFF_LOOPBACK"></a><p></p><dt><strong><strong><code>iff-loopback</code></strong></strong><dd>
+ Sets the LOOPBACK flag of the TUN network interface.
+<a name="OPTION_IFF_POINTOPOINT"></a><p></p><dt><strong><strong><code>iff-pointopoint</code></strong></strong><dd>
+ Sets the POINTOPOINT flag of the TUN device.
+<a name="OPTION_IFF_NOTRAILERS"></a><p></p><dt><strong><strong><code>iff-notrailers</code></strong></strong><dd>
+ Sets the NOTRAILERS flag of the TUN device.
+<a name="OPTION_IFF_RUNNING"></a><p></p><dt><strong><strong><code>iff-running</code></strong></strong><dd>
+ Sets the RUNNING flag of the TUN device.
+<a name="OPTION_IFF_NOARP"></a><p></p><dt><strong><strong><code>iff-noarp</code></strong></strong><dd>
+ Sets the NOARP flag of the TUN device.
+<a name="OPTION_IFF_PROMISC"></a><p></p><dt><strong><strong><code>iff-promisc</code></strong></strong><dd>
+ Sets the PROMISC flag of the TUN device.
+<a name="OPTION_IFF_ALLMULTI"></a><p></p><dt><strong><strong><code>iff-allmulti</code></strong></strong><dd>
+ Sets the ALLMULTI flag of the TUN device.
+<a name="OPTION_IFF_MASTER"></a><p></p><dt><strong><strong><code>iff-master</code></strong></strong><dd>
+ Sets the MASTER flag of the TUN device.
+<a name="OPTION_IFF_SLAVE"></a><p></p><dt><strong><strong><code>iff-slave</code></strong></strong><dd>
+ Sets the SLAVE flag of the TUN device.
+<a name="OPTION_IFF_MULTICAST"></a><p></p><dt><strong><strong><code>iff-multicast</code></strong></strong><dd>
+ Sets the MULTICAST flag of the TUN device.
+<a name="OPTION_IFFPORTSEL_"></a><p></p><dt><strong><strong><code>iff-portsel</code></strong></strong><dd>
+ Sets the PORTSEL flag of the TUN device.
+<a name="OPTION_IFF_AUTOMEDIA"></a><p></p><dt><strong><strong><code>iff-automedia</code></strong></strong><dd>
+ Sets the AUTOMEDIA flag of the TUN device.
+<a name="OPTION_IFF_DYNAMIC"></a><p></p><dt><strong><strong><code>iff-dynamic</code></strong></strong><dd>
+ Sets the DYNAMIC flag of the TUN device.
+</dl>
+<p><dl></dl><br>
+<p><a name="VALUES"></a>
+<h2>DATA VALUES</h2>
+
+<p>This section explains the different data types that address parameters and
+address options can take.
+<p><dl>
+<a name="TYPE_ADDRESS_RANGE"></a><p></p><dt><strong>address-range</strong><dd>
+ Is currently only implemented for IPv4 and IPv6. See address-option
+ <a href="socat.html#OPTION_RANGE">`range'</a>
+<a name="TYPE_BOOL"></a><p></p><dt><strong>bool</strong><dd>
+ "0" or "1"; if value is omitted, "1" is taken.
+<a name="TYPE_BYTE"></a><p></p><dt><strong>byte</strong><dd>
+ An unsigned int number, read with <code>strtoul()</code>, lower or equal to
+ <code>UCHAR_MAX</code>.
+<a name="TYPE_COMMAND_LINE"></a><p></p><dt><strong>command-line</strong><dd>
+ A string specifying a program name and its arguments, separated by single
+ spaces.
+<a name="TYPE_DATA"></a><p></p><dt><strong>data</strong><dd>
+ A raw data specification following <em>dalan</em> syntax. The only documented
+ form is a string starting with 'x' followed by an even number of hex digits.
+<a name="TYPE_DIRECTORY"></a><p></p><dt><strong>directory</strong><dd>
+ A string with usual UN*X directory name semantics.
+<a name="TYPE_FACILITY"></a><p></p><dt><strong>facility</strong><dd>
+ The name of a syslog facility in lower case characters.
+<a name="TYPE_FDNUM"></a><p></p><dt><strong>fdnum</strong><dd>
+ An unsigned int type, read with <code>strtoul()</code>, specifying a UN*X file
+ descriptor.
+<a name="TYPE_FILENAME"></a><p></p><dt><strong>filename</strong><dd>
+ A string with usual UN*X filename semantics.
+<a name="TYPE_GROUP"></a><p></p><dt><strong>group</strong><dd>
+ If the first character is a decimal digit, the value is read with
+ <code>strtoul()</code> as unsigned integer specifying a group id. Otherwise, it
+ must be an existing group name.
+<a name="TYPE_INT"></a><p></p><dt><strong>int</strong><dd>
+ A number following the rules of the <code>strtol()</code> function with base
+ "0", i.e. decimal number, octal number with leading "0", or hexadecimal
+ number with leading "0x". The value must fit into a C int.
+<a name="TYPE_INTERFACE"></a><p></p><dt><strong>interface</strong><dd>
+ A string specifying the device name of a network interface, e.g. "eth0".
+<a name="TYPE_IP_ADDRESS"></a><p></p><dt><strong>IP address</strong><dd>
+ 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
+ IPv6 address.<br>
+ Examples: 127.0.0.1, [::1], www.dest-unreach.org, dns1
+<a name="TYPE_IPV4_ADDRESS"></a><p></p><dt><strong>IPv4 address</strong><dd>
+ An IPv4 address in numbers-and-dots notation or a hostname that resolves to
+ an IPv4 address.<br>
+ Examples: 127.0.0.1, www.dest-unreach.org, dns2
+<a name="TYPE_IPV6_ADDRESS"></a><p></p><dt><strong>IPv6 address</strong><dd>
+ An iPv6 address in hexnumbers-and-colons notation enclosed in brackets, or a
+ hostname that resolves to an IPv6 address.<br>
+ Examples: [::1], [1234:5678:9abc:def0:1234:5678:9abc:def0],
+ ip6name.domain.org
+<a name="TYPE_LONG"></a><p></p><dt><strong>long</strong><dd>
+ A number read with <code>strtol()</code>. The value must fit into a C long.
+<a name="TYPE_LONGLONG"></a><p></p><dt><strong>long long</strong><dd>
+ A number read with <code>strtoll()</code>. The value must fit into a C long long.
+<a name="TYPE_OFF"></a><p></p><dt><strong>off_t</strong><dd>
+ An implementation dependend signed number, usually 32 bits, read with strtol
+ or strtoll.
+<a name="TYPE_OFF64"></a><p></p><dt><strong>off64_t</strong><dd>
+ An implementation dependend signed number, usually 64 bits, read with strtol
+ or strtoll.
+<a name="TYPE_MODE_T"></a><p></p><dt><strong>mode_t</strong><dd>
+ An unsigned integer, read with <code>strtoul()</code>, specifying mode (permission)
+ bits.
+<a name="TYPE_PID_T"></a><p></p><dt><strong>pid_t</strong><dd>
+ A number, read with <code>strtol()</code>, specifying a process id.
+<a name="TYPE_PORT"></a><p></p><dt><strong>port</strong><dd>
+ A uint16_t (16 bit unsigned number) specifying a TCP or UDP port, read
+ with <code>strtoul()</code>.
+<a name="TYPE_PROTOCOL"></a><p></p><dt><strong>protocol</strong><dd>
+ An unsigned 8 bit number, read with <code>strtoul()</code>.
+<a name="TYPE_SIZE_T"></a><p></p><dt><strong>size_t</strong><dd>
+ An unsigned number with size_t limitations, read with <code>strtoul</code>.
+<a name="TYPE_SOCKNAME"></a><p></p><dt><strong>sockname</strong><dd>
+ A socket address. See address-option <a href="socat.html#OPTION_BIND">`bind'</a>
+<a name="TYPE_STRING"></a><p></p><dt><strong>string</strong><dd>
+ A sequence of characters, not containing '\0' and, depending on
+ the position within the command line, ':', ',', or "!!". Note
+ that you might have to escape shell meta characters in the command line.
+<a name="TYPE_TCP_SERVICE"></a><p></p><dt><strong>TCP service</strong><dd>
+ A service name, not starting with a digit, that is resolved by
+ <code>getservbyname()</code>, or an unsigned int 16 bit number read with
+ <code>strtoul()</code>.
+<a name="TYPE_TIMEVAL"></a><p></p><dt><strong>timeval</strong><dd>
+ A double float specifying seconds; the number is mapped into a
+ struct timeval, consisting of seconds and microseconds.
+<a name="TYPE_TIMESPEC"></a><p></p><dt><strong>timespec</strong><dd>
+ A double float specifying seconds; the number is mapped into a
+ struct timespec, consisting of seconds and nanoseconds.
+<a name="TYPE_UDP_SERVICE"></a><p></p><dt><strong>UDP service</strong><dd>
+ A service name, not starting with a digit, that is resolved by
+ <code>getservbyname()</code>, or an unsigned int 16 bit number read with
+ <code>strtoul()</code>.
+<a name="TYPE_UNSIGNED_INT"></a><p></p><dt><strong>unsigned int</strong><dd>
+ A number read with <code>strtoul()</code>. The value must fit into a C unsigned
+ int.
+<a name="TYPE_USER"></a><p></p><dt><strong>user</strong><dd>
+ If the first character is a decimal digit, the value is read with
+ <code>strtoul()</code> as unsigned integer specifying a user id. Otherwise, it must
+ be an existing user name.
+</dl>
+<p><a name="EXAMPLES"></a>
+<h2>EXAMPLES</h2>
+
+<p><dl>
+<p><a name="EXAMPLE_ADDRESS_TCP4_CONNECT"></a>
+<p></p><dt><strong><strong><code>socat - TCP4:www.domain.org:80</code></strong></strong><dd>
+<p>Transfers data between <a href="socat.html#ADDRESS_STDIO">STDIO</a> (-) and a
+<a href="socat.html#ADDRESS_TCP4_CONNECT">TCP4</a> 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
+close the relay with ^D or abort it with ^C.
+<p><a name="EXAMPLE_ADDRESS_READLINE"></a>
+<a name="EXAMPLE_OPTION_HISTORY"></a>
+
+
+
+
+<p><dt><code><strong>socat -d -d READLINE,history=$HOME/.http_history \</strong><br>
+<strong>TCP4:www.domain.org:www,crnl</strong></code><dd>
+<p>This is similar to the previous example, but you can edit the current line in a
+bash like manner (<a href="socat.html#ADDRESS_READLINE">READLINE</a>) and use the
+<a href="socat.html#OPTION_HISTORY">history</a> file .http_history; <strong>socat</strong>
+prints messages about progress (<a href="socat.html#option_d_d">-d -d</a>). The port is specified by service name
+(www), and correct network line termination characters (<a href="socat.html#OPTION_CRNL">crnl</a>) instead of NL
+are used.
+<p><a name="EXAMPLE_ADDRESS_TCP4_LISTEN"></a>
+<p></p><dt><strong><strong><code>socat TCP4-LISTEN:www TCP4:www.domain.org:www</code></strong></strong><dd>
+<p>Installs a simple TCP port forwarder. With
+<a href="socat.html#ADDRESS_TCP4_LISTEN">TCP4-LISTEN</a> it listens on local port "www" until a
+connection comes in, accepts it, then connects to the remote host
+(<a href="socat.html#ADDRESS_TCP4_CONNECT">TCP4</a>) and starts data transfer. It will not accept a
+second connection.
+<p><a name="EXAMPLE_OPTION_BIND_TCP4"></a>
+<a name="EXAMPLE_OPTION_REUSEADDR"></a>
+<a name="EXAMPLE_OPTION_FORK"></a>
+<a name="EXAMPLE_OPTION_SUBSTUSER"></a>
+<a name="EXAMPLE_OPTION_RANGE"></a>
+
+
+
+
+<p><dt><code><strong>socat -d -d -lmlocal2 \</strong><br>
+<strong>TCP4-LISTEN:80,bind=myaddr1,su=nobody,fork,range=10.0.0.0/8,reuseaddr \</strong><br>
+<strong>TCP4:www.domain.org:80,bind=myaddr2</strong></code><dd>
+<p>TCP port forwarder, each side bound to another local IP address
+(<a href="socat.html#OPTION_BIND">bind</a>). This example handles an almost
+arbitrary number of parallel or consecutive connections by
+<a href="socat.html#OPTION_FORK">fork</a>'ing a new
+process after each <code>accept()</code>. It provides a little security by
+<a href="socat.html#OPTION_SUBSTUSER">su</a>'ing to user
+nobody after forking; it only permits connections from the private 10 network (<a href="socat.html#OPTION_RANGE">range</a>);
+due to <a href="socat.html#OPTION_REUSEADDR">reuseaddr</a>, it allows immediate restart after master process's
+termination, even if some child sockets are not completely shut down.
+With <a href="socat.html#option_lm">-lmlocal2</a>, socat logs to stderr until successfully
+reaching the accept loop. Further logging is directed to syslog with facility
+local2.
+<p><a name="EXAMPLE_ADDRESS_EXEC"></a>
+<a name="EXAMPLE_OPTION_TCPWRAPPERS"></a>
+<a name="EXAMPLE_OPTION_CHROOT"></a>
+<a name="EXAMPLE_OPTION_SUBSTUSER_DELAYED"></a>
+<a name="EXAMPLE_OPTION_PTY"></a>
+<a name="EXAMPLE_OPTION_STDERR"></a>
+
+
+
+
+<p><dt><code><strong>socat TCP4-LISTEN:5555,fork,tcpwrap=script \</strong><br>
+<strong>EXEC:/bin/myscript,chroot=/home/sandbox,su-d=sandbox,pty,stderr</strong></code><dd>
+<p>A simple server that accepts connections
+(<a href="socat.html#ADDRESS_TCP4_LISTEN">TCP4-LISTEN</a>) and <a href="socat.html#OPTION_FORK">fork</a>'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
+/etc/hosts.allow and /etc/hosts.deny, otherwise it is refused access (see "man
+5 hosts_access").
+For <a href="socat.html#ADDRESS_EXEC">EXEC</a>'uting the program, the child process
+<a href="socat.html#OPTION_CHROOT">chroot</a>'s
+to <strong>/home/sandbox</strong>, <a href="socat.html#OPTION_SUBSTUSER">su</a>'s to user sandbox, and then starts
+the program <strong>/home/sandbox/bin/myscript</strong>. <strong>Socat</strong> and
+myscript communicate via a pseudo tty (<a href="socat.html#OPTION_PTY">pty</a>); myscript's
+<a href="socat.html#OPTION_STDERR">stderr</a> is redirected to stdout,
+so its error messages are transferred via <strong>socat</strong> to the connected client.
+<p><a name="EXAMPLE_OPTION_FDIN"></a>
+<a name="EXAMPLE_OPTION_FDOUT"></a>
+<a name="EXAMPLE_OPTION_CRNL"></a>
+<a name="EXAMPLE_OPTION_MSS"></a>
+
+
+
+
+<p><dt><code><strong>socat EXEC:"mail.sh target@domain.com",fdin=3,fdout=4 \</strong><br>
+<strong>TCP4:mail.relay.org:25,crnl,bind=alias1.server.org,mss=512</strong></code><dd>
+<p><strong>mail.sh</strong> is a shell script, distributed with <strong>socat</strong>, that implements a
+simple
+SMTP client. It is programmed to "speak" SMTP on its FDs 3 (in) and 4 (out).
+The <a href="socat.html#OPTION_FDIN">fdin</a> and <a href="socat.html#OPTION_FDOUT">fdout</a> options tell <strong>socat</strong>
+to use these FDs for communication with
+the program. Because mail.sh inherits stdin and stdout while <strong>socat</strong> does not
+use them, the script can read a
+mail body from stdin. <strong>Socat</strong> makes alias1 your local source address
+(<a href="socat.html#OPTION_BIND">bind</a>), cares for correct network line termination
+(<a href="socat.html#OPTION_CRNL">crnl</a>) and sends
+at most 512 data bytes per packet (<a href="socat.html#OPTION_MSS">mss</a>).
+<p><a name="EXAMPLE_ADDRESS_GOPEN"></a>
+<a name="EXAMPLE_OPTION_RAW"></a>
+<a name="EXAMPLE_OPTION_ECHO"></a>
+<p></p><dt><strong><strong><code>socat - /dev/ttyS0,raw,echo=0,crnl</code></strong></strong><dd>
+<p>Opens an interactive connection via the serial line, e.g. for talking with a
+modem. <a href="socat.html#OPTION_RAW">raw</a> and <a href="socat.html#OPTION_ECHO">echo</a> set ttyS0's terminal
+parameters to practicable values, <a href="socat.html#OPTION_CRNL">crnl</a>
+converts to correct newline characters. Consider using
+<a href="socat.html#ADDRESS_READLINE">READLINE</a> instead of `-'.
+<p><a name="EXAMPLE_ADDRESS_UNIX_LISTEN"></a>
+<a name="EXAMPLE_ADDRESS_SOCKS4"></a>
+<a name="EXAMPLE_OPTION_SOCKSUSER"></a>
+<a name="EXAMPLE_OPTION_SOURCEPORT"></a>
+
+
+
+
+<p><dt><code><strong>socat UNIX-LISTEN:/tmp/.X11-unix/X1,fork \</strong><br>
+<strong>SOCKS4:host.victim.org:127.0.0.1:6000,socksuser=nobody,sourceport=20</strong></code><dd>
+<p>With <a href="socat.html#ADDRESS_UNIX_LISTEN">UNIX-LISTEN</a>, <strong>socat</strong> opens a listening
+UNIX domain socket <strong>/tmp/.X11-unix/X1</strong>. This path corresponds
+to local XWindow display :1 on your machine, so XWindow client connections to
+DISPLAY=:1 are accepted. <strong>Socat</strong> then speaks with
+the <a href="socat.html#ADDRESS_SOCKS4">SOCKS4</a> server host.victim.org that might permit
+<a href="socat.html#OPTION_SOURCEPORT">sourceport</a> 20 based connections due to an FTP related
+weakness in its static IP filters. <strong>Socat</strong>
+pretends to be invoked by <a href="socat.html#OPTION_SOCKSUSER">socksuser</a> nobody, and
+requests to be connected to
+loopback port 6000 (only weak sockd configurations will allow this). So we get
+a connection to the victims XWindow server and, if it does not require MIT
+cookies or Kerberos authentication, we can start work. Please note that there
+can only be one connection at a time, because TCP can establish only one
+session with a given set of addresses and ports.
+<p><a name="EXAMPLE_option_u"></a>
+<a name="EXAMPLE_OPTION_IGNOREEOF"></a>
+<p></p><dt><strong><strong><code>socat -u /tmp/readdata,seek-end=0,ignoreeof -</code></strong></strong><dd>
+<p>This is an example for unidirectional data transfer
+(<a href="socat.html#option_u">-u</a>). <strong>Socat</strong> transfers data
+from file /tmp/readdata (implicit address <a href="socat.html#ADDRESS_GOPEN">GOPEN</a>), starting
+at its current end (<a href="socat.html#OPTION_SEEK_END">seek-end</a>=0 lets <strong>socat</strong> start
+reading at current end of file; use <a href="socat.html#OPTION_SEEK">seek</a>=0 or no
+seek option to first read the existing data) in a "tail -f" like mode
+(<a href="socat.html#OPTION_IGNOREEOF">ignoreeof</a>). The "file"
+might also be a listening UNIX domain socket (do not use a seek option then).
+<p><a name="EXAMPLE_OPTION_SETSID"></a>
+<a name="EXAMPLE_OPTION_CTTY"></a>
+
+
+
+
+<p><dt><code><strong>(echo PASSWORD; sleep 5; echo ls; sleep 1) |</strong><br>
+<strong>socat - EXEC:'ssh -l user server',pty,setsid,ctty</strong></code><dd>
+<p><a href="socat.html#ADDRESS_EXEC">EXEC</a>'utes an ssh session to server. Uses a <a href="socat.html#OPTION_PTY">pty</a> for communication between <strong>socat</strong> and
+ssh, makes it ssh's controlling tty (<a href="socat.html#OPTION_CTTY">ctty</a>),
+and makes this pty the owner of
+a new process group (<a href="socat.html#OPTION_SETSID">setsid</a>), so ssh accepts the password from <strong>socat</strong>.
+<p><a name="EXAMPLE_ADDRESS_OPEN"></a>
+<a name="EXAMPLE_OPTION_CREAT"></a>
+<a name="EXAMPLE_OPTION_APPEND"></a>
+
+
+
+
+<p><dt><code><strong>socat -u TCP4-LISTEN:3334,reuseaddr,fork \</strong><br>
+<strong>OPEN:/tmp/in.log,creat,append</strong></code><dd>
+<p>Implements a simple network based message collector.
+For each client connecting to port 3334, a new child process is generated (option <a href="socat.html#OPTION_FORK">fork</a>).
+All data sent by the clients are <a href="socat.html#OPTION_APPEND">append</a>'ed to the file /tmp/in.log.
+If the file does not exist, socat <a href="socat.html#OPTION_CREAT">creat</a>'s it.
+Option <a href="socat.html#OPTION_REUSEADDR">reuseaddr</a> allows immediate restart of the server
+process.
+<p>
+
+<p><a name="EXAMPLE_OPTION_NOECHO"></a>
+<p></p><dt><strong><strong><code>socat READLINE,noecho='[Pp]assword:' EXEC:'ftp ftp.server.com',pty,setsid,ctty</code></strong></strong><dd>
+<p>Wraps a command line history (<a href="socat.html#ADDRESS_READLINE">READLINE</a>) around the <a href="socat.html#ADDRESS_EXEC">EXEC</a>'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!
+ <a href="socat.html#OPTION_PTY">pty</a> is required to have ftp issue a prompt.
+Nevertheless, there may occur some confusion with the password and FTP
+prompts.
+<p><a name="EXAMPLE_ADDRESS_PTY"></a>
+<a name="EXAMPLE_OPTION_SYMBOLIC_LINK"></a>
+<a name="EXAMPLE_OPTION_WAITSLAVE"></a>
+<a name="EXAMPLE_OPTION_NONBLOCK"></a>
+(<strong><code>socat PTY,link=$HOME/dev/vmodem0,raw,echo=0,waitslave EXEC:'"ssh modemserver.us.org socat - /dev/ttyS0,nonblock,raw,echo=0"'</code></strong>)
+<p>Generates a pseudo terminal
+device (<a href="socat.html#ADDRESS_PTY">PTY</a>) on the client that can be reached under the
+symbolic <a href="socat.html#OPTION_SYMBOLIC_LINK">link</a> <strong>$HOME/dev/vmodem0</strong>.
+An application that expects a serial line or modem
+can be configured to use <strong>$HOME/dev/vmodem0</strong>; its traffic will be directed
+to a modemserver via ssh where another socat instance links it with
+<strong>/dev/ttyS0</strong>.
+<p>
+
+
+
+<p><dt><code><strong>socat TCP4-LISTEN:2022,reuseaddr,fork \</strong><br>
+<strong>PROXY:proxy:www.domain.org:22,proxyport=3128,proxyauth=user:pass</strong></code><dd>
+<p>starts a forwarder that accepts connections on port 2022, and directs them
+through the <a href="socat.html#ADDRESS_PROXY_CONNECT">proxy</a> daemon listening on port 3128
+(<a href="socat.html#OPTION_PROXYPORT">proxyport</a>) on host proxy, using the
+CONNECT method, where they are authenticated as "user" with "pass" (<a href="socat.html#OPTION_PROXY_AUTHORIZATION">proxyauth</a>). The proxy
+should establish connections to host www.domain.org on port 22 then.
+<p><a name="EXAMPLE_ADDRESS_OPENSSL_CONNECT"></a>
+<p></p><dt><strong><strong><code>socat - SSL:server:4443,cafile=server.crt,cert=client.pem</code></strong></strong><dd>
+<p>is an OpenSSL client that tries to establish a secure connection to an SSL
+server. Option <a href="socat.html#OPTION_OPENSSL_CAFILE">cafile</a> specifies a file that
+contains trust certificates: we trust the server only when it presents one of
+these certificates and proofs that it owns the related private key.
+Otherwise the connection is terminated.
+With <a href="socat.html#OPTION_OPENSSL_CERTIFICATE">cert</a> a file containing the client certificate
+and the associated private key is specified. This is required in case the
+server wishes a client authentication; many Internet servers do not.<br>
+The first address ('-') can be replaced by almost any other socat address.
+<p><a name="EXAMPLE_ADDRESS_OPENSSL_LISTEN"></a>
+<p></p><dt><strong><strong><code>socat SSL-LISTEN:4443,reuseaddr,pf=ip4,fork,cert=server.pem,cafile=client.crt PIPE</code></strong></strong><dd>
+<p>is an OpenSSL server that accepts TCP connections, presents the certificate
+from the file server.pem and forces the client to present a certificate that is
+verified against cafile.crt.<br>
+The second address ('PIPE') can be replaced by almost any other socat
+address.<br>
+For instructions on generating and distributing OpenSSL keys and certificates
+see the additional socat docu <code>socat-openssl.txt</code>.
+<p><p></p><dt><strong><strong><code>echo |socat -u - file:/tmp/bigfile,create,largefile,seek=100000000000</code></strong></strong><dd>
+<p>creates a 100GB sparse file; this requires a file system type that
+supports this (ext2, ext3, reiserfs, jfs; not minix, vfat). The operation of
+writing 1 byte might take long (reiserfs: some minutes; ext2: "no" time), and
+the resulting file can consume some disk space with just its inodes (reiserfs:
+2MB; ext2: 16KB).
+<p><p></p><dt><strong><strong><code>socat tcp-l:7777,reuseaddr,fork system:'filan -i 0 -s >&2',nofork</code></strong></strong><dd>
+<p>listens for incoming TCP connections on port 7777. For each accepted
+connection, invokes a shell. This shell has its stdin and stdout directly
+connected to the TCP socket (<a href="socat.html#OPTION_NOFORK">nofork</a>). The shell starts filan and lets it print the socket addresses to
+stderr (your terminal window).
+<p><p></p><dt><strong><strong><code>echo -e "\0\14\0\0\c" |socat -u - file:/usr/bin/squid.exe,seek=0x00074420</code></strong></strong><dd>
+<p>functions as primitive binary editor: it writes the 4 bytes 000 014 000 000 to
+the executable /usr/bin/squid at offset 0x00074420 (this is a real world patch
+to make the squid executable from Cygwin run under Windows, actual per May 2004).
+<p><p></p><dt><strong><strong><code>socat - tcp:www.blackhat.org:31337,readbytes=1000</code></strong></strong><dd>
+<p>connects to an unknown service and prevents being flooded.
+<p><a name="EXAMPLE_END_CLOSE"></a>
+<p></p><dt><strong><strong><code>socat -U TCP:target:9999,end-close TCP-L:8888,reuseaddr,fork</code></strong></strong><dd>
+<p>merges data arriving from different TCP streams on port 8888 to just one stream
+to target:9999. The <a href="socat.html#OPTION_END_CLOSE">end-close</a> option prevents the child
+processes forked off by the second address from terminating the shared
+connection to 9999 (close(2) just unlinks the inode which stays active as long
+as the parent process lives; shutdown(2) would actively terminate the
+connection).
+<p><a name="EXAMPLE_ADDRESS_UDP4_BROADCAST_CLIENT"></a>
+<p></p><dt><strong><strong><code>socat - UDP4-DATAGRAM:192.168.1.0:123,sp=123,broadcast,range=192.168.1.0/24</code></strong></strong><dd>
+<p>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.
+<p><a name="EXAMPLE_ADDRESS_IP4_BROADCAST_CLIENT"></a>
+<p></p><dt><strong><strong><code>socat - IP4-DATAGRAM:255.255.255.255:44,broadcast,range=10.0.0.0/8</code></strong></strong><dd>
+<p>sends a broadcast to the local network(s) using protocol 44. Accepts replies
+from the private address range only.
+<p><a name="EXAMPLE_ADDRESS_UDP4_MULTICAST"></a>
+<p></p><dt><strong><strong><code>socat - UDP4-DATAGRAM:224.255.0.1:6666,bind=:6666,ip-add-membership=224.255.0.1:eth0</code></strong></strong><dd>
+<p>transfers data from stdin to the specified multicast address using UDP. Both
+local and remote ports are 6666. Tells the interface eth0 to also accept
+multicast packets of the given group. Multiple hosts on the local network can
+run this command, so all data sent by any of the hosts will be received
+by all the other ones. Note that there are many possible reasons for failure,
+including IP-filters, routing issues, wrong interface selection by the
+operating system, bridges, or a badly configured switch.
+<p><a name="EXAMPLE_ADDRESS_TUN"></a>
+<p></p><dt><strong><strong><code>socat TCP:host2:4443 TUN:192.168.255.1/24,up</code></strong></strong><dd>
+<p>establishes one side of a virtual (but not private!) network with host2 where a
+similar process might run, with TCP-L and tun address 192.168.255.2. They
+can reach each other using the addresses 192.168.255.1 and
+192.168.255.2. Substitute the TCP link with an SSL connection protected by
+client and server authentication (see OpenSSL
+<a href="socat.html#EXAMPLE_ADDRESS_OPENSSL_CONNECT">client</a> and
+<a href="socat.html#EXAMPLE_ADDRESS_OPENSSL_LISTEN">server</a>).
+<p></dl>
+<p><a name="DIAGNOSTICS"></a>
+<h2>DIAGNOSTICS</h2>
+
+<p><strong>Socat</strong> uses a logging mechanism that allows to filter messages by severity. The
+severities provided are more or less compatible to the appropriate syslog
+priority. With one or up to four occurrences of the -d command line option, the
+lowest priority of messages that are issued can be selected. Each message
+contains a single uppercase character specifying the messages severity (one of
+F, E, W, N, I, or D)
+<p><dl>
+<p></p><dt><strong>FATAL:</strong><dd> Conditions that require unconditional and immediate program termination.
+<p></p><dt><strong>ERROR:</strong><dd> Conditions that prevent proper program processing. Usually the
+program is terminated (see <a href="socat.html#option_s">option -s</a>).
+<p></p><dt><strong>WARNING:</strong><dd> Something did not function correctly or is in a state where
+correct further processing cannot be guaranteed, but might be possible.
+<p></p><dt><strong>NOTICE:</strong><dd> Interesting actions of the program, e.g. for supervising <strong>socat</strong> in some kind of server mode.
+<p></p><dt><strong>INFO:</strong><dd> Description of what the program does, and maybe why it
+happens. Allows to monitor the lifecycles of file descriptors.
+<p></p><dt><strong>DEBUG:</strong><dd> Description of how the program works, all system or library calls and their results.
+</dl>
+<p>Log messages can be written to stderr, to a file, or to syslog.
+<p>On exit, <strong>socat</strong> gives status 0 if it terminated due to EOF or inactivity
+timeout, with a positive value on error, and with a negative value on fatal
+error.
+<p><a name="FILES"></a>
+<h2>FILES</h2>
+
+<p>/usr/bin/socat <br>
+/usr/bin/filan <br>
+/usr/bin/procan
+<p><a name="ENVIRONMENT_VARIABLES"></a>
+<h2>ENVIRONMENT VARIABLES</h2>
+
+<p><dl>
+<p></p><dt><strong><strong>SOCAT_DEFAULT_LISTEN_IP</strong></strong><dd> (Values 4 or 6) Sets the IP version to be used
+for listen, recv, and recvfrom addresses if no <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a>
+(protocol-family) option is given. Is overridden by socat options
+<a href="socat.html#option_4">-4</a> or <a href="socat.html#option_6">-6</a>.
+<p><p></p><dt><strong><strong>SOCAT_PREFERRED_RESOLVE_IP</strong></strong><dd> (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 <a href="socat.html#OPTION_PROTOCOL_FAMILY">pf</a> (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.
+<p><p></p><dt><strong><strong>SOCAT_FORK_WAIT</strong></strong><dd> Specifies the time (seconds) to sleep the parent and
+child processes after successful fork(). Useful for debugging.
+<p><p></p><dt><strong><strong>HOSTNAME</strong></strong><dd> Is used to determine the hostname for logging (see
+<a href="socat.html#option_lh">-lh</a>).
+<p><p></p><dt><strong><strong>LOGNAME</strong></strong><dd> Is used as name for the socks client user name if no
+<a href="socat.html#OPTION_SOCKSUSER">socksuser</a> is given.<br>
+With options <a href="socat.html#OPTION_SUBSTUSER">su</a> and
+<a href="socat.html#OPTION_SUBSTUSER_DELAYED">su-d</a>, LOGNAME is set to the given user name.
+<p><p></p><dt><strong><strong>USER</strong></strong><dd> Is used as name for the socks client user name if no
+<a href="socat.html#OPTION_SOCKSUSER">socksuser</a> is given and LOGNAME is empty.<br>
+With options <a href="socat.html#OPTION_SUBSTUSER">su</a> and
+<a href="socat.html#OPTION_SUBSTUSER_DELAYED">su-d</a>, USER is set to the given user name.
+<p><p></p><dt><strong><strong>SHELL</strong></strong><dd>
+With options <a href="socat.html#OPTION_SUBSTUSER">su</a> and
+<a href="socat.html#OPTION_SUBSTUSER_DELAYED">su-d</a>, SHELL is set to the login shell of the
+given user.
+<p><p></p><dt><strong><strong>PATH</strong></strong><dd>
+Can be set with option <a href="socat.html#OPTION_PATH">path</a> for <a href="socat.html#ADDRESS_EXEC">exec</a> and
+<a href="socat.html#ADDRESS_SYSTEM">system</a> addresses.
+<p><p></p><dt><strong><strong>HOME</strong></strong><dd>
+With options <a href="socat.html#OPTION_SUBSTUSER">su</a> and
+<a href="socat.html#OPTION_SUBSTUSER_DELAYED">su-d</a>, HOME is set to the home directory of the
+given user.
+<p></dl>
+<p><a name="CREDITS"></a>
+<h2>CREDITS</h2>
+
+<p>The work of the following groups and organizations was invaluable for this
+project:
+<p>The <em>FSF</em> (GNU, <a href="http://www.fsf.org/">http://www.fsf.org/</a> project
+with their free and portable development software and
+lots of other useful tools and libraries.
+<p>The <em>Linux developers community</em> (<a href="http://www.linux.org/">http://www.linux.org/</a>) for providing a free, open source operating
+system.
+<p>The <em>Open Group</em> (<a href="http://www.unix-systems.org/">http://www.unix-systems.org/</a>) for making their
+standard specifications available on the Internet for free.
+<p><a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<p>This man page describes version 1.6.0 of <strong>socat</strong>.
+<p><a name="BUGS"></a>
+<h2>BUGS</h2>
+
+<p>Addresses cannot be nested, so a single socat process cannot, e.g., drive ssl
+over socks.
+<p>Address option ftruncate without value uses default 1 instead of 0.
+<p>Verbose modes (-x and/or -v) display line termination characters inconsistently
+when address options cr or crnl are used: They show the data <em>after</em>
+conversion in either direction.
+<p>The data transfer blocksize setting (-b) is ignored with address readline.
+<p>Send bug reports to <socat@dest-unreach.org>
+<p><a name="SEEALSO"></a>
+<h2>SEE ALSO</h2>
+
+<p>
+nc(1), netcat6(1), sock(1), rinetd(8), cage(1), socks.conf(5), openssl(1),
+stunnel(8), pty(1), rlwrap(1), setsid(1)
+<p><strong>Socat</strong> home page <a href="http://www.dest-unreach.org/socat/">http://www.dest-unreach.org/socat/</a>
+<p><a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<p>Gerhard Rieger <rieger@dest-unreach.org>
+</body>
+</html>
diff --git a/doc/socat.yo b/doc/socat.yo
new file mode 100644
index 0000000..49bacab
--- /dev/null
+++ b/doc/socat.yo
@@ -0,0 +1,3026 @@
+COMMENT($Id: socat.yo,v 1.99 2007/03/06 20:56:24 gerhard Exp $)
+mailto(socat@dest-unreach.org)
+
+def(unix)(0)(UN*X)
+def(unixdomain)(0)(UNIX domain)
+def(socat)(0)(bf(socat))
+def(Socat)(0)(bf(Socat))
+def(filan)(0)(bf(filan))
+def(Filan)(0)(bf(Filan))
+def(procan)(0)(bf(procan))
+def(Procan)(0)(bf(Procan))
+
+manpage(socat)(1)(March 2007)(socat)()
+
+whenhtml(
+label(CONTENTS)
+manpagesection(CONTENTS)
+link(NAME)(NAME)nl()
+link(SYNOPSIS)(SYNOPSIS)nl()
+link(DESCRIPTION)(DESCRIPTION)nl()
+link(OPTIONS)(OPTIONS)nl()
+link(ADDRESS SPECIFICATIONS)(ADDRESS_SPECIFICATIONS)nl()
+link(ADDRESS TYPES)(ADDRESS_TYPES)nl()
+link(ADDRESS OPTIONS)(ADDRESS_OPTIONS)nl()
+link(DATA VALUES)(VALUES)nl()
+link(EXAMPLES)(EXAMPLES)nl()
+link(DIAGNOSTICS)(DIAGNOSTICS)nl()
+link(FILES)(FILES)nl()
+link(ENVIRONMENT VARIABLES)(ENVIRONMENT_VARIABLES)nl()
+link(CREDITS)(CREDITS)nl()
+link(VERSION)(VERSION)nl()
+link(BUGS)(BUGS)nl()
+link(SEE ALSO)(SEEALSO)nl()
+)
+
+label(NAME)
+manpagename(socat) (Multipurpose relay (SOcket CAT))
+
+label(SYNOPSIS)
+manpagesynopsis()
+tt(socat [options] <address> <address>)nl()
+tt(socat -V)nl()
+tt(socat -h[h[h]] | -?[?[?]])nl()
+tt(filan)nl()
+tt(procan)
+
+label(DESCRIPTION)
+manpagedescription()
+
+Socat() is a command line based utility that establishes two bidirectional byte
+streams and transfers data between them. Because the streams can be constructed
+from a large set of different types of data sinks and sources
+(see link(address types)(ADDRESS_TYPES)), and because lots of
+link(address options)(ADDRESS_OPTIONS) may be applied to the streams, socat can
+be used for many different purposes.
+It might be one of the tools that one `has already needed'.
+
+Filan() is a utility that prints information about its active file
+descriptors to stdout. It has been written for debugging socat(), but might be
+useful for other purposes too. Use the -h option to find more infos.
+
+Procan() is a utility that prints information about process parameters to
+stdout. It has been written to better understand
+some UNIX process properties and for debugging socat(), but might be
+useful for other purposes too.
+
+The life cycle of a socat() instance typically consists of four phases.
+
+In the em(init) phase, the command line options are parsed and logging is
+initialized.
+
+During the em(open) phase, socat() opens the first address and afterwards the
+second address. These steps are usually blocking; thus, especially for complex address types like socks,
+connection requests or authentication dialogs must be completed before the next
+step is started.
+
+In the em(transfer) phase, socat() watches both streams' read and write file
+descriptors via code(select()), and, when data is available on one side em(and)
+can be written to the other side, socat reads it, performs newline
+character conversions if required, and writes the data to the write file
+descriptor of the other stream, then continues waiting for more data in both
+directions.
+
+When one of the streams effectively reaches EOF, the em(closing) phase
+begins. Socat() transfers the EOF condition to the other stream,
+i.e. tries to shutdown only its write stream, giving it a chance to
+terminate gracefully. For a defined time socat() continues to transfer data in
+the other direction, but then closes all remaining channels and terminates.
+
+
+label(OPTIONS)
+manpageoptions()
+
+Socat() provides some command line options that modify the behaviour of the
+program. They have nothing to do with so called
+link(address options)(ADDRESS_OPTIONS) that are used as parts of link(address specifications)(ADDRESS_SPECIFICATIONS).
+
+startdit()
+dit(bf(tt(-V)))
+ Print version and available feature information to stdout, and exit.
+dit(bf(tt(-h | -?)))
+ Print a help text to stdout describing command line options and available address
+ types, and exit.
+dit(bf(tt(-hh | -??)))
+ Like -h, plus a list of the short names of all available address options. Some options are
+ platform dependend, so this output is helpful for checking the particular
+ implementation.
+dit(bf(tt(-hhh | -???)))
+ Like -hh, plus a list of all available address option names.
+label(option_d)dit(bf(tt(-d)))
+ Without this option, only fatal and error messages are generated; applying
+ this option also prints warning messages. See link(DIAGNOSTICS)(DIAGNOSTICS)
+ for more information.
+label(option_d_d)dit(bf(tt(-d -d))) Prints fatal, error, warning, and notice messages.
+dit(bf(tt(-d -d -d))) Prints fatal, error, warning, notice, and info messages.
+dit(bf(tt(-d -d -d -d))) Prints fatal, error, warning, notice, info, and debug
+ messages.
+dit(bf(tt(-D)))
+ Logs information about file descriptors before starting the transfer phase.
+dit(bf(tt(-ly[<facility>])))
+ Writes messages to syslog instead of stderr; severity as defined with -d
+ option. With optional link(<facility>)(TYPE_FACILITY), the syslog type can
+ be selected, default is "daemon".
+dit(bf(tt(-lf))tt( <logfile>))
+ Writes messages to <logfile> [link(filename)(TYPE_FILENAME)] instead of
+ stderr.
+dit(bf(tt(-ls)))
+ Writes messages to stderr (this is the default).
+label(option_lp)dit(bf(tt(-lp))tt(<progname>))
+ Overrides the program name printed in error messages.
+dit(bf(tt(-lu)))
+ Extends the timestamp of error messages to microsecond resolution. Does not
+ work when logging to syslog.
+label(option_lm)dit(bf(tt(-lm[<facility>])))
+ Mixed log mode. During startup messages are printed to stderr; when socat()
+ starts the transfer phase loop or daemon mode (i.e. after opening all
+ streams and before starting data transfer, or, with listening sockets with
+ fork option, before the first accept call), it switches logging to syslog.
+ With optional link(<facility>)(TYPE_FACILITY), the syslog type can be
+ selected, default is "daemon".
+label(option_lh)dit(bf(tt(-lh)))
+ Adds hostname to log messages. Uses the value from environment variable
+ HOSTNAME or the value retrieved with tt(uname()) if HOSTNAME is not set.
+dit(bf(tt(-v)))
+ Writes the transferred data not only to their target streams, but also to
+ stderr. The output format is text with some conversions for readability, and
+ prefixed with "> " or "< " indicating flow directions.
+dit(bf(tt(-x)))
+ Writes the transferred data not only to their target streams, but also to
+ stderr. The output format is hexadecimal, prefixed with "> " or "< "
+ indicating flow directions. Can be combined with code(-v).
+label(option_b)dit(bf(tt(-b))tt(<size>))
+ Sets the data transfer block <size> [link(size_t)(TYPE_SIZE_T)].
+ At most <size> bytes are transferred per step. Default is 8192 bytes.
+label(option_s)dit(bf(tt(-s)))
+ By default, socat() terminates when an error occurred to prevent the process
+ from running when some option could not be applied. With this
+ option, socat() is sloppy with errors and tries to continue. Even with this
+ option, socat will exit on fatals, and will abort connection attempts when
+ security checks failed.
+label(option_t)dit(bf(tt(-t))tt(<timeout>))
+ When one channel has reached EOF, the write part of the other channel is shut
+ down. Then, socat() waits <timeout> [link(timeval)(TYPE_TIMEVAL)] seconds
+ before terminating. Default is 0.5 seconds. This timeout only applies to
+ addresses where write and read part can be closed independently. When during
+ the timeout intervall the read part gives EOF, socat terminates without
+ awaiting the timeout.
+label(option_T)dit(bf(tt(-T))tt(<timeout>))
+ Total inactivity timeout: when socat is already in the transfer loop and
+ nothing has happened for <timeout> [link(timeval)(TYPE_TIMEVAL)] seconds
+ (no data arrived, no interrupt occurred...) then it terminates.
+ Useful with protocols like UDP that cannot transfer EOF.
+label(option_u)dit(bf(tt(-u)))
+ Uses unidirectional mode. The first address is only used for reading, and the
+ second address is only used for writing (link(example)(EXAMPLE_option_u)).
+label(option_U)dit(bf(tt(-U)))
+ Uses unidirectional mode in reverse direction. The first address is only
+ used for writing, and the second address is only used for reading.
+label(option_g)dit(bf(tt(-g)))
+ During address option parsing, don't check if the option is considered
+ useful in the given address environment. Use it if you want to force, e.g.,
+ appliance of a socket option to a serial device.
+label(option_L)dit(bf(tt(-L))tt(<lockfile>))
+ If lockfile exists, exits with error. If lockfile does not exist, creates it
+ and continues, unlinks lockfile on exit.
+label(option_W)dit(bf(tt(-W))tt(<lockfile>))
+ If lockfile exists, waits until it disappears. When lockfile does not exist,
+ creates it and continues, unlinks lockfile on exit.
+label(option_4)dit(bf(tt(-4)))
+ Use IP version 4 in case that the addresses do not implicitly or explicitly
+ specify a version; this is the default.
+label(option_6)dit(bf(tt(-6)))
+ Use IP version 6 in case that the addresses do not implicitly or explicitly
+ specify a version.
+enddit()
+
+
+label(ADDRESS_SPECIFICATIONS)
+manpagesection(ADDRESS SPECIFICATIONS)
+
+With the address command line arguments, the user gives socat() instructions and
+the necessary information for establishing the byte streams.
+
+An address specification usually consists of an address type
+keyword, zero or more required address parameters separated by ':' from the keyword and
+from each
+other, and zero or more address options separated by ','.
+
+The keyword specifies the address type (e.g., TCP4, OPEN, EXEC). For some
+keywords there exist synonyms ('-' for STDIO, TCP for TCP4). Keywords are case
+insensitive.
+For a few special address types, the keyword may be omitted:
+Address specifications starting with a number are assumed to be FD (raw file
+descriptor) addresses;
+if a '/' is found before the first ':' or ',', GOPEN (generic file open) is
+assumed.
+
+The required number and type of address parameters depend on the address
+type. E.g., TCP4 requires a server specification (name or address), and a port
+specification (number or service name).
+
+Zero or more address options may be given with each address. They influence the
+address in some ways.
+Options consist of an option keyword or an option keyword and a value,
+separated by '='. Option keywords are case insensitive.
+For filtering the options that are useful with an address
+type, each option is member of one option group. For
+each address type there is a set of option groups allowed. Only options
+belonging to one of these address groups may be used (except with link(option -g)(option_g)).
+
+label(ADDRESS_DUAL)
+Address specifications following the above schema are also called em(single)
+address specifications.
+Two single addresses can be combined with "!!" to form a em(dual) type
+address for one channel. Here, the first address is used by socat() for reading
+data, and the
+second address for writing data. There is no way to specify an option only once
+for being applied to both single addresses.
+
+Usually, addresses are opened in read/write
+mode. When an address is part of a dual address specification, or when
+link(option -u)(option_u) or link(-U)(option_U) is used, an address might be
+used only for reading or for writing. Considering this is important with some
+address types.
+
+With socat version 1.5.0 and higher, the lexical analysis tries to handle
+quotes and parenthesis meaningfully and allows escaping of special characters.
+If one of the characters ( { [ ' is found, the corresponding closing
+character - ) } ] ' - is looked for; they may also be nested. Within these
+constructs, socats special characters and strings : , !! are not handled
+specially. All those characters and strings can be escaped with \ or within ""
+
+label(ADDRESS_TYPES)
+manpagesection(ADDRESS TYPES)
+
+This section describes the available address types with their keywords,
+parameters, and semantics.
+
+startdit()
+label(ADDRESS_CREAT)dit(bf(tt(CREATE:<filename>)))
+ Opens link(<filename>)(TYPE_FILENAME) with code(creat()) and uses the file
+ descriptor for writing.
+ This address type requires write-only context, because a file opened with
+ code(creat) cannot be read from.
+ <filename> must be a valid existing or not existing path.
+ If <filename> is a named pipe, code(creat()) might block;
+ if <filename> refers to a socket, this is an error.nl()
+ Option groups: link(FD)(GROUP_FD),link(REG)(GROUP_REG),link(NAMED)(GROUP_NAMED) nl()
+ Useful options:
+ link(mode)(OPTION_MODE),
+ link(user)(OPTION_USER),
+ link(group)(OPTION_GROUP),
+ link(unlink-early)(OPTION_UNLINK_EARLY),
+ link(unlink-late)(OPTION_UNLINK_LATE),
+ link(append)(OPTION_APPEND)nl()
+ See also: link(OPEN)(ADDRESS_OPEN), link(GOPEN)(ADDRESS_GOPEN)
+label(ADDRESS_EXEC)dit(bf(tt(EXEC:<command-line>)))
+ Forks a sub process that establishes communication with its parent process
+ and invokes the specified program with code(execvp()).
+ link(<command-line>)(TYPE_COMMAND_LINE) is a simple command
+ with arguments separated by single spaces. If the program name
+ contains a '/', the part after the last '/' is taken as ARGV[0]. If the
+ program name is a relative
+ path, the code(execvp()) semantics for finding the program via
+ code($PATH)
+ apply. After successful program start, socat() writes data to stdin of the
+ process and reads from its stdout using a unixdomain() socket generated by
+ code(socketpair()) per default. (link(example)(EXAMPLE_ADDRESS_EXEC)) nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(EXEC)(GROUP_EXEC),link(FORK)(GROUP_FORK),link(TERMIOS)(GROUP_TERMIOS) nl()
+ Useful options:
+ link(path)(OPTION_PATH),
+ link(fdin)(OPTION_FDIN),
+ link(fdout)(OPTION_FDOUT),
+ link(chroot)(OPTION_CHROOT),
+ link(su)(OPTION_SUBSTUSER),
+ link(su-d)(OPTION_SUBSTUSER_DELAYED),
+ link(nofork)(OPTION_NOFORK),
+ link(pty)(OPTION_PTY),
+ link(stderr)(OPTION_STDERR),
+ link(ctty)(OPTION_CTTY),
+ link(setsid)(OPTION_SETSID),
+ link(pipes)(OPTION_PIPES),
+ link(login)(OPTION_LOGIN),
+ link(sigint)(OPTION_SIGINT),
+ link(sigquit)(OPTION_SIGQUIT)nl()
+ See also: link(SYSTEM)(ADDRESS_SYSTEM)
+label(ADDRESS_FD)dit(bf(tt(FD:<fdnum>)))
+ Uses the file descriptor link(<fdnum>)(TYPE_FDNUM). It must already exist as
+ valid unix() file descriptor.nl()
+ Option groups: link(FD)(GROUP_FD) (link(TERMIOS)(GROUP_TERMIOS),link(REG)(GROUP_REG),link(SOCKET)(GROUP_SOCKET)) nl()
+ See also:
+ link(STDIO)(ADDRESS_STDIO),
+ link(STDIN)(ADDRESS_STDIN),
+ link(STDOUT)(ADDRESS_STDOUT),
+ link(STDERR)(ADDRESS_STDERR)
+label(ADDRESS_GOPEN)dit(bf(tt(GOPEN:<filename>)))
+ (Generic open) This address type tries to handle any file system entry
+ except directories usefully. link(<filename>)(TYPE_FILENAME) may be a
+ relative or absolute path. If it already exists, its type is checked.
+ In case of a unixdomain() socket, socat() connects; if connecting fails,
+ socat() assumes a datagram socket and uses code(sendto()) calls.
+ If the entry is not a socket, socat() opens it applying the code(O_APPEND)
+ flag.
+ If it does not exist, it is opened with flag
+ code(O_CREAT) as a regular file (link(example)(EXAMPLE_ADDRESS_GOPEN)).nl()
+ Option groups: link(FD)(GROUP_FD),link(REG)(GROUP_REG),link(SOCKET)(GROUP_SOCKET),link(NAMED)(GROUP_NAMED),link(OPEN)(GROUP_OPEN) nl()
+ See also:
+ link(OPEN)(ADDRESS_OPEN),
+ link(CREATE)(ADDRESS_CREAT),
+ link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT)
+
+label(ADDRESS_IP_SENDTO)dit(bf(tt(IP-SENDTO:<host>:<protocol>)))
+ Opens a raw IP socket. Depending on host specification or option link(pf)(OPTION_PROTOCOL_FAMILY), IP procotol version
+ 4 or 6 is used. It uses link(<protocol>)(TYPE_PROTOCOL) to send packets
+ to <host> [link(IP address)(TYPE_IP_ADDRESS)] and receives packets from
+ host, ignores packets from other hosts.
+ Protocol 255 uses the raw socket with the IP header being part of the
+ data.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6) nl()
+ Useful options:
+ link(pf)(OPTION_PROTOCOL_FAMILY),
+ link(ttl)(OPTION_TTL)
+ See also:
+ link(IP4-SENDTO)(ADDRESS_IP4_SENDTO),
+ link(IP6-SENDTO)(ADDRESS_IP6_SENDTO),
+ link(IP-RECVFROM)(ADDRESS_IP_RECVFROM),
+ link(IP-RECV)(ADDRESS_IP_RECV),
+ link(UDP-SENDTO)(ADDRESS_UDP_SENDTO)
+ link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO)
+label(ADDRESS_IP4_SENDTO)dit(bf(tt(IP4-SENDTO:<host>:<protocol>)))
+ 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()
+label(ADDRESS_IP6_SENDTO)dit(bf(tt(IP6-SENDTO:<host>:<protocol>)))
+ Like link(IP-SENDTO)(ADDRESS_IP_SENDTO), but always uses IPv6.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6) nl()
+
+label(ADDRESS_IP_DATAGRAM)dit(bf(tt(IP-DATAGRAM:<address>:<protocol>)))
+ Sends outgoing data to the specified address which may in particular be a
+ broadcast or multicast address. Packets arriving on the local socket are
+ checked if their source addresses match
+ eventual link(RANGE)(OPTION_RANGE) or link(TCPWRAP)(OPTION_TCPWRAPPERS)
+ 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:
+ link(range)(OPTION_RANGE),
+ link(tcpwrap)(OPTION_TCPWRAPPERS),
+ link(broadcast)(OPTION_SO_BROADCAST),
+ link(ip-multicast-loop)(OPTION_IP_MULTICAST_LOOP),
+ link(ip-multicast-ttl)(OPTION_IP_MULTICAST_TTL),
+ link(ip-multicast-if)(OPTION_IP_MULTICAST_IF),
+ 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),
+ link(IP6-DATAGRAM)(ADDRESS_IP6_DATAGRAM),
+ link(IP-SENDTO)(ADDRESS_IP_SENDTO),
+ link(IP-RECVFROM)(ADDRESS_IP_RECVFROM),
+ link(IP-RECV)(ADDRESS_IP_RECV),
+ link(UDP-DATAGRAM)(ADDRESS_UDP_DATAGRAM)
+label(ADDRESS_IP4_DATAGRAM)dit(bf(tt(IP4-DATAGRAM:<host>:<protocol>)))
+ Like link(IP-DATAGRAM)(ADDRESS_IP_DATAGRAM), but always uses IPv4.
+ (link(example)(EXAMPLE_ADDRESS_IP4_BROADCAST_CLIENT))nl()
+ Option groups: link(FD)(GROUP_FD), link(SOCKET)(GROUP_SOCKET),
+ link(IP4)(GROUP_IP4), link(RANGE)(GROUP_RANGE) nl()
+label(ADDRESS_IP6_DATAGRAM)dit(bf(tt(IP6-DATAGRAM:<host>:<protocol>)))
+ Like link(IP-DATAGRAM)(ADDRESS_IP_DATAGRAM), but always uses IPv6. Please
+ note that IPv6 does not know broadcasts.nl()
+ Option groups: link(FD)(GROUP_FD), link(SOCKET)(GROUP_SOCKET),
+ link(IP6)(GROUP_IP6), link(RANGE)(GROUP_RANGE) nl()
+
+label(ADDRESS_IP_RECVFROM)dit(bf(tt(IP-RECVFROM:<protocol>)))
+ Opens a raw IP socket of link(<protocol>)(TYPE_PROTOCOL). Depending on option link(pf)(OPTION_PROTOCOL_FAMILY), IP procotol version
+ 4 or 6 is used. It receives one packet from an unspecified peer and may send one or more answer packets to that peer.
+ This mode is particularly useful with fork option where each arriving packet - from arbitrary peers - is handled by its own sub process.
+ This allows a behaviour similar to typical UDP based servers like ntpd or named.
+ This address works well with IP-SENDTO address peers (see above).
+ Protocol 255 uses the raw socket with the IP header being part of the
+ data.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE) nl()
+ Useful options:
+ link(pf)(OPTION_PROTOCOL_FAMILY),
+ link(fork)(OPTION_FORK),
+ link(range)(OPTION_RANGE),
+ link(ttl)(OPTION_TTL),
+ link(broadcast)(OPTION_SO_BROADCAST)nl()
+ See also:
+ link(IP4-RECVFROM)(ADDRESS_IP4_RECVFROM),
+ link(IP6-RECVFROM)(ADDRESS_IP6_RECVFROM),
+ link(IP-SENDTO)(ADDRESS_IP_SENDTO),
+ link(IP-RECV)(ADDRESS_IP_RECV),
+ link(UDP-RECVFROM)(ADDRESS_UDP_RECVFROM),
+ link(UNIX-RECVFROM)(ADDRESS_UNIX_RECVFROM)
+label(ADDRESS_IP4_RECVFROM)dit(bf(tt(IP4-RECVFROM:<protocol>)))
+ Like link(IP-RECVFROM)(ADDRESS_IP_RECVFROM), but always uses IPv4.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE) nl()
+label(ADDRESS_IP6_RECVFROM)dit(bf(tt(IP6-RECVFROM:<protocol>)))
+ Like link(IP-RECVFROM)(ADDRESS_IP_RECVFROM), but always uses IPv6.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE) nl()
+
+label(ADDRESS_IP_RECV)dit(bf(tt(IP-RECV:<protocol>)))
+ Opens a raw IP socket of link(<protocol>)(TYPE_PROTOCOL). Depending on option link(pf)(OPTION_PROTOCOL_FAMILY), IP procotol version
+ 4 or 6 is used. It receives packets from multiple unspecified peers and merges the data.
+ No replies are possible.
+ It can be, e.g., addressed by socat IP-SENDTO address peers.
+ Protocol 255 uses the raw socket with the IP header being part of the
+ data.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:
+ link(pf)(OPTION_PROTOCOL_FAMILY),
+ link(range)(OPTION_RANGE)nl()
+ See also:
+ link(IP4-RECV)(ADDRESS_IP4_RECV),
+ link(IP6-RECV)(ADDRESS_IP6_RECV),
+ link(IP-SENDTO)(ADDRESS_IP_SENDTO),
+ link(IP-RECVFROM)(ADDRESS_IP_RECVFROM),
+ link(UDP-RECV)(ADDRESS_UDP_RECV),
+ link(UNIX-RECV)(ADDRESS_UNIX_RECV)
+label(ADDRESS_IP4_RECV)dit(bf(tt(IP4-RECV:<protocol>)))
+ Like link(IP-RECV)(ADDRESS_IP_RECV), but always uses IPv4.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(RANGE)(GROUP_RANGE) nl()
+label(ADDRESS_IP6_RECV)dit(bf(tt(IP6-RECV:<protocol>)))
+ Like link(IP-RECV)(ADDRESS_IP_RECV), but always uses IPv6.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6),link(RANGE)(GROUP_RANGE) nl()
+
+label(ADDRESS_OPEN)dit(bf(tt(OPEN:<filename>)))
+ Opens link(<filename>)(TYPE_FILENAME) using the code(open()) system call
+ (link(example)(EXAMPLE_ADDRESS_OPEN)).
+ This operation fails on unixdomain() sockets. nl()
+ Note: This address type is rarly useful in bidirectional mode.nl()
+ Option groups: link(FD)(GROUP_FD),link(REG)(GROUP_REG),link(NAMED)(GROUP_NAMED),link(OPEN)(GROUP_OPEN) nl()
+ Useful options:
+ link(creat)(OPTION_CREAT),
+ link(excl)(OPTION_EXCL),
+ link(noatime)(OPTION_O_NOATIME),
+ link(nofollow)(OPTION_NOFOLLOW),
+ link(append)(OPTION_APPEND),
+ link(rdonly)(OPTION_RDONLY),
+ link(wronly)(OPTION_WRONLY),
+ link(lock)(OPTION_LOCK),
+ link(readbytes)(OPTION_READBYTES),
+ link(ignoreeof)(OPTION_IGNOREEOF)nl()
+ See also:
+ link(CREATE)(ADDRESS_CREAT),
+ link(GOPEN)(ADDRESS_GOPEN),
+ link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT)
+label(ADDRESS_OPENSSL_CONNECT)dit(bf(tt(OPENSSL:<host>:<port>)))
+ Tries to establish a SSL connection to <port> [link(TCP
+ service)(TYPE_TCP_SERVICE)] on
+ <host> [link(IP address)(TYPE_IP_ADDRESS)] using TCP/IP version 4 or 6
+ depending on address specification, name resolution, or option
+ link(pf)(OPTION_PROTOCOL_FAMILY).nl()
+ NOTE: The server certificate is only checked for validity against
+ link(cafile)(OPTION_OPENSSL_CAFILE) or link(capath)(OPTION_OPENSSL_CAPATH),
+ but not for match with the server's name or its IP address!nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(OPENSSL)(GROUP_OPENSSL),link(RETRY)(GROUP_RETRY) nl()
+ Useful options:
+ link(cipher)(OPTION_OPENSSL_CIPHERLIST),
+ link(method)(OPTION_OPENSSL_METHOD),
+ link(verify)(OPTION_OPENSSL_VERIFY),
+ link(cafile)(OPTION_OPENSSL_CAFILE),
+ link(capath)(OPTION_OPENSSL_CAPATH),
+ link(certificate)(OPTION_OPENSSL_CERTIFICATE),
+ link(bind)(OPTION_BIND),
+ link(pf)(OPTION_PROTOCOL_FAMILY),
+ link(connect-timeout)(OPTION_CONNECT_TIMEOUT),
+ link(sourceport)(OPTION_SOURCEPORT),
+ link(retry)(OPTION_RETRY)nl()
+ See also:
+ link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN),
+ link(TCP)(ADDRESS_TCP_CONNECT)
+label(ADDRESS_OPENSSL_LISTEN)dit(bf(tt(OPENSSL-LISTEN:<port>)))
+ Listens on tcp <port> [link(TCP service)(TYPE_TCP_SERVICE)].
+ The IP version is 4 or the one specified with
+ link(pf)(OPTION_PROTOCOL_FAMILY). When a
+ connection is accepted, this address behaves as SSL server.nl()
+ Note: You probably want to use the link(certificate)(OPTION_OPENSSL_CERTIFICATE) option with this address.nl()
+ NOTE: The client certificate is only checked for validity against
+ link(cafile)(OPTION_OPENSSL_CAFILE) or link(capath)(OPTION_OPENSSL_CAPATH),
+ but not for match with the client's name or its IP address!nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(LISTEN)(GROUP_LISTEN),link(OPENSSL)(GROUP_OPENSSL),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(RETRY)(GROUP_RETRY) nl()
+ Useful options:
+ link(pf)(OPTION_PROTOCOL_FAMILY),
+ link(cipher)(OPTION_OPENSSL_CIPHERLIST),
+ link(method)(OPTION_OPENSSL_METHOD),
+ link(verify)(OPTION_OPENSSL_VERIFY),
+ link(cafile)(OPTION_OPENSSL_CAFILE),
+ link(capath)(OPTION_OPENSSL_CAPATH),
+ link(certificate)(OPTION_OPENSSL_CERTIFICATE),
+ link(fork)(OPTION_FORK),
+ link(bind)(OPTION_BIND),
+ link(range)(OPTION_RANGE),
+ link(tcpwrap)(OPTION_TCPWRAPPERS),
+ link(su)(OPTION_SUBSTUSER),
+ link(reuseaddr)(OPTION_REUSEADDR),
+ link(retry)(OPTION_RETRY)nl()
+ See also:
+ link(OPENSSL)(ADDRESS_OPENSSL_CONNECT),
+ link(TCP)(ADDRESS_TCP_CONNECT)
+label(ADDRESS_NAMED_PIPE)dit(bf(tt(PIPE:<filename>)))
+ If link(<filename>)(TYPE_FILENAME) already exists, it is opened.
+ If is does not exist, a named pipe is created and opened. Beginning with
+ socat version 1.4.3, the named pipe is removed when the address is closed
+ (but see option link(unlink-close)(OPTION_UNLINK_CLOSE)nl()
+ Note: When a pipe is used for both reading and writing, it works
+ as echo service.nl()
+ Note: When a pipe is used for both reading and writing, and socat tries
+ to write more bytes than the pipe can buffer (Linux 2.4: 2048 bytes), socat
+ might block. Consider using socat option, e.g., code(-b 2048) nl()
+ Option groups: link(FD)(GROUP_FD),link(NAMED)(GROUP_NAMED),link(OPEN)(GROUP_OPEN) nl()
+ Useful options:
+ link(rdonly)(OPTION_RDONLY),
+ link(nonblock)(OPTION_NONBLOCK),
+ link(group)(OPTION_GROUP),
+ link(user)(OPTION_USER),
+ link(mode)(OPTION_MODE),
+ link(unlink-early)(OPTION_UNLINK_EARLY)nl()
+ See also: link(unnamed pipe)(ADDRESS_UNNAMED_PIPE)
+label(ADDRESS_UNNAMED_PIPE)dit(bf(tt(PIPE)))
+ Creates an unnamed pipe and uses it for reading and writing. It works as an
+ echo, because everything written
+ to it appeares immediately as read data.nl()
+ Note: When socat tries to write more bytes than the pipe can queue (Linux
+ 2.4: 2048 bytes), socat might block. Consider, e.g., using
+ option code(-b 2048) nl()
+ Option groups: link(FD)(GROUP_FD) nl()
+ See also: link(named pipe)(ADDRESS_NAMED_PIPE)
+label(ADDRESS_PROXY_CONNECT)dit(bf(tt(PROXY:<proxy>:<hostname>:<port>)))
+ Connects to an HTTP proxy server on port 8080 using TCP/IP version 4 or 6
+ depending on address specification, name resolution, or option
+ link(pf)(OPTION_PROTOCOL_FAMILY), and sends a CONNECT
+ request for hostname:port. If the proxy grants access and succeeds to
+ connect to the target, data transfer between socat and the target can
+ start. Note that the traffic need not be HTTP but can be an arbitrary
+ protocol. nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(HTTP)(GROUP_HTTP),link(RETRY)(GROUP_RETRY) nl()
+ Useful options:
+ link(proxyport)(OPTION_PROXYPORT),
+ link(ignorecr)(OPTION_IGNORECR),
+ link(proxyauth)(OPTION_PROXY_AUTHORIZATION),
+ link(resolve)(OPTION_PROXY_RESOLVE),
+ link(crnl)(OPTION_CRNL),
+ link(bind)(OPTION_BIND),
+ link(connect-timeout)(OPTION_CONNECT_TIMEOUT),
+ link(mss)(OPTION_MSS),
+ link(sourceport)(OPTION_SOURCEPORT),
+ link(retry)(OPTION_RETRY) nl()
+ See also: link(SOCKS)(ADDRESS_SOCKS4), link(TCP)(ADDRESS_TCP_CONNECT)
+label(ADDRESS_PTY)dit(bf(tt(PTY)))
+ Generates a pseudo terminal (pty) and uses its master side. Another process
+ may open the pty's slave side using it like a serial line or terminal.
+ (link(example)(EXAMPLE_ADDRESS_PTY)). If
+ both the ptmx and the openpty mechanisms are available, ptmx is used
+ (POSIX).nl()
+ Option groups: link(FD)(GROUP_FD),link(NAMED)(GROUP_NAMED),link(PTY)(GROUP_PTY),link(TERMIOS)(GROUP_TERMIOS) nl()
+ Useful options:
+ link(link)(OPTION_SYMBOLIC_LINK),
+ link(openpty)(OPTION_OPENPTY),
+ link(wait-slave)(OPTION_PTY_WAIT_SLAVE),
+ link(mode)(OPTION_MODE),
+ link(user)(OPTION_USER),
+ link(group)(OPTION_GROUP)nl()
+ See also:
+ link(UNIX-LISTEN)(ADDRESS_UNIX_LISTEN),
+ link(PIPE)(ADDRESS_NAMED_PIPE),
+ link(EXEC)(ADDRESS_EXEC), link(SYSTEM)(ADDRESS_SYSTEM)
+label(ADDRESS_READLINE)dit(bf(tt(READLINE)))
+ Uses GNU readline and history on stdio to allow editing and reusing input
+ lines (link(example)(EXAMPLE_ADDRESS_READLINE)). This requires the GNU readline and
+ history libraries. Note that stdio should be a (pseudo) terminal device,
+ otherwise readline does not seem to work.nl()
+ Option groups: link(FD)(GROUP_FD),link(READLINE)(GROUP_READLINE),link(TERMIOS)(GROUP_TERMIOS) nl()
+ Useful options:
+ link(history)(OPTION_HISTORY),
+ link(noecho)(OPTION_NOECHO)nl()
+ See also:
+ link(STDIO)(ADDRESS_STDIO)
+label(ADDRESS_SOCKS4)dit(bf(tt(SOCKS4:<socks-server>:<host>:<port>)))
+ Connects via <socks-server> [link(IP address)(TYPE_IP_ADDRESS)]
+ to <host> [link(IPv4 address)(TYPE_IPV4_ADDRESS)]
+ on <port> [link(TCP service)(TYPE_TCP_SERVICE)],
+ using socks version 4 protocol over IP version 4 or 6 depending on address specification, name resolution, or option
+ link(pf)(OPTION_PROTOCOL_FAMILY) (link(example)(EXAMPLE_ADDRESS_SOCKS4)).nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(SOCKS4)(GROUP_SOCKS),link(RETRY)(GROUP_RETRY) nl()
+ Useful options:
+ link(socksuser)(OPTION_SOCKSUSER),
+ link(socksport)(OPTION_SOCKSPORT),
+ link(sourceport)(OPTION_SOURCEPORT),
+ link(pf)(OPTION_PROTOCOL_FAMILY),
+ link(retry)(OPTION_RETRY)nl()
+ See also:
+ link(SOCKS4A)(ADDRESS_SOCKS4A),
+ link(PROXY)(ADDRESS_PROXY_CONNECT),
+ link(TCP)(ADDRESS_TCP_CONNECT)
+label(ADDRESS_SOCKS4A)dit(bf(tt(SOCKS4A:<socks-server>:<host>:<port>)))
+ like link(SOCKS4)(ADDRESS_SOCKS4), but uses socks protocol version 4a, thus
+ leaving host name resolution to the socks server.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(SOCKS4)(GROUP_SOCKS),link(RETRY)(GROUP_RETRY) nl()
+label(ADDRESS_STDERR)dit(bf(tt(STDERR)))
+ Uses file descriptor 2.nl()
+ Option groups: link(FD)(GROUP_FD) (link(TERMIOS)(GROUP_TERMIOS),link(REG)(GROUP_REG),link(SOCKET)(GROUP_SOCKET)) nl()
+ See also: link(FD)(ADDRESS_FD)
+label(ADDRESS_STDIN)dit(bf(tt(STDIN)))
+ Uses file descriptor 0.nl()
+ Option groups: link(FD)(GROUP_FD) (link(TERMIOS)(GROUP_TERMIOS),link(REG)(GROUP_REG),link(SOCKET)(GROUP_SOCKET)) nl()
+ Useful options:
+ link(readbytes)(OPTION_READBYTES)nl()
+ See also: link(FD)(ADDRESS_FD)
+label(ADDRESS_STDIO)dit(bf(tt(STDIO)))
+ Uses file descriptor 0 for reading, and 1 for writing.nl()
+ Option groups: link(FD)(GROUP_FD) (link(TERMIOS)(GROUP_TERMIOS),link(REG)(GROUP_REG),link(SOCKET)(GROUP_SOCKET)) nl()
+ Useful options:
+ link(readbytes)(OPTION_READBYTES)nl()
+ See also: link(FD)(ADDRESS_FD)
+label(ADDRESS_STDOUT)dit(bf(tt(STDOUT)))
+ Uses file descriptor 1.nl()
+ Option groups: link(FD)(GROUP_FD) (link(TERMIOS)(GROUP_TERMIOS),link(REG)(GROUP_REG),link(SOCKET)(GROUP_SOCKET)) nl()
+ See also: link(FD)(ADDRESS_FD)
+label(ADDRESS_SYSTEM)dit(bf(tt(SYSTEM:<shell-command>)))
+ Forks a sub process that establishes communication with its parent process
+ and invokes the specified program with code(system()). Please note that
+ <shell-command> [link(string)(TYPE_STRING)] must
+ not contain ',' or "!!", and that shell meta characters may have to be
+ protected.
+ After successful program start, socat() writes data to stdin of the
+ process and reads from its stdout.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(EXEC)(GROUP_EXEC),link(FORK)(GROUP_FORK),link(TERMIOS)(GROUP_TERMIOS) nl()
+ Useful options:
+ link(path)(OPTION_PATH),
+ link(fdin)(OPTION_FDIN),
+ link(fdout)(OPTION_FDOUT),
+ link(chroot)(OPTION_CHROOT),
+ link(su)(OPTION_SUBSTUSER),
+ link(su-d)(OPTION_SUBSTUSER_DELAYED),
+ link(nofork)(OPTION_NOFORK),
+ link(pty)(OPTION_PTY),
+ link(stderr)(OPTION_STDERR),
+ link(ctty)(OPTION_CTTY),
+ link(setsid)(OPTION_SETSID),
+ link(pipes)(OPTION_PIPES),
+ link(sigint)(OPTION_SIGINT),
+ link(sigquit)(OPTION_SIGQUIT)nl()
+ See also: link(EXEC)(ADDRESS_EXEC)
+label(ADDRESS_TCP_CONNECT)dit(bf(tt(TCP:<host>:<port>)))
+ Connects to <port> [link(TCP service)(TYPE_TCP_SERVICE)] on
+ <host> [link(IP address)(TYPE_IP_ADDRESS)] using TCP/IP version 4 or 6
+ depending on address specification, name resolution, or option
+ link(pf)(OPTION_PROTOCOL_FAMILY).nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(RETRY)(GROUP_RETRY) nl()
+ Useful options:
+ link(crnl)(OPTION_CRNL),
+ link(bind)(OPTION_BIND),
+ link(pf)(OPTION_PROTOCOL_FAMILY),
+ link(connect-timeout)(OPTION_CONNECT_TIMEOUT),
+ link(tos)(OPTION_TOS),
+ link(mtudiscover)(OPTION_MTUDISCOVER),
+ link(mss)(OPTION_MSS),
+ link(nodelay)(OPTION_NODELAY),
+ link(nonblock)(OPTION_NONBLOCK),
+ link(sourceport)(OPTION_SOURCEPORT),
+ link(retry)(OPTION_RETRY),
+ link(readbytes)(OPTION_READBYTES)nl()
+ See also:
+ link(TCP4)(ADDRESS_TCP4_CONNECT),
+ link(TCP6)(ADDRESS_TCP6_CONNECT),
+ link(TCP-LISTEN)(ADDRESS_TCP_LISTEN),
+ link(UDP)(ADDRESS_UDP_CONNECT),
+ link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT)
+label(ADDRESS_TCP4_CONNECT)dit(bf(tt(TCP4:<host>:<port>)))
+ Like link(TCP)(ADDRESS_TCP_CONNECT), but only supports IPv4 protocol (link(example)(EXAMPLE_ADDRESS_TCP4_CONNECT)).nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(TCP)(GROUP_TCP),link(RETRY)(GROUP_RETRY) nl()
+label(ADDRESS_TCP6_CONNECT)dit(bf(tt(TCP6:<host>:<port>)))
+ Like link(TCP)(ADDRESS_TCP_CONNECT), but only supports IPv6 protocol.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(RETRY)(GROUP_RETRY) nl()
+label(ADDRESS_TCP_LISTEN)dit(bf(tt(TCP-LISTEN:<port>)))
+ Listens on <port> [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).
+ 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()
+ 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(mss)(OPTION_MSS),
+ link(su)(OPTION_SUBSTUSER),
+ link(reuseaddr)(OPTION_REUSEADDR),
+ link(retry)(OPTION_RETRY),
+ link(retry)(OPTION_COOL_WRITE)nl()
+ See also:
+ link(TCP4-LISTEN)(ADDRESS_TCP4_CONNECT),
+ link(TCP6-LISTEN)(ADDRESS_TCP6_LISTEN),
+ link(UDP-LISTEN)(ADDRESS_UDP_LISTEN),
+ link(UNIX-LISTEN)(ADDRESS_UNIX_LISTEN),
+ link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN)
+label(ADDRESS_TCP4_LISTEN)dit(bf(tt(TCP4-LISTEN:<port>)))
+ Like link(TCP-LISTEN)(ADDRESS_TCP_LISTEN), but only supports IPv4
+ protocol (link(example)(EXAMPLE_ADDRESS_TCP4_LISTEN)).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(TCP)(GROUP_TCP),link(RETRY)(GROUP_RETRY) nl()
+label(ADDRESS_TCP6_LISTEN)dit(bf(tt(TCP6-LISTEN:<port>)))
+ Like link(TCP-LISTEN)(ADDRESS_TCP_LISTEN), but only supports IPv6
+ protocol.nl()
+ Additional useful option:
+ link(ipv6only)(OPTION_IPV6_V6ONLY)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(TCP)(GROUP_TCP),link(RETRY)(GROUP_RETRY) nl()
+label(ADDRESS_TUN)dit(bf(tt(TUN:<if-addr>/<bits>)))
+ Creates a Linux TUN/TAP device and assignes to it the address and netmask
+ defined by the parameters. The resulting network interface is ready for use
+ by other processes; socat serves its "wire side". This address requires read
+ and write access to the tunnel cloning device, usually code(/dev/net/tun).
+ nl()
+ Option groups: link(FD)(GROUP_FD),link(NAMED)(GROUP_NAMED),link(OPEN)(GROUP_OPEN),link(TUN)(GROUP_TUN) nl()
+ Useful options:
+ link(iff-up)(OPTION_IFF_UP),
+ link(tun-device)(OPTION_TUN_DEVICE),
+ link(tun-name)(OPTION_TUN_NAME),
+ link(tun-type)(OPTION_TUN_TYPE),
+ link(iff-no-pi)(OPTION_IFF_NO_PI) nl()
+ See also:
+ link(ip-recv)(ADDRESS_IP_RECV)
+label(ADDRESS_UDP_CONNECT)dit(bf(tt(UDP:<host>:<port>)))
+ Connects to <port> [link(UDP service)(TYPE_UDP_SERVICE)] on
+ <host> [link(IP address)(TYPE_IP_ADDRESS)] using UDP/IP version 4 or 6
+ depending on address specification, name resolution, or option
+ link(pf)(OPTION_PROTOCOL_FAMILY).nl()
+ Please note that,
+ due to UDP protocol properties, no real connection is established; data has
+ to be sent for `connecting' to the server, and no end-of-file condition can
+ be transported.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6) nl()
+ Useful options:
+ link(ttl)(OPTION_TTL),
+ link(tos)(OPTION_TOS),
+ link(bind)(OPTION_BIND),
+ link(sourceport)(OPTION_SOURCEPORT),
+ link(pf)(OPTION_PROTOCOL_FAMILY)nl()
+ See also:
+ link(UDP4)(ADDRESS_UDP4_CONNECT),
+ link(UDP6)(ADDRESS_UDP6_CONNECT),
+ link(UDP-LISTEN)(ADDRESS_UDP_LISTEN),
+ link(TCP)(ADDRESS_TCP_CONNECT),
+ link(IP)(ADDRESS_IP_SENDTO)
+label(ADDRESS_UDP4_CONNECT)dit(bf(tt(UDP4:<host>:<port>)))
+ Like link(UDP)(ADDRESS_UDP_CONNECT), but only supports IPv4 protocol.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4) nl()
+label(ADDRESS_UDP6_CONNECT)dit(bf(tt(UDP6:<host>:<port>)))
+ Like link(UDP)(ADDRESS_UDP_CONNECT), but only supports IPv6 protocol.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6) nl()
+label(ADDRESS_UDP_DATAGRAM)dit(bf(tt(UDP-DATAGRAM:<address>:<port>)))
+ Sends outgoing data to the specified address which may in particular be a
+ broadcast or multicast address. Packets arriving on the local socket are
+ checked for the correct remote port and if their source addresses match
+ eventual link(RANGE)(OPTION_RANGE) or link(TCPWRAP)(OPTION_TCPWRAPPERS)
+ 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:
+ link(range)(OPTION_RANGE),
+ link(tcpwrap)(OPTION_TCPWRAPPERS),
+ link(broadcast)(OPTION_SO_BROADCAST),
+ link(ip-multicast-loop)(OPTION_IP_MULTICAST_LOOP),
+ link(ip-multicast-ttl)(OPTION_IP_MULTICAST_TTL),
+ link(ip-multicast-if)(OPTION_IP_MULTICAST_IF),
+ 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:
+ link(UDP4-DATAGRAM)(ADDRESS_UDP4_DATAGRAM),
+ link(UDP6-DATAGRAM)(ADDRESS_UDP6_DATAGRAM),
+ link(UDP-SENDTO)(ADDRESS_UDP_SENDTO),
+ link(UDP-RECVFROM)(ADDRESS_UDP_RECVFROM),
+ link(UDP-RECV)(ADDRESS_UDP_RECV),
+ link(UDP-CONNECT)(ADDRESS_UDP_CONNECT),
+ link(UDP-LISTEN)(ADDRESS_UDP_LISTEN),
+ link(IP-DATAGRAM)(ADDRESS_IP_DATAGRAM)
+label(ADDRESS_UDP4_DATAGRAM)dit(bf(tt(UDP4-DATAGRAM:<address>:<port>)))
+ Like link(UDP-DATAGRAM)(ADDRESS_UDP_DATAGRAM), but only supports IPv4
+ protocol (link(example1)(EXAMPLE_ADDRESS_UDP4_BROADCAST_CLIENT),
+ link(example2)(EXAMPLE_ADDRESS_UDP4_MULTICAST)).nl()
+ Option groups: link(FD)(GROUP_FD), link(SOCKET)(GROUP_SOCKET),
+ link(IP4)(GROUP_IP4), link(RANGE)(GROUP_RANGE)
+label(ADDRESS_UDP6_DATAGRAM)dit(bf(tt(UDP6-DATAGRAM:<address>:<port>)))
+ Like link(UDP-DATAGRAM)(ADDRESS_UDP_DATAGRAM), but only supports IPv6
+ protocol.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),
+ link(IP6)(GROUP_IP6),link(RANGE)(GROUP_RANGE)
+label(ADDRESS_UDP_LISTEN)dit(bf(tt(UDP-LISTEN:<port>)))
+ Waits for a UDP/IP packet arriving on <port>
+ [link(UDP service)(TYPE_UDP_SERVICE)] and `connects' back to sender.
+ The accepted IP version is 4 or the one specified with option
+ link(pf)(OPTION_PROTOCOL_FAMILY).
+ Please note that,
+ due to UDP protocol properties, no real connection is established; data has
+ to arrive from the peer first, and no end-of-file condition can be
+ transported. 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) nl()
+ Useful options:
+ link(fork)(OPTION_FORK),
+ link(bind)(OPTION_BIND),
+ link(range)(OPTION_RANGE),
+ link(pf)(OPTION_PROTOCOL_FAMILY) nl()
+ See also:
+ link(UDP)(ADDRESS_UDP_CONNECT),
+ link(UDP4-LISTEN)(ADDRESS_UDP4_LISTEN),
+ link(UDP6-LISTEN)(ADDRESS_UDP6_LISTEN),
+ link(TCP-LISTEN)(ADDRESS_TCP_LISTEN)
+label(ADDRESS_UDP4_LISTEN)dit(bf(tt(UDP4-LISTEN:<port>)))
+ Like link(UDP-LISTEN)(ADDRESS_UDP_LISTEN), but only support 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) nl()
+label(ADDRESS_UDP6_LISTEN)dit(bf(tt(UDP6-LISTEN:<port>)))
+ Like link(UDP-LISTEN)(ADDRESS_UDP_LISTEN), but only support 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) nl()
+label(ADDRESS_UDP_SENDTO)dit(bf(tt(UDP-SENDTO:<host>:<port>)))
+ Communicates with the specified peer socket, defined by <port> [link(UDP
+ service)(TYPE_UDP_SERVICE)] on
+ <host> [link(IP address)(TYPE_IP_ADDRESS)], using UDP/IP version 4 or 6
+ depending on address specification, name resolution, or option
+ link(pf)(OPTION_PROTOCOL_FAMILY). It sends packets to and receives packets
+ from that peer socket only.
+ This address effectively implements a datagram client.
+ It works well with socat UDP-RECVFROM and UDP-RECV address peers.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6) nl()
+ Useful options:
+ link(ttl)(OPTION_TTL),
+ link(tos)(OPTION_TOS),
+ link(bind)(OPTION_BIND),
+ link(sourceport)(OPTION_SOURCEPORT),
+ link(pf)(OPTION_PROTOCOL_FAMILY)nl()
+ See also:
+ link(UDP4-SENDTO)(ADDRESS_UDP4_SENDTO),
+ link(UDP6-SENDTO)(ADDRESS_UDP6_SENDTO),
+ link(UDP-RECVFROM)(ADDRESS_UDP_RECVFROM),
+ link(UDP-RECV)(ADDRESS_UDP_RECV),
+ link(UDP-CONNECT)(ADDRESS_UDP_CONNECT),
+ link(UDP-LISTEN)(ADDRESS_UDP_LISTEN),
+ link(IP-SENDTO)(ADDRESS_IP_SENDTO)
+label(ADDRESS_UDP4_SENDTO)dit(bf(tt(UDP4-SENDTO:<host>:<port>)))
+ Like link(UDP-SENDTO)(ADDRESS_UDP_SENDTO), but only supports IPv4
+ protocol.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4)
+label(ADDRESS_UDP6_SENDTO)dit(bf(tt(UDP6-SENDTO:<host>:<port>)))
+ Like link(UDP-SENDTO)(ADDRESS_UDP_SENDTO), but only supports IPv6
+ protocol.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6)
+
+label(ADDRESS_UDP_RECVFROM)dit(bf(tt(UDP-RECVFROM:<port>)))
+ Creates a UDP socket on <port> [link(UDP service)(TYPE_UDP_SERVICE)] using
+ UDP/IP version 4 or 6
+ depending on option link(pf)(OPTION_PROTOCOL_FAMILY).
+ It receives one packet from an unspecified peer and may send one or more
+ answer packets to that peer. This mode is particularly useful with fork
+ option
+ where each arriving packet - from arbitrary peers - is handled by its own sub
+ process. This allows a behaviour similar to typical UDP based servers like ntpd
+ or named. This address works well with socat SENDTO address peers.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE) nl()
+ Useful options:
+ link(fork)(OPTION_FORK),
+ link(ttl)(OPTION_TTL),
+ link(tos)(OPTION_TOS),
+ link(bind)(OPTION_BIND),
+ link(sourceport)(OPTION_SOURCEPORT),
+ link(pf)(OPTION_PROTOCOL_FAMILY)nl()
+ See also:
+ link(UDP4-RECVFROM)(ADDRESS_UDP4_RECVFROM),
+ link(UDP6-RECVFROM)(ADDRESS_UDP6_RECVFROM),
+ link(UDP-SENDTO)(ADDRESS_UDP_SENDTO),
+ link(UDP-RECV)(ADDRESS_UDP_RECV),
+ link(UDP-CONNECT)(ADDRESS_UDP_CONNECT),
+ link(UDP-LISTEN)(ADDRESS_UDP_LISTEN),
+ link(IP-RECVFROM)(ADDRESS_IP_RECVFROM),
+ link(UNIX-RECVFROM)(ADDRESS_UNIX_RECVFROM)
+label(ADDRESS_UDP4_RECVFROM)dit(bf(tt(UDP4-RECVFROM:<port>)))
+ Like link(UDP-RECVFROM)(ADDRESS_UDP_RECVFROM), but only supports IPv4 protocol.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE)
+label(ADDRESS_UDP6_RECVFROM)dit(bf(tt(UDP6-RECVFROM:<port>)))
+ Like link(UDP-RECVFROM)(ADDRESS_UDP_RECVFROM), but only supports IPv6 protocol.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE)
+
+label(ADDRESS_UDP_RECV)dit(bf(tt(UDP-RECV:<port>)))
+ Creates a UDP socket on <port> [link(UDP service)(TYPE_UDP_SERVICE)] using UDP/IP version 4 or 6
+ depending on option link(pf)(OPTION_PROTOCOL_FAMILY).
+ It receives packets from multiple unspecified peers and merges the data.
+ No replies are possible. It works well with, e.g., socat UDP-SENDTO address peers; it behaves similar to a syslog server.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:
+ link(fork)(OPTION_FORK),
+ link(pf)(OPTION_PROTOCOL_FAMILY),
+ link(bind)(OPTION_BIND),
+ link(sourceport)(OPTION_SOURCEPORT),
+ link(ttl)(OPTION_TTL),
+ link(tos)(OPTION_TOS)nl()
+ See also:
+ link(UDP4-RECV)(ADDRESS_UDP4_RECV),
+ link(UDP6-RECV)(ADDRESS_UDP6_RECV),
+ link(UDP-SENDTO)(ADDRESS_UDP_SENDTO),
+ link(UDP-RECVFROM)(ADDRESS_UDP_RECVFROM),
+ link(UDP-CONNECT)(ADDRESS_UDP_CONNECT),
+ link(UDP-LISTEN)(ADDRESS_UDP_LISTEN),
+ link(IP-RECV)(ADDRESS_IP_RECV),
+ link(UNIX-RECV)(ADDRESS_UNIX_RECV)
+label(ADDRESS_UDP4_RECV)dit(bf(tt(UDP4-RECV:<port>)))
+ Like link(UDP-RECV)(ADDRESS_UDP_RECV), but only supports IPv4 protocol.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(RANGE)(GROUP_RANGE)
+label(ADDRESS_UDP6_RECV)dit(bf(tt(UDP6-RECV:<port>)))
+ Like link(UDP-RECV)(ADDRESS_UDP_RECV), but only supports IPv6 protocol.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6),link(RANGE)(GROUP_RANGE)
+
+label(ADDRESS_UNIX_CONNECT)dit(bf(tt(UNIX-CONNECT:<filename>)))
+ Connects to link(<filename>)(TYPE_FILENAME) assuming it is a unixdomain()
+ socket.
+ If <filename> does not exist, this is an error;
+ if <filename> is not a unixdomain() socket, this is an error;
+ if <filename> is a unixdomain() socket, but no process is listening, this is
+ an error.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),
+ link(NAMED)(GROUP_NAMED),link(RETRY)(GROUP_RETRY),
+ link(UNIX)(GROUP_SOCK_UNIX) nl())
+ Useful options:
+ link(bind)(OPTION_BIND)nl()
+ See also:
+ link(UNIX-LISTEN)(ADDRESS_UNIX_LISTEN),
+ link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO),
+ link(TCP)(ADDRESS_TCP_CONNECT)
+
+label(ADDRESS_UNIX_LISTEN)dit(bf(tt(UNIX-LISTEN:<filename>)))
+ Listens on link(<filename>)(TYPE_FILENAME) using a unixdomain() stream
+ socket and accepts a connection.
+ If <filename> exists and is not a socket, this is an error.
+ If <filename> exists and is a unixdomain() socket, binding to the address
+ fails (use option link(unlink-early)(OPTION_UNLINK_EARLY)!).
+ Note that opening this address usually blocks until a client connects.
+ Beginning with socat version 1.4.3, the file system entry is removed when
+ this address is closed (but see option link(unlink-close)(OPTION_UNLINK_CLOSE)) (link(example)(EXAMPLE_ADDRESS_UNIX_LISTEN)).nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),
+ link(NAMED)(GROUP_NAMED),link(LISTEN)(GROUP_LISTEN),
+ link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY),
+ link(UNIX)(GROUP_SOCK_UNIX) nl()
+ Useful options:
+ link(fork)(OPTION_FORK),
+ link(umask)(OPTION_UMASK),
+ link(mode)(OPTION_MODE),
+ link(user)(OPTION_USER),
+ link(group)(OPTION_GROUP),
+ link(unlink-early)(OPTION_UNLINK_EARLY)nl()
+ See also:
+ link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT),
+ link(UNIX-RECVFROM)(ADDRESS_UNIX_RECVFROM),
+ link(UNIX-RECV)(ADDRESS_UNIX_RECV),
+ link(TCP-LISTEN)(ADDRESS_TCP4_LISTEN)
+
+label(ADDRESS_UNIX_SENDTO)dit(bf(tt(UNIX-SENDTO:<filename>)))
+ Communicates with the specified peer socket, defined by [link(<filename>)(TYPE_FILENAME)] assuming it is a unixdomain() datagram socket.
+ It sends packets to and receives packets from that peer socket only.
+ It works well with socat UNIX-RECVFROM and UNIX-RECV address peers.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),
+ link(NAMED)(GROUP_NAMED),link(UNIX)(GROUP_SOCK_UNIX)nl()
+ Useful options:
+ link(bind)(OPTION_BIND)nl()
+ See also:
+ link(UNIX-RECVFROM)(ADDRESS_UNIX_RECVFROM),
+ link(UNIX-RECV)(ADDRESS_UNIX_RECV),
+ link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT),
+ link(UDP-SENDTO)(ADDRESS_UDP_SENDTO),
+ link(IP-SENDTO)(ADDRESS_IP_SENDTO)
+
+label(ADDRESS_UNIX_RECVFROM)dit(bf(tt(UNIX-RECVFROM:<filename>)))
+ Creates a unixdomain() datagram socket [link(<filename>)(TYPE_FILENAME)].
+ Receives one packet and may send one or more answer packets to that peer.
+ This mode is particularly useful with fork option where each arriving packet - from arbitrary peers - is handled by its own sub process.
+ This address works well with socat UNIX-SENDTO address peers.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),
+ link(NAMED)(GROUP_NAMED),link(CHILD)(GROUP_CHILD),
+ link(UNIX)(GROUP_SOCK_UNIX) nl()
+ Useful options:
+ link(fork)(OPTION_FORK)nl()
+ See also:
+ link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO),
+ link(UNIX-RECV)(ADDRESS_UNIX_RECV),
+ link(UNIX-LISTEN)(ADDRESS_UNIX_LISTEN),
+ link(UDP-RECVFROM)(ADDRESS_UDP_RECVFROM),
+ link(IP-RECVFROM)(ADDRESS_IP_RECVFROM)
+
+label(ADDRESS_UNIX_RECV)dit(bf(tt(UNIX-RECV:<filename>)))
+ Creates a unixdomain() datagram socket [link(<filename>)(TYPE_FILENAME)].
+ Receives packets from multiple unspecified peers and merges the data.
+ No replies are possible. It can be, e.g., addressed by socat UNIX-SENDTO address peers.
+ It behaves similar to a syslog server.
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),
+ link(NAMED)(GROUP_NAMED),link(UNIX)(GROUP_SOCK_UNIX) nl()
+ See also:
+ link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO),
+ link(UNIX-RECVFROM)(ADDRESS_UNIX_RECVFROM),
+ link(UNIX-LISTEN)(ADDRESS_UNIX_LISTEN),
+ link(UDP-RECV)(ADDRESS_UDP_RECV),
+ link(IP-RECV)(ADDRESS_IP_RECV)
+
+label(ADDRESS_UNIX_CLIENT)dit(bf(tt(UNIX-CLIENT:<filename>)))
+ Communicates with the specified peer socket, defined by
+ [link(<filename>)(TYPE_FILENAME)] assuming it is a unixdomain() socket.
+ It first tries to connect and, if that fails, assumes it is a datagram
+ socket, thus supporting both types.nl()
+ Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),
+ link(NAMED)(GROUP_NAMED),link(UNIX)(GROUP_SOCK_UNIX) nl()
+ Useful options:
+ link(bind)(OPTION_BIND)nl()
+ See also:
+ link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT),
+ link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO),
+ link(GOPEN)(ADDRESS_GOPEN)
+
+dit(bf(tt(ABSTRACT-CONNECT:<string>)))
+dit(bf(tt(ABSTRACT-LISTEN:<string>)))
+dit(bf(tt(ABSTRACT-SENDTO:<string>)))
+dit(bf(tt(ABSTRACT-RECVFROM:<string>)))
+dit(bf(tt(ABSTRACT-RECV:<string>)))
+dit(bf(tt(ABSTRACT-CLIENT:<string>)))
+ The ABSTRACT addresses are almost identical to the related UNIX addresses
+ except that they do not address file system based sockets but an alternate
+ unixdomain() address space. To archieve this the socket address strings are
+ prefixed with "\0" internally. This feature is available (only?) on Linux.
+ Option groups are the same as with the related UNIX addresses, except that
+ the ABSTRACT addresses are not member of the NAMED group.
+enddit()
+
+
+label(ADDRESS_OPTIONS)
+manpagesection(ADDRESS OPTIONS)
+
+Address options can be applied to address specifications to influence the
+process of opening the addresses and the
+properties of the resulting data channels.
+
+For technical reasons not every option can be
+applied to every address type; e.g., applying a socket option to a regular file
+will fail. To catch most useless combinations as early as in the open phase,
+the concept of em(option groups) was introduced. Each option belongs to one
+or more option groups. Options can be used only with address types that support
+at least one of their option groups (but see link(option -g)(option_g)).
+
+Address options have data types that their values must conform to.
+Every address option consists of just a keyword or a keyword followed by
+"=value", where value must conform to the options type.
+COMMENT(Options that trigger a call with
+trivial parameters are described with type BOOL which might be misleading.)
+Some address options manipulate parameters of system calls;
+e.g., option sync sets the code(O_SYNC) flag with the code(open()) call.
+Other options cause a system or library call; e.g., with option `ttl=value'
+the code(setsockopt(fd, SOL_IP, IP_TTL, value, sizeof(int))) call is applied.
+Other
+options set internal socat() variables that are used during data transfer;
+e.g., `crnl' causes explicit character conversions.
+A few options have more complex implementations; e.g., su-d
+(substuser-delayed) inquires some user and group infos, stores them, and
+applies them later after a possible code(chroot()) call.
+
+If multiple options are given to an address, their sequence in the address specification has (almost) no
+effect on the sequence of their execution/application. Instead, socat() has
+built in an em(option phase) model that tries to bring the options in a useful
+order. Some options exist in different forms (e.g.,
+unlink, unlink-early, unlink-late) to control the time of their execution.
+
+If the same option is specified more than once within one address
+specification, with equal or different values, the effect depends on the kind of option. Options
+resulting in function calls like code(setsockopt()) cause multiple
+invocations. With options that set parameters for a required call like
+code(open())
+or set internal flags, the value of the last option occurrence is effective.
+
+The existence or semantics of many options are system dependent. Socat()
+usually does NOT try to emulate missing libc or kernel features, it just
+provides an
+interface to the underlying system. So, if an operating system lacks a feature,
+the related option is simply not available on this platform.
+
+The following paragraphs introduce just the more common address options. For
+a more comprehensive reference and to find information about canonical option
+names, alias names, option phases, and platforms see file file(xio.help).
+nl() nl()
+
+startdit()enddit()nl()
+
+
+label(GROUP_FD)em(bf(FD option group))
+
+This option group contains options that are applied to a unix()
+style file descriptor, no matter how it was generated.
+Because all current socat() address types are file descriptor based, these
+options may be applied to any address. nl()
+Note: Some of these options are also member of another option group, that
+provides an other, non-fd based mechanism.
+For these options, it depends on the actual address type and its option groups
+which mechanism is used. The second, non-fd based mechanism is prioritized.
+startdit()
+label(OPTION_CLOEXEC)dit(bf(tt(cloexec=<bool>)))
+ Sets the code(FD_CLOEXEC) flag with the code(fcntl()) system call to value
+ link(<bool>)(TYPE_BOOL). If set,
+ the file descriptor is closed on code(exec()) family function calls. Socat()
+ internally handles
+ this flag for the fds it controls, so in most cases there will be no need to
+ apply this option.
+label(OPTION_SETLK_WR)dit(bf(tt(setlk)))
+ Tries to set a discretionary write lock to the whole file using the code(fcntl(fd,
+ F_SETLK, ...)) system call. If the file is already locked, this call results
+ in an error.
+ On Linux, when the file permissions for group are "S" (g-x,g+s), and the
+ file system is locally mounted with the "mand" option, the lock is
+ mandatory, i.e. prevents other processes from opening the file.
+label(OPTION_SETLKW_WR)dit(bf(tt(setlkw)))
+ Tries to set a discretionary waiting write lock to the whole file using the
+ code(fcntl(fd, F_SETLKW, ...)) system call. If the file is already locked,
+ this call blocks.
+ See option link(setlk)(OPTION_SETLK_WR) for information about making this
+ lock mandatory.
+label(OPTION_SETLK_RD)dit(bf(tt(setlk-rd)))
+ Tries to set a discretionary read lock to the whole file using the code(fcntl(fd,
+ F_SETLK, ...)) system call. If the file is already write locked, this call
+ results in an error.
+ See option link(setlk)(OPTION_SETLK_WR) for information about making this
+ lock mandatory.
+label(OPTION_SETLKW_RD)dit(bf(tt(setlkw-rd)))
+ Tries to set a discretionary waiting read lock to the whole file using the
+ code(fcntl(fd, F_SETLKW, ...)) system call. If the file is already write
+ locked, this call blocks.
+ See option link(setlk)(OPTION_SETLK_WR) for information about making this
+ lock mandatory.
+label(OPTION_FLOCK_EX)dit(bf(tt(flock-ex)))
+ Tries to set a blocking exclusive advisory lock to the file using the
+ code(flock(fd, LOCK_EX)) system call. Socat() hangs in this call if the file
+ is locked by another process.
+label(OPTION_FLOCK_EX_NB)dit(bf(tt(flock-ex-nb)))
+ Tries to set a nonblocking exclusive advisory lock to the file using the
+ code(flock(fd, LOCK_EX|LOCK_NB)) system call. If the file is already locked,
+ this option results in an error.
+label(OPTION_FLOCK_SH)dit(bf(tt(flock-sh)))
+ Tries to set a blocking shared advisory lock to the file using the
+ code(flock(fd, LOCK_SH)) system call. Socat() hangs in this call if the file
+ is locked by another process.
+label(OPTION_FLOCK_SH_NB)dit(bf(tt(flock-sh-nb)))
+ Tries to set a nonblocking shared advisory lock to the file using the
+ code(flock(fd, LOCK_SH|LOCK_NB)) system call. If the file is already locked,
+ this option results in an error.
+label(OPTION_LOCK)dit(bf(tt(lock)))
+ Sets a blocking lock on the file. Uses the setlk or flock mechanism
+ depending on availability on the particular platform. If both are available,
+ the POSIX variant (setlkw) is used.
+label(OPTION_USER)dit(bf(tt(user=<user>)))
+ Sets the link(<user>)(TYPE_USER) (owner) of the stream.
+ If the address is member of the NAMED option group,
+ socat() uses the code(chown()) system call after opening the
+ file or binding to the unixdomain() socket (race condition!).
+ Without filesystem entry, socat() sets the user of the stream
+ using the code(fchown()) system call.
+ These calls might require root privilege.
+label(OPTION_USER_LATE)dit(bf(tt(user-late=<user>)))
+ Sets the owner of the fd to link(<user>)(TYPE_USER) with the code(fchown())
+ system call after opening
+ or connecting the channel.
+ This is useful only on file system entries.
+label(OPTION_GROUP)dit(bf(tt(group=<group>)))
+ Sets the link(<group>)(TYPE_GROUP) of the stream.
+ If the address is member of the NAMED option group,
+ socat() uses the code(chown()) system call after opening the
+ file or binding to the unixdomain() socket (race condition!).
+ Without filesystem entry, socat() sets the group of the stream
+ with the code(fchown()) system call.
+ These calls might require group membership or root privilege.
+label(OPTION_GROUP_LATE)dit(bf(tt(group-late=<group>)))
+ Sets the group of the fd to link(<group>)(TYPE_GROUP) with the
+ code(fchown()) system call after opening
+ or connecting the channel.
+ This is useful only on file system entries.
+label(OPTION_MODE)dit(bf(tt(mode=<mode>)))
+ Sets the <mode> [link(mode_t)(TYPE_MODE_T)] (permissions) of the stream.
+ If the address is member of the NAMED option group and
+ uses the code(open()) or code(creat()) call, the mode is applied with these.
+ If the address is member of the NAMED option group without using these
+ system calls, socat() uses the code(chmod()) system call after opening the
+ filesystem entry or binding to the unixdomain() socket (race condition!).
+ Otherwise, socat() sets the mode of the stream
+ using code(fchmod()).
+ These calls might require ownership or root privilege.
+label(OPTION_PERM_LATE)dit(bf(tt(perm-late=<mode>)))
+ Sets the permissions of the fd to value <mode>
+ [link(mode_t)(TYPE_MODE_T)] using the code(fchmod()) system call after
+ opening or connecting the channel.
+ This is useful only on file system entries.
+label(OPTION_APPEND)dit(bf(tt(append=<bool>)))
+ Always writes data to the actual end of file.
+ If the address is member of the OPEN option group,
+ socat() uses the code(O_APPEND) flag with the code(open()) system call
+ (link(example)(EXAMPLE_OPTION_APPEND)).
+ Otherwise, socat() applies the code(fcntl(fd, F_SETFL, O_APPEND)) call.
+label(OPTION_NONBLOCK)dit(bf(tt(nonblock=<bool>)))
+ Tries to open or use file in nonblocking mode. Its only effects are that the
+ code(connect()) call of TCP addresses does not block, and that opening a
+ named pipe for reading does not block.
+ If the address is member of the OPEN option group,
+ socat() uses the code(O_NONBLOCK) flag with the code(open()) system call.
+ Otherwise, socat() applies the code(fcntl(fd, F_SETFL, O_NONBLOCK)) call.
+COMMENT(label(OPTION_NDELAY)dit(bf(tt(ndelay=<bool>)))
+ Tries to open or use file in nonblocking mode. Has no effect because socat()
+ works with code(select()).)
+COMMENT(label(OPTION_ASYNC)dit(bf(tt(async=<bool>)))
+ Enables SIGIO for this fd. Has no effect, because socat() ignores SIGIO.)
+label(OPTION_O_BINARY)dit(bf(tt(binary)))
+ Opens the file in binary mode to avoid implicit line terminator
+ conversions (Cygwin).
+label(OPTION_O_TEXT)dit(bf(tt(text)))
+ Opens the file in text mode to force implicit line terminator conversions
+ (Cygwin).
+label(OPTION_O_NOINHERIT)dit(bf(tt(noinherit)))
+ Does not keep this file open in a spawned process (Cygwin).
+label(OPTION_COOL_WRITE)dit(bf(tt(cool-write)))
+ Takes it easy when write fails with EPIPE or ECONNRESET and logs the message
+ with em(notice) level instead of em(error).
+ This prevents the log file from being filled with useless error messages
+ when socat is used as a high volume server or proxy where clients often
+ abort the connection.nl()
+ This option is experimental.
+label(OPTION_END_CLOSE)dit(bf(tt(end-close)))
+ Changes the (address dependent) method of ending a connection to just close
+ the file descriptors. This is useful when the connection is to be reused by
+ or shared with other processes (link(example)(EXAMPLE_END_CLOSE)).nl()
+ Normally, socket connections will be ended with tt(shutdown(2)) which
+ terminates the socket even if it is shared by multiple processes.
+ tt(close(2)) "unlinks" the socket from the process but keeps it active as
+ long as there are still links from other processes.nl()
+ 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.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_NAMED)em(bf(NAMED option group))
+
+These options work on file system entries.nl()
+See also options link(user)(OPTION_USER), link(group)(OPTION_GROUP), and
+link(mode)(OPTION_MODE).
+
+startdit()
+label(OPTION_USER_EARLY)dit(bf(tt(user-early=<user>)))
+ Changes the link(<user>)(TYPE_USER) (owner) of the file system entry before
+ accessing it, using the
+ code(chown()) system call. This call might require root privilege.
+label(OPTION_GROUP_EARLY)dit(bf(tt(group-early=<group>)))
+ Changes the link(<group>)(TYPE_GROUP) of the file system entry before
+ accessing it, using the
+ code(chown()) system call. This call might require group membership or root
+ privilege.
+label(OPTION_PERM_EARLY)dit(bf(tt(perm-early=<mode>)))
+ Changes the <mode> [link(mode_t)(TYPE_MODE_T)] of the file system entry
+ before accessing it, using the
+ code(chmod()) system call. This call might require ownership or root
+ privilege.
+label(OPTION_UMASK)dit(bf(tt(umask=<mode>)))
+ Sets the umask of the process to <mode> [link(mode_t)(TYPE_MODE_T)] before
+ accessing the file system entry (useful
+ with unixdomain() sockets!). This call might affect all further operations
+ of the socat() process!
+label(OPTION_UNLINK_EARLY)dit(bf(tt(unlink-early)))
+ Unlinks (removes) the file before opening it and even before applying
+ user-early etc.
+label(OPTION_UNLINK)dit(bf(tt(unlink)))
+ Unlinks (removes) the file before accessing it, but after user-early etc.
+label(OPTION_UNLINK_LATE)dit(bf(tt(unlink-late)))
+ Unlinks (removes) the file after opening it to make it inaccessible for
+ other processes after a short race condition.
+label(OPTION_UNLINK_CLOSE)dit(bf(tt(unlink-close)))
+ Removes the addresses file system entry when closing the address.
+ For link(named pipes)(ADDRESS_NAMED_PIPE),
+ link(listening unix domain sockets)(ADDRESS_UNIX_LISTEN),
+ and the link(symbolic links)(OPTION_SYMBOLIC_LINK) of link(pty addresses)(ADDRESS_PTY),
+ the default is 1; for link(created files)(ADDRESS_CREAT),
+ link(opened files)(ADDRESS_OPEN),
+ link(generic opened files)(ADDRESS_GOPEN), and
+ link(client unix domain sockets)(ADDRESS_UNIX_CONNECT) the default is 0.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_OPEN)em(bf(OPEN option group))
+
+The OPEN group options allow to set flags with the code(open()) system call.
+E.g., option `creat' sets the code(O_CREAT) flag.nl()
+See also options link(append)(OPTION_APPEND) and
+link(nonblock)(OPTION_NONBLOCK).
+startdit()
+label(OPTION_CREAT)dit(bf(tt(creat=<bool>)))
+ Creates the file if it does not exist (link(example)(EXAMPLE_OPTION_CREAT)).
+label(OPTION_DSYNC)dit(bf(tt(dsync=<bool>)))
+ Blocks code(write()) calls until metainfo is physically written to media.
+label(OPTION_EXCL)dit(bf(tt(excl=<bool>)))
+ With option creat, if file exists this is an error.
+label(OPTION_LARGEFILE)dit(bf(tt(largefile=<bool>)))
+ On 32 bit systems, allows a file larger than 2^31 bytes.
+label(OPTION_O_NOATIME)dit(bf(tt(noatime)))
+ Sets the O_NOATIME options, so reads do not change the access timestamp.
+label(OPTION_NOCTTY)dit(bf(tt(noctty=<bool>)))
+ Does not make this file the controlling terminal.
+label(OPTION_NOFOLLOW)dit(bf(tt(nofollow=<bool>)))
+ Does not follow symbolic links.
+label(OPTION_NSHARE)dit(bf(tt(nshare=<bool>)))
+ Does not allow to share this file with other processes.
+label(OPTION_RSHARE)dit(bf(tt(rshare=<bool>)))
+ Does not allow other processes to open this file for writing.
+label(OPTION_RSYNC)dit(bf(tt(rsync=<bool>)))
+ Blocks code(write()) until metainfo is physically written to media.
+label(OPTION_SYNC)dit(bf(tt(sync=<bool>)))
+ Blocks code(write()) until data is physically written to media.
+COMMENT(label(OPTION_DEFER)dit(bf(tt(defer=<bool>)))
+ Temporarily stores write data in paging space.)
+COMMENT(label(OPTION_DELAY)dit(bf(tt(delay=<bool>)))
+ Blocks code(open()) until share conditions are fulfilled.)
+COMMENT(label(OPTION_DIRECT)dit(bf(tt(direct=<bool>))))
+COMMENT(label(OPTION_DIRECTORY)dit(bf(tt(directory=<bool>)))
+ Fails if file is not a directory. Not useful with socat().)
+label(OPTION_RDONLY)dit(bf(tt(rdonly=<bool>)))
+ Opens the file for reading only.
+COMMENT(label(OPTION_RDWR)dit(bf(tt(rdwr=<bool>)))
+ Opens the file for reading and writing.)
+label(OPTION_WRONLY)dit(bf(tt(wronly=<bool>)))
+ Opens the file for writing only.
+label(OPTION_TRUNC)dit(bf(tt(trunc)))
+ Truncates the file to size 0 during opening it.
+enddit()
+
+
+startdit()enddit()nl()
+
+
+label(GROUP_REG)em(bf(REG and BLK option group))
+
+These options are usually applied to a unix() file descriptor, but their
+semantics make sense only on a file supporting random access.
+startdit()
+label(OPTION_SEEK)dit(bf(tt(seek=<offset>)))
+ Applies the code(lseek(fd, <offset>, SEEK_SET)) (or code(lseek64)) system
+ call, thus positioning the file pointer absolutely to <offset>
+ [link(off_t)(TYPE_OFF) or link(off64_t)(TYPE_OFF64)].
+label(OPTION_SEEK_CUR)dit(bf(tt(seek-cur=<offset>)))
+ Applies the code(lseek(fd, <offset>, SEEK_CUR)) (or code(lseek64)) system
+ call, thus positioning the file pointer <offset> [link(off_t)(TYPE_OFF) or
+ link(off64_t)(TYPE_OFF64)] bytes relatively to its current position (which
+ is usually 0).
+label(OPTION_SEEK_END)dit(bf(tt(seek-end=<offset>)))
+ Applies the code(lseek(fd, <offset>, SEEK_END)) (or code(lseek64)) system
+ call, thus positioning the file pointer <offset> [link(off_t)(TYPE_OFF) or
+ link(off64_t)(TYPE_OFF64)] bytes relatively to the files current end.
+label(OPTION_FTRUNCATE)dit(bf(tt(ftruncate=<offset>)))
+ Applies the code(ftruncate(fd, <offset>))
+ (or code(ftruncate64) if available) system call, thus
+ truncating the file at the position <offset> [link(off_t)(TYPE_OFF) or
+ link(off64_t)(TYPE_OFF64)].
+
+label(OPTION_EXT2_SECRM_FL)dit(bf(tt(secrm=<bool>)))
+label(OPTION_EXT2_UNRM)dit(bf(tt(unrm=<bool>)))
+label(OPTION_EXT2_COMPR)dit(bf(tt(compr=<bool>)))
+label(OPTION_EXT2_SYNC)dit(bf(tt(ext2-sync=<bool>)))
+label(OPTION_EXT2_IMMUTABLE)dit(bf(tt(immutable=<bool>)))
+label(OPTION_EXT2_APPEND)dit(bf(tt(ext2-append=<bool>)))
+label(OPTION_EXT2_NODUMP)dit(bf(tt(nodump=<bool>)))
+label(OPTION_EXT2_NOATIME)dit(bf(tt(ext2-noatime=<bool>)))
+label(OPTION_EXT2_JOURNAL_DATA)dit(bf(tt(journal-data=<bool>)))
+label(OPTION_EXT2_NOTAIL)dit(bf(tt(notail=<bool>)))
+label(OPTION_EXT2_DIRSYNC)dit(bf(tt(dirsync=<bool>)))
+ These options change non standard file attributes on operating systems and
+ file systems that support these features, like Linux with ext2fs,
+ ext3fs, or reiserfs. See man 1 chattr for information on these options.
+ Please note that there might be a race condition between creating the file
+ and applying these options.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_PROCESS)em(bf(PROCESS option group))
+
+Options of this group change the process properties instead of just affecting
+one data channel.
+For EXEC and SYSTEM addresses and for LISTEN and CONNECT type addresses with
+option FORK,
+these options apply to the child processes instead of the main socat process.
+startdit()
+label(OPTION_CHROOT)dit(bf(tt(chroot=<directory>)))
+ Performs a code(chroot()) operation to link(<directory>)(TYPE_DIRECTORY)
+ after processing the address (link(example)(EXAMPLE_OPTION_CHROOT)). This call might require root privilege.
+label(OPTION_CHROOT_EARLY)dit(bf(tt(chroot-early=<directory>)))
+ Performs a code(chroot()) operation to link(<directory>)(TYPE_DIRECTORY)
+ before opening the address. This call might require root privilege.
+label(OPTION_SETGID)dit(bf(tt(setgid=<group>)))
+ Changes the primary link(<group>)(TYPE_GROUP) of the process after
+ processing the address. This call might require root privilege.
+label(OPTION_SETGID_EARLY)dit(bf(tt(setgid-early=<group>)))
+ Changes the primary link(<group>)(TYPE_GROUP) of the process before opening
+ the address. This call might require root privilege.
+label(OPTION_SETUID)dit(bf(tt(setuid=<user>)))
+ Changes the link(<user>)(TYPE_USER) (owner) of the process after processing
+ the address. This call might require root privilege.
+label(OPTION_SETUID_EARLY)dit(bf(tt(setuid-early=<user>)))
+ Changes the link(<user>)(TYPE_USER) (owner) of the process before opening
+ the address. This call might require root privilege.
+label(OPTION_SUBSTUSER)dit(bf(tt(su=<user>)))
+ Changes the link(<user>)(TYPE_USER) (owner) and groups of the process after
+ processing the address (link(example)(EXAMPLE_OPTION_SUBSTUSER)). This call might require root privilege.
+label(OPTION_SUBSTUSER_DELAYED)dit(bf(tt(su-d=<user>)))
+ Short name for bf(tt(substuser-delayed)).
+ Changes the link(<user>)(TYPE_USER)
+ (owner) and groups of the process after processing the address (link(example)(EXAMPLE_OPTION_SUBSTUSER_DELAYED)).
+ The user and his groups are retrieved em(before) a possible
+ code(chroot()). This call might require root privilege.
+label(OPTION_SETPGID)dit(bf(tt(setpgid=<pid_t>)))
+ Makes the process a member of the specified process group
+ link(<pid_t>)(TYPE_PID_T). If no value
+ is given, or if the value is 0 or 1, the process becomes leader of a new
+ process group.
+label(OPTION_SETSID)dit(bf(tt(setsid)))
+ Makes the process the leader of a new session (link(example)(EXAMPLE_OPTION_SETSID)).
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_READLINE)em(bf(READLINE option group))
+
+These options apply to the readline address type.
+startdit()
+label(OPTION_HISTORY)dit(bf(tt(history=<filename>)))
+ Reads and writes history from/to link(<filename>)(TYPE_FILENAME) (link(example)(EXAMPLE_OPTION_HISTORY)).
+label(OPTION_NOPROMPT)dit(bf(tt(noprompt)))
+ Since version 1.4.0, socat per default tries to determine a prompt -
+ that is then passed to the readline call - by remembering the last
+ incomplete line of the output. With this option, socat does not pass a
+ prompt to readline, so it begins line editing in the first column
+ of the terminal.
+label(OPTION_NOECHO)dit(bf(tt(noecho=<pattern>)))
+ Specifies a regular pattern for a prompt that prevents the following input
+ line from being displayed on the screen and from being added to the history.
+ The prompt is defined as the text that was output to the readline address
+ after the lastest newline character and before an input character was
+ typed. The pattern is a regular expression, e.g.
+ "^[Pp]assword:.*$" or "([Uu]ser:|[Pp]assword:)". See regex(7) for details.
+ (link(example)(EXAMPLE_OPTION_NOECHO))
+label(OPTION_PROMPT)dit(bf(tt(prompt=<string>)))
+ Passes the string as prompt to the readline function. readline prints this
+ prompt when stepping through the history. If this string matches a constant
+ prompt issued by an interactive program on the other socat address,
+ consistent look and feel can be archieved.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_APPLICATION)em(bf(APPLICATION option group))
+
+This group contains options that work at data level.
+Note that these options only apply to the "raw" data transferred by socat,
+but not to protocol data used by addresses like
+link(PROXY)(ADDRESS_PROXY_CONNECT).
+startdit()
+label(OPTION_CR)dit(bf(tt(cr)))
+ Converts the default line termination character NL ('\n', 0x0a) to/from CR
+ ('\r', 0x0d) when writing/reading on this channel.
+label(OPTION_CRNL)dit(bf(tt(crnl)))
+ Converts the default line termination character NL ('\n', 0x0a) to/from CRNL
+ ("\r\n", 0x0d0a) when writing/reading on this channel (link(example)(EXAMPLE_OPTION_CRNL)).
+ Note: socat simply strips all CR characters.
+label(OPTION_IGNOREEOF)dit(bf(tt(ignoreeof)))
+ When EOF occurs on this channel, socat() ignores it and tries to read more
+ data (like "tail -f") (link(example)(EXAMPLE_OPTION_IGNOREEOF)).
+label(OPTION_READBYTES)dit(bf(tt(readbytes=<bytes>)))
+ socat() reads only so many bytes from this address (the address provides
+ only so many bytes for transfer and pretends to be at EOF afterwards).
+ Must be greater than 0.
+label(OPTION_LOCKFILE)dit(bf(tt(lockfile=<filename>)))
+ If lockfile exists, exits with error. If lockfile does not exist, creates it
+ and continues, unlinks lockfile on exit.
+label(OPTION_WAITLOCK)dit(bf(tt(waitlock=<filename>)))
+ If lockfile exists, waits until it disappears. When lockfile does not exist,
+ creates it and continues, unlinks lockfile on exit.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_SOCKET)em(bf(SOCKET option group))
+
+These options are intended for all kinds of sockets, e.g. IP or unixdomain(). Most are applied with a code(setsockopt()) call.
+startdit()
+label(OPTION_BIND)dit(bf(tt(bind=<sockname>)))
+ Binds the socket to the given socket address using the code(bind()) system
+ call. The form of <sockname> is socket domain dependent:
+ IP4 and IP6 allow the form [hostname|hostaddress][:(service|port)] (link(example)(EXAMPLE_OPTION_BIND_TCP4)),
+ unixdomain() sockets require link(<filename>)(TYPE_FILENAME).
+label(OPTION_CONNECT_TIMEOUT)dit(bf(tt(connect-timeout=<seconds>)))
+ Abort the connection attempt after <seconds> [link(timeval)(TYPE_TIMEVAL)]
+ with error status.
+label(OPTION_INTERFACE)dit(bf(tt(interface=<interface>)))
+ Binds the socket to the given link(<interface>)(TYPE_INTERFACE).
+ This option might require root privilege.
+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.
+label(OPTION_DEBUG)dit(bf(tt(debug)))
+ Enables socket debugging.
+label(OPTION_DONTROUTE)dit(bf(tt(dontroute)))
+ Only communicates with directly connected peers, does not use routers.
+label(OPTION_KEEPALIVE)dit(bf(tt(keepalive)))
+ Enables sending keepalives on the socket.
+label(OPTION_LINGER)dit(bf(tt(linger=<seconds>)))
+ Blocks code(shutdown()) or code(close()) until data transfers have finished
+ or the given timeout [link(int)(TYPE_INT)] expired.
+COMMENT(label(OPTION_NOREUSEADDR)dit(bf(tt(noreuseaddr)))
+ Set the code(SO_NOREUSEADDR) socket option.)
+label(OPTION_OOBINLINE)dit(bf(tt(oobinline)))
+ Places out-of-band data in the input data stream.
+label(OPTION_PRIORITY)dit(bf(tt(priority=<priority>)))
+ Sets the protocol defined <priority> [link(<int>)(TYPE_INT)] for outgoing
+ packets.
+label(OPTION_RCVBUF)dit(bf(tt(rcvbuf=<bytes>)))
+ Sets the size of the receive buffer after the code(socket()) call to
+ <bytes> [link(int)(TYPE_INT)]. With TCP
+ sockets, this value corresponds to the socket's maximal window size.
+label(OPTION_RCVBUF_LATE)dit(bf(tt(rcvbuf-late=<bytes>)))
+ Sets the size of the receive buffer when the socket is already
+ connected to <bytes> [link(int)(TYPE_INT)].
+ With TCP sockets, this value corresponds to the socket's
+ maximal window size.
+label(OPTION_RCVLOWAT)dit(bf(tt(rcvlowat=<bytes>)))
+ Specifies the minimum number of received bytes [link(int)(TYPE_INT)] until
+ the socket layer will pass the buffered data to socat().
+label(OPTION_RCVTIMEO)dit(bf(tt(rcvtimeo=<seconds>)))
+ Sets the receive timeout [link(timeval)(TYPE_TIMEVAL)].
+label(OPTION_REUSEADDR)dit(bf(tt(reuseaddr)))
+ Allows other sockets to bind to an address even if parts of it (e.g. the
+ local port) are already in use by socat() (link(example)(EXAMPLE_OPTION_REUSEADDR)).
+label(OPTION_SNDBUF)dit(bf(tt(sndbuf=<bytes>)))
+ Sets the size of the send buffer after the code(socket()) call to
+ <bytes> [link(int)(TYPE_INT)].
+label(OPTION_SNDBUF_LATE)dit(bf(tt(sndbuf-late=<bytes>)))
+ Sets the size of the send buffer when the socket is connected to
+ <bytes> [link(int)(TYPE_INT)].
+label(OPTION_SNDLOWAT)dit(bf(tt(sndlowat=<bytes>)))
+ Specifies the minimum number of bytes in the send buffer until the socket
+ layer will send the data to <bytes> [link(int)(TYPE_INT)].
+label(OPTION_SNDTIMEO)dit(bf(tt(sndtimeo=<seconds>)))
+ Sets the send timeout to seconds [link(timeval)(TYPE_TIMEVAL)].
+label(OPTION_TYPE)dit(bf(tt(type=<type>)))
+ Sets the type of the socket, usually as argument to the code(socket()) or
+ code(socketpair()) call, to <type> [link(int)(TYPE_INT)].
+ Under Linux, 1 means stream oriented socket, 2 means datagram socket, and 3
+ means raw socket.
+COMMENT(label(OPTION_USELOOPBACK)dit(bf(tt(useloopback)))
+ Sets the code(SO_USELOOPBACK) socket option.)
+COMMENT(label(OPTION_ACCEPTCONN)dit(bf(tt(acceptconn)))
+ Tries to set the code(SO_ACCEPTCONN) socket option.)
+COMMENT(label(OPTION_ATTACHFILTER)dit(bf(tt(attachfilter)))
+ Tries to set the code(SO_ATTACH_FILTER) socket option.)
+COMMENT(label(OPTION_AUDIT)dit(bf(tt(audit)))
+ Sets the code(SO_AUDIT) socket option.)
+COMMENT(label(OPTION_CHSUMRECV)dit(bf(tt(cksumrecv)))
+ Sets the code(SO_CKSUMRECV) socket option.)
+COMMENT(label(OPTION_DETACHFILTER)dit(bf(tt(detachfilter)))
+ Tries to set the code(SO_DETACH_FILTER) socket option.)
+COMMENT(label(OPTION_DGRAMERRIND)dit(bf(tt(dgramerrind)))
+ Sets the code(SO_DGRAM_ERRIND) socket option.)
+COMMENT(label(OPTION_DONTLINGER)dit(bf(tt(dontlinger)))
+ Sets the code(SO_DONTLINGER) socket option.)
+COMMENT(label(OPTION_ERROR)dit(bf(tt(error)))
+ Tries to set this read only socket option.)
+COMMENT(label(OPTION_FIOSETOWN)dit(bf(tt(fiosetown=<pid_t>)))
+ Sets the receiver of SIGIO.)
+COMMENT(label(OPTION_KERNACCEPT)dit(bf(tt(kernaccept)))
+ Sets the code(SO_KERNACCEPT) socket option.)
+COMMENT(label(OPTION_NOCHECK)dit(bf(tt(nocheck)))
+ Sets the code(SO_NO_CHECK) socket option. Undocumented...)
+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)))
+ Set the code(SO_SECURITY_AUTHENTICATION) socket option.)
+COMMENT(label(OPTION_SECURITYENCRYPTIONNETWORK)dit(bf(tt(securityencryptionnetwork)))
+ Set the code(SO_SECURITY_ENCRYPTION_NETWORK) socket option.)
+COMMENT(label(OPTION_SECURITYENCRYPTIONTRANSPORT)dit(bf(tt(securityencryptiontransport)))
+ Set the code(SO_SECURITY_ENCRYPTION_TRANSPORT) socket option.)
+COMMENT(label(OPTION_SIOCSPGRP)dit(bf(tt(siocspgrp=<pid_t>)))
+ 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=<string>)))
+ Forces the use of the specified IP version. <string> can be
+ something like "ip4" or "ip6".
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_SOCK_UNIX)em(bf(UNIX option group))
+
+These options apply to UNIX domain based addresses.
+startdit()
+label(OPTION_UNIX_TIGHTSOCKLEN)dit(bf(tt(unix-tightsocklen=[0|1])))
+ On socket operations, pass a socket address length that does not include the
+ whole code(struct sockaddr_un) record but (besides other components) only
+ the relevant part of the filename or abstract string. Default is 1.
+enddit()
+
+label(GROUP_IP4)
+label(GROUP_IP)em(bf(IP4 and IP6 option groups))
+
+These options can be used with IPv4 and IPv6 based sockets.
+startdit()
+label(OPTION_TOS)dit(bf(tt(tos=<tos>)))
+ Sets the TOS (type of service) field of outgoing packets to <tos>
+ [link(byte)(TYPE_BYTE)] (see RFC 791).
+label(OPTION_TTL)dit(bf(tt(ttl=<ttl>)))
+ Sets the TTL (time to live) field of outgoing packets to <ttl>
+ [link(byte)(TYPE_BYTE)].
+label(OPTION_IPOPTIONS)dit(bf(tt(ipoptions=<data>)))
+ 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()
+ IP options are defined in RFC 791. COMMENT(, RFC 2113)nl()
+COMMENT( x00 end of option list
+ x01 no operation (nop)
+ x0211 security
+ x03 loose source route
+ x09 strict source route
+ x07 record route
+ x0804 stream ID
+ x44 internet timestamp)
+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)))
+ Tell the raw socket that the application data includes the IP header.)
+COMMENT(label(OPTION_IP_MULTICAST_LOOP)dit(bf(tt(multicastloop)))
+ Allow looping back outgoing multicast to the local interface.)
+COMMENT(label(OPTION_IP_MULTICAST_TTL)dit(bf(tt(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)))
+ 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)))
+ Set the IP_RETOPTS socket option.)
+COMMENT(label(OPTION_ROUTERALERT)dit(bf(tt(routeralert)))
+ Set the IP_ROUTER_ALERT socket option.)
+label(OPTION_IP_ADD_MEMBERSHIP)
+dit(bf(tt(ip-add-membership=<multicast-address:interface-address>)))
+dit(bf(tt(ip-add-membership=<multicast-address:interface-name>)))
+dit(bf(tt(ip-add-membership=<multicast-address:interface-index>)))
+dit(bf(tt(ip-add-membership=<multicast-address:interface-address:interface-name>)))
+dit(bf(tt(ip-add-membership=<multicast-address:interface-address:interface-index>)))
+ Makes the socket member of the specified multicast group. This is currently
+ only implemented for IPv4. The option takes the IP address of the multicast
+ group and info about the desired network interface. The most common syntax
+ is the first one, while the others are only available on systems that
+ provide tt(struct mreqn) (Linux).nl()
+ The indices of active network interfaces can be shown using the utility
+ procan().
+label(OPTION_IP_MULTICAST_IF)
+dif(bf(tt(ip-multicast-if=<hostname>)))
+ Specifies hostname or address of the network interface to be used for
+ multicast traffic.
+label(OPTION_IP_MULTICAST_LOOP)
+dif(bf(tt(ip-multicast-loop=<bool>)))
+ Specifies if outgoing multicast traffic should loop back to the interface.
+label(OPTION_IP_MULTICAST_TTL)
+dif(bf(tt(ip-multicast-ttl=<byte>)))
+ Sets the TTL used for outgoing multicast traffic. Default is 1.
+label(OPTION_RES_DEBUG)dit(bf(tt(res-debug)))
+label(OPTION_RES_AAONLY)dit(bf(tt(res-aaonly)))
+label(OPTION_RES_USEVC)dit(bf(tt(res-usevc)))
+label(OPTION_RES_PRIMARY)dit(bf(tt(res-primary)))
+label(OPTION_RES_IGNTC)dit(bf(tt(res-igntc)))
+label(OPTION_RES_RECURSE)dit(bf(tt(res-recurse)))
+label(OPTION_RES_DEFNAMES)dit(bf(tt(res-defnames)))
+label(OPTION_RES_STAYOPEN)dit(bf(tt(res-stayopen)))
+label(OPTION_RES_DNSRCH)dit(bf(tt(res-dnsrch)))
+ These options set the corresponding resolver (name resolution) option flags.
+ Append "=0" to clear a default option. See man resolver(5) for more
+ information on these options. Note: these options are valid only for the
+ address they are applied to.
+
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_IP6)em(bf(IP6 option group))
+
+These options can only be used on IPv6 based sockets. See link(IP
+options)(GROUP_IP) for options that can be applied to both IPv4 and IPv6
+sockets.
+startdit()
+label(OPTION_IPV6_V6ONLY)dit(bf(tt(ipv6only=<bool>)))
+ 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.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_TCP)em(bf(TCP option group))
+
+These options may be applied to TCP sockets. They work by invoking code(setsockopt()) with the appropriate parameters.
+startdit()
+label(OPTION_CORK)dit(bf(tt(cork)))
+ Doesn't send packets smaller than MSS (maximal segment size).
+label(OPTION_DEFER-ACCEPT)dit(bf(tt(defer-accept)))
+ While listening, accepts connections only when data from the peer arrived.
+label(OPTION_KEEPCNT)dit(bf(tt(keepcnt=<count>)))
+ Sets the number of keepalives before shutting down the socket to
+ <count> [link(int)(TYPE_INT)].
+label(OPTION_KEEPIDLE)dit(bf(tt(keepidle=<seconds>)))
+ Sets the idle time before sending the first keepalive to <seconds>
+ [link(int)(TYPE_INT)].
+label(OPTION_KEEPINTVL)dit(bf(tt(keepintvl=<seconds>)))
+ Sets the intervall between two keepalives to <seconds>
+ [link(int)(TYPE_INT)].
+label(OPTION_LINGER2)dit(bf(tt(linger2=<seconds>)))
+ Sets the time to keep the socket in FIN-WAIT-2 state to <seconds>
+ [link(int)(TYPE_INT)].
+label(OPTION_MSS)dit(bf(tt(mss=<bytes>)))
+ Sets the MSS (maximum segment size) after the code(socket()) call to <bytes>
+ [link(int)(TYPE_INT)]. This
+ value is then proposed to the peer with the SYN or SYN/ACK packet
+ (link(example)(EXAMPLE_OPTION_MSS)).
+label(OPTION_MSS_LATE)dit(bf(tt(mss-late=<bytes>)))
+ Sets the MSS of the socket after connection has been established to <bytes>
+ [link(int)(TYPE_INT)].
+label(OPTION_NODELAY)dit(bf(tt(nodelay)))
+ Turns off the Nagle algorithm for measuring the RTT (round trip time).
+label(OPTION_RFC1323)dit(bf(tt(rfc1323)))
+ Enables RFC1323 TCP options: TCP window scale, round-trip time measurement
+ (RTTM), and protect against wrapped sequence numbers (PAWS) (AIX).
+label(OPTION_STDURG)dit(bf(tt(stdurg)))
+ Enables RFC1122 compliant urgent pointer handling (AIX).
+label(OPTION_SYNCNT)dit(bf(tt(syncnt=<count>)))
+ Sets the maximal number of SYN retransmits during connect to <count>
+ [link(int)(TYPE_INT)].
+COMMENT(label(OPTION_INFO)dit(bf(tt(info)))
+ Tries to set the read-only TCP_INFO socket option.)
+COMMENT(label(OPTION_WINDOW_CLAMP)dit(bf(tt(window-clamp)))
+ Sets the TCP_WINDOW_CLAMP socket option.)
+label(OPTION_TCP_MD5SIG)dit(bf(tt(md5sig)))
+ Enables generation of MD5 digests on the packets (FreeBSD).
+label(OPTION_TCP_NOOPT)dit(bf(tt(noopt)))
+ Disables use of TCP options (FreeBSD, MacOSX).
+label(OPTION_TCP_NOPUSH)dit(bf(tt(nopush)))
+ sets the TCP_NOPUSH socket option (FreeBSD, MacOSX).
+label(OPTION_TCP_SACK_DISABLE)dit(bf(tt(sack-disable)))
+ Disables use the selective acknowledge feature (OpenBSD).
+label(OPTION_TCP_SIGNATURE_ENABLE)dit(bf(tt(signature-enable)))
+ Enables generation of MD5 digests on the packets (OpenBSD).
+label(OPTION_TCP_ABORT_THRESHOLD)dit(bf(tt(abort-threshold=<milliseconds>)))
+ Sets the time to wait for an answer of the peer on an established connection
+ (HP-UX).
+label(OPTION_TCP_CONN_ABORT_THRESHOLD)dit(bf(tt(conn-abort-threshold=<milliseconds>)))
+ Sets the time to wait for an answer of the server during the initial connect
+ (HP-UX).
+label(OPTION_TCP_KEEPINIT)dit(bf(tt(keepinit)))
+ Sets the time to wait for an answer of the server during connect() before
+ giving up. Value in half seconds, default is 150 (75s) (Tru64).
+label(OPTION_TCP_PAWS)dit(bf(tt(paws)))
+ Enables the "protect against wrapped sequence numbers" feature (Tru64).
+label(OPTION_TCP_SACKENA)dit(bf(tt(sackena)))
+ Enables selective acknowledge (Tru64).
+label(OPTION_TCP_TSOPTENA)dit(bf(tt(tsoptena)))
+ Enables the time stamp option that allows RTT recalculation on existing
+ connections (Tru64).
+enddit()
+
+startdit()enddit()nl()
+
+
+em(bf(UDP and TCP option groups))
+
+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.
+startdit()
+label(OPTION_SOURCEPORT)dit(bf(tt(sourceport=<port>)))
+ For outgoing (client) TCP and UDP connections, it sets the source
+ link(<port>)(TYPE_PORT) using an extra code(bind()) call.
+ With TCP or UDP listen addresses, socat immediately shuts down the
+ connection if the client does not use this sourceport (link(example)(EXAMPLE_OPTION_SOURCEPORT)).
+label(OPTION_LOWPORT)dit(bf(tt(lowport)))
+ Outgoing (client) TCP and UDP connections with this option use
+ an unused random source port between 640 and 1023 incl. On UNIX class operating
+ systems, this requires root privilege, and thus indicates that the
+ client process is authorized by local root.
+ TCP and UDP listen addresses with this option immediately shut down the
+ connection if the client does not use a sourceport <= 1023.
+ This mechanism can provide limited authorization under some circumstances.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_SOCKS)em(bf(SOCKS option group))
+
+When using SOCKS type addresses, some socks specific options can be set.
+startdit()
+label(OPTION_SOCKSPORT)dit(bf(tt(socksport=<tcp service>)))
+ Overrides the default "socks" service or port 1080 for the socks server
+ port with link(<TCP service>)(TYPE_TCP_SERVICE).
+label(OPTION_SOCKSUSER)dit(bf(tt(socksuser=<user>)))
+ Sends the <user> [link(string)(TYPE_STRING)] in the username field to the
+ socks server. Default is the actual user name ($LOGNAME or $USER) (link(example)(EXAMPLE_OPTION_SOCKSUSER)).
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_HTTP)em(bf(HTTP option group))
+
+Options that can be provided with HTTP type addresses. The only HTTP address
+currently implemented is link(proxy-connect)(ADDRESS_PROXY_CONNECT).
+
+startdit()
+label(OPTION_PROXYPORT)dit(bf(tt(proxyport=<TCP service>)))
+ Overrides the default HTTP proxy port 8080 with
+ link(<TCP service>)(TYPE_TCP_SERVICE).
+label(OPTION_IGNORECR)dit(bf(tt(ignorecr)))
+ The HTTP protocol requires the use of CR+NL as line terminator. When a proxy
+ server violates this standard, socat might not understand its answer.
+ This option directs socat to interprete NL as line terminator and
+ to ignore CR in the answer. Nevertheless, socat sends CR+NL to the proxy.
+label(OPTION_PROXY_AUTHORIZATION)dit(bf(tt(proxyauth=<username>:<password>)))
+ Provide "basic" authentication to the proxy server. The argument to the
+ option is used with a "Proxy-Authorization: Base" header in base64 encoded
+ form.nl()
+ Note: username and password are visible for every user on the local machine
+ in the process list; username and password are transferred to the proxy
+ server unencrypted (base64 encoded) and might be sniffed.
+label(OPTION_PROXY_RESOLVE)dit(bf(tt(resolve)))
+ Per default, socat sends to the proxy a CONNECT request containing the
+ target hostname. With this option, socat resolves the hostname locally and
+ sends the IP address. Please note that, according to RFC 2396, only name
+ resolution to IPv4 addresses is implemented.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_RANGE)em(bf(RANGE option group))
+
+These options check if a connecting client should be granted access. They can
+be applied to listening and receiving network sockets. tcp-wrappers options
+fall into this group.
+startdit()
+label(OPTION_RANGE)dit(bf(tt(range=<address-range>)))
+ After accepting a connection, tests if the peer is within em(range). For
+ IPv4 addresses, address-range takes the form address/bits, e.g.
+ 10.0.0.0/8, or address:mask, e.g. 10.0.0.0:255.0.0.0 (link(example)(EXAMPLE_OPTION_RANGE)); for IPv6, it is [ip6-address/bits], e.g. [::1/128].
+ If the client address does not match, socat() issues a warning and keeps
+ listening/receiving.
+label(OPTION_TCPWRAPPERS)dit(bf(tt(tcpwrap[=<name>])))
+ Uses Wietse Venema's libwrap (tcpd) library to determine
+ if the client is allowed to connect. The configuration files are
+ /etc/hosts.allow and /etc/hosts.deny per default, see "man 5 hosts_access"
+ for more information. The optional <name> (type link(string)(TYPE_STRING))
+ is passed to the wrapper functions as daemon process name (link(example)(EXAMPLE_OPTION_TCPWRAPPERS)).
+ If omitted, the basename of socats invocation (argv[0]) is passed.
+ If both tcpwrap and range options are applied to an address, both
+ conditions must be fulfilled to allow the connection.
+label(OPTION_TCPWRAP_HOSTS_ALLOW_TABLE)dit(bf(tt(allow-table=<filename>)))
+ Takes the specified file instead of /etc/hosts.allow.
+label(OPTION_TCPWRAP_HOSTS_DENY_TABLE)dit(bf(tt(deny-table=<filename>)))
+ Takes the specified file instead of /etc/hosts.deny.
+label(OPTION_TCPWRAP_ETC)dit(bf(tt(tcpwrap-etc=<directoryname>)))
+ Looks for hosts.allow and hosts.deny in the specified directory. Is
+ overridden by options link(hosts-allow)(OPTION_TCPWRAP_HOSTS_ALLOW_TABLE)
+ and link(hosts-deny)(OPTION_TCPWRAP_HOSTS_DENY_TABLE).
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_LISTEN)em(bf(LISTEN option group))
+
+Options specific to listening sockets.
+startdit()
+label(OPTION_BACKLOG)dit(bf(tt(backlog=<count>)))
+ Sets the backlog value passed with the code(listen()) system call to <count>
+ [link(int)(TYPE_INT)]. Default is 5.
+enddit()
+startdit()enddit()nl()
+
+
+label(GROUP_CHILD)em(bf(CHILD option group))
+
+Options for addresses with multiple connections via child processes.
+startdit()
+label(OPTION_FORK)dit(bf(tt(fork)))
+ After establishing a connection, handles its channel in a child process and
+ keeps the parent process attempting to produce more connections, either by
+ listening or by connecting in a loop (link(example)(EXAMPLE_OPTION_FORK)).nl()
+ SSL-CONNECT and SSL-LISTEN differ in when they actually fork off the child:
+SSL-LISTEN forks em(before) the SSL handshake, while SSL-CONNECT forks
+em(afterwards).
+ RETRY and FOREVER options are not inherited by the child process.nl()
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_EXEC)em(bf(EXEC option group))
+
+Options for addresses that invoke a program.
+startdit()
+label(OPTION_PATH)dit(bf(tt(path=<string>)))
+ Overrides the PATH environment variable for searching the program with
+ link(<string>)(TYPE_STRING). This
+ code($PATH) value is effective in the child process too.
+label(OPTION_LOGIN)dit(bf(tt(login)))
+ Prefixes code(argv[0]) for the code(execvp()) call with '-', thus making a
+ shell behave as login shell.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_FORK)em(bf(FORK option group))
+
+EXEC or SYSTEM addresses invoke a program using a child process and transfer data between socat() and the program. The interprocess communication mechanism can be influenced with the following options. Per
+default, a code(socketpair()) is created and assigned to stdin and stdout of
+the child process, while stderr is inherited from the socat() process, and the
+child process uses file descriptors 0 and 1 for communicating with the main
+socat process.
+startdit()
+label(OPTION_NOFORK)dit(bf(tt(nofork)))
+ Does not fork a subprocess for executing the program, instead calls execvp()
+ or system() directly from the actual socat instance. This avoids the
+ overhead of another process between the program and its peer,
+ but introduces a lot of restrictions:
+ startit()
+ it() this option can only be applied to the second socat() address.
+ it() it cannot be applied to a part of a link(dual)(ADDRESS_DUAL) address.
+ it() the first socat address cannot be OPENSSL or READLINE
+ it() socat options -b, -t, -D, -l, -v, -x become useless
+ it() for both addresses, options ignoreeof, cr, and crnl become useless
+ it() for the second address (the one with option nofork), options
+ append, metaCOMMENT(async,) cloexec, flock, user, group, mode, nonblock,
+ perm-late, setlk, and setpgid cannot be applied. Some of these could be
+ used on the first address though.
+ endit()
+label(OPTION_PIPES)dit(bf(tt(pipes)))
+ Creates a pair of unnamed pipes for interprocess communication instead of a
+ socket pair.
+label(OPTION_OPENPTY)dit(bf(tt(openpty)))
+ Establishes communication with the sub process using a pseudo terminal
+ created with code(openpty()) instead of the default (socketpair or ptmx).
+label(OPTION_PTMX)dit(bf(tt(ptmx)))
+ Establishes communication with the sub process using a pseudo terminal
+ created by opening file(/dev/ptmx) or file(/dev/ptc) instead of the default
+ (socketpair).
+label(OPTION_PTY)dit(bf(tt(pty)))
+ Establishes communication with the sub process using a pseudo terminal
+ instead of a socket pair. Creates the pty with an available mechanism. If
+ openpty and ptmx are both available, it uses ptmx because this is POSIX
+ compliant (link(example)(EXAMPLE_OPTION_PTY)).
+label(OPTION_CTTY)dit(bf(tt(ctty)))
+ Makes the pty the controlling tty of the sub process (link(example)(EXAMPLE_OPTION_CTTY)).
+label(OPTION_STDERR)dit(bf(tt(stderr)))
+ Directs stderr of the sub process to its output channel by making stderr a
+ code(dup()) of stdout (link(example)(EXAMPLE_OPTION_STDERR)).
+label(OPTION_FDIN)dit(bf(tt(fdin=<fdnum>)))
+ Assigns the sub processes input channel to its file descriptor
+ link(<fdnum>)(TYPE_FDNUM)
+ instead of stdin (0). The program started from the subprocess has to use
+ this fd for reading data from socat() (link(example)(EXAMPLE_OPTION_FDIN)).
+label(OPTION_FDOUT)dit(bf(tt(fdout=<fdnum>)))
+ Assigns the sub processes output channel to its file descriptor
+ link(<fdnum>)(TYPE_FDNUM)
+ instead of stdout (1). The program started from the subprocess has to use
+ this fd for writing data to socat() (link(example)(EXAMPLE_OPTION_FDOUT)).
+label(OPTION_SIGHUP)label(OPTION_SIGINT)label(OPTION_SIGQUIT)dit(bf(tt(sighup)), bf(tt(sigint)), bf(tt(sigquit)))
+ Has socat() pass an eventual signal of this type to the sub process.
+ If no address has this option, socat terminates on these signals.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_TERMIOS)em(bf(TERMIOS option group))
+
+For addresses that work on a tty (e.g., stdio, file:/dev/tty, exec:...,pty), the terminal parameters defined in the unix() termios mechanism are made available as address option parameters.
+Please note that changes of the parameters of your interactive terminal
+remain effective after socat()'s termination, so you might have to enter "reset"
+or "stty sane" in your shell afterwards.
+For EXEC and SYSTEM addresses with option PTY,
+these options apply to the pty by the child processes.
+
+startdit()
+label(OPTION_B0)dit(bf(tt(b0)))
+ Disconnects the terminal.
+label(OPTION_B19200)dit(bf(tt(b19200)))
+ Sets the serial line speed to 19200 baud. Some other rates are possible; use
+something like tt(socat -hh |grep ' b[1-9]') to find all speeds supported by
+your implementation.nl()
+Note: On some operating systems, these options may not be
+available. Use link(ispeed)(OPTION_ISPEED) or link(ospeed)(OPTION_OSPEED)
+instead.
+label(OPTION_ECHO)dit(bf(tt(echo=<bool>)))
+ Enables or disables local echo (link(example)(EXAMPLE_OPTION_ECHO)).
+label(OPTION_ICANON)dit(bf(tt(icanon=<bool>)))
+ Sets or clears canonical mode, enabling line buffering and some special
+ characters.
+label(OPTION_RAW)dit(bf(tt(raw)))
+ Sets raw mode, thus passing input and output almost unprocessed (link(example)(EXAMPLE_OPTION_RAW)).
+label(OPTION_IGNBRK)dit(bf(tt(ignbrk=<bool>)))
+ Ignores or interpretes the BREAK character (e.g., ^C)
+label(OPTION_BRKINT)dit(bf(tt(brkint=<bool>)))
+label(OPTION_BS0)dit(bf(tt(bs0)))
+label(OPTION_BS1)dit(bf(tt(bs1)))
+label(OPTION_BSDLY)dit(bf(tt(bsdly=<0|1>)))
+label(OPTION_CLOCAL)dit(bf(tt(clocal=<bool>)))
+
+label(OPTION_CR0)label(OPTION_CR1)label(OPTION_CR2)label(OPTION_CR3)
+mancommand(\.LP)
+mancommand(\.nf)
+mancommand(\fBcr0
+cr1
+cr2
+cr3\fP)
+mancommand(\.fi)
+mancommand(\.IP)
+htmlcommand(<dt><code><strong>cr0</strong><br>
+<strong>cr1</strong><br>
+<strong>cr2</strong><br>
+<strong>cr3</strong></code><dd>)
+ Sets the carriage return delay to 0, 1, 2, or 3, respectively.
+ 0 means no delay, the other values are terminal dependent.
+
+label(OPTION_CRDLY)dit(bf(tt(crdly=<0|1|2|3>)))
+label(OPTION_CREAD)dit(bf(tt(cread=<bool>)))
+label(OPTION_CRTSCTS)dit(bf(tt(crtscts=<bool>)))
+
+label(OPTION_CS5)label(OPTION_CS6)label(OPTION_CS7)label(OPTION_CS8)
+mancommand(\.LP)
+mancommand(\.nf)
+mancommand(\fBcs5
+cs6
+cs7
+cs8\fP)
+mancommand(\.fi)
+mancommand(\.IP)
+htmlcommand(<dt><code><strong>cs5</strong><br>
+<strong>cs6</strong><br>
+<strong>cs7</strong><br>
+<strong>cs8</strong></code><dd>)
+ Sets the character size to 5, 6, 7, or 8 bits, respectively.
+
+label(OPTION_CSIZE)dit(bf(tt(csize=<0|1|2|3>)))
+label(OPTION_CSTOPB)dit(bf(tt(cstopb=<bool>)))
+ Sets two stop bits, rather than one.
+label(OPTION_VDSUSP)dit(bf(tt(dsusp=<byte>)))
+ Sets the value for the VDSUSP character that suspends the current foreground
+ process and reactivates the shell (all except Linux).
+label(OPTION_ECHOCTL)dit(bf(tt(echoctl=<bool>)))
+ Echos control characters in hat notation (e.g. ^A)
+label(OPTION_ECHOE)dit(bf(tt(echoe=<bool>)))
+label(OPTION_ECHOK)dit(bf(tt(echok=<bool>)))
+label(OPTION_ECHOKE)dit(bf(tt(echoke=<bool>)))
+label(OPTION_ECHONL)dit(bf(tt(echonl=<bool>)))
+label(OPTION_ECHOPRT)dit(bf(tt(echoprt=<bool>)))
+label(OPTION_EOF)dit(bf(tt(eof=<byte>)))
+label(OPTION_EOL)dit(bf(tt(eol=<byte>)))
+label(OPTION_EOL2)dit(bf(tt(eol2=<byte>)))
+label(OPTION_ERASE)dit(bf(tt(erase=<byte>)))
+label(OPTION_DISCARD)dit(bf(tt(discard=<byte>)))
+label(OPTION_FF0)dit(bf(tt(ff0)))
+label(OPTION_FF1)dit(bf(tt(ff1)))
+label(OPTION_FFDLY)dit(bf(tt(ffdly=<bool>)))
+label(OPTION_FLUSHO)dit(bf(tt(flusho=<bool>)))
+label(OPTION_HUPCL)dit(bf(tt(hupcl=<bool>)))
+label(OPTION_ICRNL)dit(bf(tt(icrnl=<bool>)))
+label(OPTION_IEXTEN)dit(bf(tt(iexten=<bool>)))
+label(OPTION_IGNCR)dit(bf(tt(igncr=<bool>)))
+label(OPTION_IGNPAR)dit(bf(tt(ignpar=<bool>)))
+label(OPTION_IMAXBEL)dit(bf(tt(imaxbel=<bool>)))
+label(OPTION_INLCR)dit(bf(tt(inlcr=<bool>)))
+label(OPTION_INPCK)dit(bf(tt(inpck=<bool>)))
+label(OPTION_INTR)dit(bf(tt(intr=<byte>)))
+label(OPTION_ISIG)dit(bf(tt(isig=<bool>)))
+label(OPTION_ISPEED)dit(bf(tt(ispeed=<unsigned-int>)))
+ Set the baud rate for incoming data on this line.nl()
+ See also: link(ospeed)(OPTION_OSPEED), link(b19200)(OPTION_B19200)
+label(OPTION_ISTRIP)dif(bf(tt(istrip=<bool>)))
+label(OPTION_IUCLC)dit(bf(tt(iuclc=<bool>)))
+label(OPTION_IXANY)dit(bf(tt(ixany=<bool>)))
+label(OPTION_IXOFF)dit(bf(tt(ixoff=<bool>)))
+label(OPTION_IXON)dit(bf(tt(ixon=<bool>)))
+label(OPTION_KILL)dit(bf(tt(kill=<byte>)))
+label(OPTION_LNEXT)dit(bf(tt(lnext=<byte>)))
+label(OPTION_MIN)dit(bf(tt(min=<byte>)))
+label(OPTION_NL0)dit(bf(tt(nl0)))
+ Sets the newline delay to 0.
+label(OPTION_NL1)dit(bf(tt(nl1)))
+label(OPTION_NLDLY)dit(bf(tt(nldly=<bool>)))
+label(OPTION_NOFLSH)dit(bf(tt(noflsh=<bool>)))
+label(OPTION_OCRNL)dit(bf(tt(ocrnl=<bool>)))
+label(OPTION_OFDEL)dit(bf(tt(ofdel=<bool>)))
+label(OPTION_OFILL)dit(bf(tt(ofill=<bool>)))
+label(OPTION_OLCUC)dit(bf(tt(olcuc=<bool>)))
+label(OPTION_ONLCR)dit(bf(tt(onlcr=<bool>)))
+label(OPTION_ONLRET)dit(bf(tt(onlret=<bool>)))
+label(OPTION_ONOCR)dit(bf(tt(onocr=<bool>)))
+label(OPTION_OPOST)dit(bf(tt(opost=<bool>)))
+ Enables or disables output processing; e.g., converts NL to CR-NL.
+label(OPTION_OSPEED)dit(bf(tt(ospeed=<unsigned-int>)))
+ Set the baud rate for outgoing data on this line.nl()
+ See also: link(ispeed)(OPTION_ISPEED), link(b19200)(OPTION_B19200)
+label(OPTION_PARENB)dit(bf(tt(parenb=<bool>)))
+ Enable parity generation on output and parity checking for input.
+label(OPTION_PARMRK)dit(bf(tt(parmrk=<bool>)))
+label(OPTION_PARODD)dit(bf(tt(parodd=<bool>)))
+label(OPTION_PENDIN)dit(bf(tt(pendin=<bool>)))
+label(OPTION_QUIT)dit(bf(tt(quit=<byte>)))
+label(OPTION_REPRINT)dit(bf(tt(reprint=<byte>)))
+label(OPTION_SANE)dit(bf(tt(sane)))
+ Brings the terminal to something like a useful default state.
+label(OPTION_START)dit(bf(tt(start=<byte>)))
+label(OPTION_STOP)dit(bf(tt(stop=<byte>)))
+label(OPTION_SUSP)dit(bf(tt(susp=<byte>)))
+label(OPTION_SWTC)dit(bf(tt(swtc=<byte>)))
+label(OPTION_TAB0)dit(bf(tt(tab0)))
+label(OPTION_TAB1)dit(bf(tt(tab1)))
+label(OPTION_TAB2)dit(bf(tt(tab2)))
+label(OPTION_TAB3)dit(bf(tt(tab3)))
+label(OPTION_TABDLY)dit(bf(tt(tabdly=<unsigned-int>)))
+label(OPTION_TIME)dit(bf(tt(time=<byte>)))
+label(OPTION_TOSTOP)dit(bf(tt(tostop=<bool>)))
+label(OPTION_VT0)dit(bf(tt(vt0)))
+label(OPTION_VT1)dit(bf(tt(vt1)))
+label(OPTION_VTDLY)dit(bf(tt(vtdly=<bool>)))
+label(OPTION_WERASE)dit(bf(tt(werase=<byte>)))
+label(OPTION_XCASE)dit(bf(tt(xcase=<bool>)))
+label(OPTION_XTABS)dit(bf(tt(xtabs)))
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_PTY)em(bf(PTY option group))
+
+These options are intended for use with the link(pty)(ADDRESS_PTY) address
+type.
+
+startdit()
+label(OPTION_SYMBOLIC_LINK)dit(bf(tt(link=<filename>)))
+ Generates a symbolic link that points to the actual pseudo terminal
+ (pty). This might help
+ to solve the problem that ptys are generated with more or less
+ unpredictable names, making it difficult to directly access the socat
+ generated pty automatically. With this option, the user can specify a "fix"
+ point in the file hierarchy that helps him to access the actual pty
+ (link(example)(EXAMPLE_OPTION_SYMBOLIC_LINK)).
+ Beginning with socat() version 1.4.3, the symbolic link is removed when
+ the address is closed (but see option link(unlink-close)(OPTION_UNLINK_CLOSE)).
+label(OPTION_PTY_WAIT_SLAVE)dit(bf(tt(wait-slave)))
+ Blocks the open phase until a process opens the slave side of the pty.
+ Usually, socat continues after generating the pty with opening the next
+ address or with entering the transfer loop. With the wait-slave option,
+ socat waits until some process opens the slave side of the pty before
+ continuing.
+ This option only works if the operating system provides the tt(poll())
+ system call. And it depends on an undocumented behaviour of pty's, so it
+ does not work on all operating systems. It has successfully been tested on
+ Linux, FreeBSD, NetBSD, and on Tru64 with openpty.
+label(OPTION_PTY_INTERVALL)dit(bf(tt(pty-intervall=<seconds>)))
+ When the link(wait-slave)(OPTION_PTY_WAIT_SLAVE) option is set, socat
+ periodically checks the HUP condition using tt(poll()) to find if the pty's
+ slave side has been opened. The default polling intervall is 1s. Use the
+ pty-intervall option [link(timeval)(TYPE_TIMEVAL)] to change this value.
+enddit()
+
+
+startdit()enddit()nl()
+
+
+label(GROUP_OPENSSL)em(bf(OPENSSL option group))
+
+These options apply to the link(openssl)(ADDRESS_OPENSSL_CONNECT) and
+link(openssl-listen)(ADDRESS_OPENSSL_LISTEN) address types.
+
+startdit()
+label(OPTION_OPENSSL_CIPHERLIST)dit(bf(tt(cipher=<cipherlist>)))
+ Selects the list of ciphers that may be used for the connection.
+ See the man page of code(ciphers), section bf(CIPHER LIST FORMAT), for
+ detailed information about syntax, values, and default of <cipherlist>.nl()
+ Several cipher strings may be given, separated by ':'.
+ Some simple cipher strings:
+ startdit()
+ dit(3DES) Uses a cipher suite with triple DES.
+ dit(MD5) Uses a cipher suite with MD5.
+ dit(aNULL) Uses a cipher suite without authentication.
+ dit(NULL) Does not use encryption.
+ dit(HIGH) Uses a cipher suite with "high" encryption.
+ enddit()
+ Note that the peer must support the selected property, or the negotiation
+ will fail.
+label(OPTION_OPENSSL_METHOD)dit(bf(tt(method=<ssl-method>)))
+ Sets the protocol version to be used. Valid strings (not case sensitive)
+ are:
+ startdit()
+ dit(tt(SSLv2)) Select SSL protocol version 2.
+ dit(tt(SSLv3)) Select SSL protocol version 3.
+ dit(tt(SSLv23)) Select SSL protocol version 2 or 3. This is the default when
+ this option is not provided.
+ dit(tt(TLSv1)) Select TLS protocol version 1.
+ enddit()
+label(OPTION_OPENSSL_VERIFY)dit(bf(tt(verify=<bool>)))
+ Controls check of the peer's certificate. Default is 1 (true). Disabling
+ verify might open your socket for everyone, making the encryption useless!
+label(OPTION_OPENSSL_CERTIFICATE)dit(bf(tt(cert=<filename>)))
+ Specifies the file with the certificate and private key for authentication.
+ The certificate must be in OpenSSL format (*.pem).
+ With openssl-listen, use of this option is strongly
+ recommended. Except with cipher aNULL, "no shared ciphers" error will
+ occur when no certificate is given.
+label(OPTION_OPENSSL_KEY)dit(bf(tt(key=<filename>)))
+ Specifies the file with the private key. The private key may be in this
+ file or in the file given with the link(cert)(OPTION_OPENSSL_CERTIFICATE) option. The party that has
+ to proof that it is the owner of a certificate needs the private key.
+label(OPTION_OPENSSL_DHPARAMS)dit(bf(tt(dhparams=<filename>)))
+ Specifies the file with the Diffie Hellman parameters. These parameters may
+ also be in the file given with the link(cert)(OPTION_OPENSSL_CERTIFICATE)
+ option in which case the dhparams option is not needed.
+label(OPTION_OPENSSL_CAFILE)dit(bf(tt(cafile=<filename>)))
+ Specifies the file with the trusted (root) authority certificates. The file
+ must be in PEM format and should contain one or more certificates. The party
+ that checks the authentication of its peer trusts only certificates that are
+ in this file.
+label(OPTION_OPENSSL_CAPATH)dit(bf(tt(capath=<dirname>)))
+ Specifies the directory with the trusted (root) certificates. The directory
+ must contain certificates in PEM format and their hashes (see OpenSSL
+ documentation)
+label(OPTION_OPENSSL_EGD)dit(bf(tt(egd=<filename>)))
+ On some systems, openssl requires an explicit source of random data. Specify
+ the socket name where an entropy gathering daemon like egd provides random
+ data, e.g. /dev/egd-pool.
+label(OPTION_OPENSSL_PSEUDO)dit(bf(tt(pseudo)))
+ On systems where openssl cannot find an entropy source and where no entropy
+ gathering daemon can be utilized, this option activates a mechanism for
+ providing pseudo entropy. This is archieved by taking the current time in
+ microseconds for feeding the libc pseudo random number generator with an
+ initial value. openssl is then feeded with output from random() calls.nl()
+ NOTE:This mechanism is not sufficient for generation of secure keys!
+label(OPTION_OPENSSL_FIPS)dit(bf(tt(fips)))
+ Enables FIPS mode if compiled in. For info about the FIPS encryption
+ implementation standard see lurl(http://oss-institute.org/fips-faq.html).
+ This mode might require that the involved certificates are generated with a
+ FIPS enabled version of openssl. Setting or clearing this option on one
+ socat address affects all OpenSSL addresses of this process.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_RETRY)em(bf(RETRY option group))
+
+Options that control retry of some system calls, especially connection
+attempts.
+
+startdit()
+label(OPTION_RETRY)dit(bf(tt(retry=<num>)))
+ Number of retries before the connection or listen attempt is aborted.
+ Default is 0, which means just one attempt.
+label(OPTION_INTERVALL)dit(bf(tt(intervall=<timespec>)))
+ Time between consecutive attempts (seconds,
+ [link(timespec)(TYPE_TIMESPEC)]). Default is 1 second.
+label(OPTION_FOREVER)dit(bf(tt(forever)))
+ Performs an unlimited number of retry attempts.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(GROUP_TUN)em(bf(TUN option group))
+
+Options that control Linux TUN/TAP interface device addresses.
+
+startdit()
+label(OPTION_TUN_DEVICE)dit(bf(tt(tun-device=<device-file>)))
+ Instructs socat to take another path for the TUN clone device. Default is
+ tt(/dev/net/tun).
+label(OPTION_TUN_NAME)dit(bf(tt(tun-name=<if-name>)))
+ Gives the resulting network interface a specific name instead of the system
+ generated (tun0, tun1, etc.)
+label(OPTION_TUN_TYPE)dit(bf(tt(tun-type=[tun|tap])))
+ Sets the type of the TUN device; use this option to generate a TAP
+ device. See the Linux docu for the difference between these types.
+ When you try to establish a tunnel between two TUN devices, their types
+ should be the same.
+label(OPTION_IFF_NO_PI)dit(bf(tt(iff-no-pi)))
+ Sets the IFF_NO_PI flag which controls if the device includes additional
+ packet information in the tunnel.
+ When you try to establish a tunnel between two TUN devices, these flags
+ should have the same values.
+label(OPTION_IFF_UP)dit(bf(tt(iff-up)))
+ Sets the TUN network interface status UP. Strongly recommended.
+label(OPTION_IFF_BROADCAST)dit(bf(tt(iff-broadcast)))
+ Sets the BROADCAST flag of the TUN network interface.
+label(OPTION_IFF_DEBUG)dit(bf(tt(iff-debug)))
+ Sets the DEBUG flag of the TUN network interface.
+label(OPTION_IFF_LOOPBACK)dit(bf(tt(iff-loopback)))
+ Sets the LOOPBACK flag of the TUN network interface.
+label(OPTION_IFF_POINTOPOINT)dit(bf(tt(iff-pointopoint)))
+ Sets the POINTOPOINT flag of the TUN device.
+label(OPTION_IFF_NOTRAILERS)dit(bf(tt(iff-notrailers)))
+ Sets the NOTRAILERS flag of the TUN device.
+label(OPTION_IFF_RUNNING)dit(bf(tt(iff-running)))
+ Sets the RUNNING flag of the TUN device.
+label(OPTION_IFF_NOARP)dit(bf(tt(iff-noarp)))
+ Sets the NOARP flag of the TUN device.
+label(OPTION_IFF_PROMISC)dit(bf(tt(iff-promisc)))
+ Sets the PROMISC flag of the TUN device.
+label(OPTION_IFF_ALLMULTI)dit(bf(tt(iff-allmulti)))
+ Sets the ALLMULTI flag of the TUN device.
+label(OPTION_IFF_MASTER)dit(bf(tt(iff-master)))
+ Sets the MASTER flag of the TUN device.
+label(OPTION_IFF_SLAVE)dit(bf(tt(iff-slave)))
+ Sets the SLAVE flag of the TUN device.
+label(OPTION_IFF_MULTICAST)dit(bf(tt(iff-multicast)))
+ Sets the MULTICAST flag of the TUN device.
+label(OPTION_IFFPORTSEL_)dit(bf(tt(iff-portsel)))
+ Sets the PORTSEL flag of the TUN device.
+label(OPTION_IFF_AUTOMEDIA)dit(bf(tt(iff-automedia)))
+ Sets the AUTOMEDIA flag of the TUN device.
+label(OPTION_IFF_DYNAMIC)dit(bf(tt(iff-dynamic)))
+ Sets the DYNAMIC flag of the TUN device.
+enddit()
+
+startdit()enddit()nl()
+
+
+label(VALUES)
+manpagesection(DATA VALUES)
+
+This section explains the different data types that address parameters and
+address options can take.
+
+startdit()
+label(TYPE_ADDRESS_RANGE)dit(address-range)
+ Is currently only implemented for IPv4 and IPv6. See address-option
+ link(`range')(OPTION_RANGE)
+label(TYPE_BOOL)dit(bool)
+ "0" or "1"; if value is omitted, "1" is taken.
+label(TYPE_BYTE)dit(byte)
+ An unsigned int number, read with code(strtoul()), lower or equal to
+ code(UCHAR_MAX).
+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.
+label(TYPE_DIRECTORY)dit(directory)
+ A string with usual unix() directory name semantics.
+label(TYPE_FACILITY)dit(facility)
+ The name of a syslog facility in lower case characters.
+label(TYPE_FDNUM)dit(fdnum)
+ An unsigned int type, read with code(strtoul()), specifying a unix() file
+ descriptor.
+label(TYPE_FILENAME)dit(filename)
+ A string with usual unix() filename semantics.
+label(TYPE_GROUP)dit(group)
+ If the first character is a decimal digit, the value is read with
+ code(strtoul()) as unsigned integer specifying a group id. Otherwise, it
+ must be an existing group name.
+label(TYPE_INT)dit(int)
+ A number following the rules of the code(strtol()) function with base
+ "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".
+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
+ IPv6 address.nl()
+ Examples: 127.0.0.1, [::1], www.dest-unreach.org, dns1
+label(TYPE_IPV4_ADDRESS)dit(IPv4 address)
+ An IPv4 address in numbers-and-dots notation or a hostname that resolves to
+ an IPv4 address.nl()
+ Examples: 127.0.0.1, www.dest-unreach.org, dns2
+label(TYPE_IPV6_ADDRESS)dit(IPv6 address)
+ An iPv6 address in hexnumbers-and-colons notation enclosed in brackets, or a
+ hostname that resolves to an IPv6 address.nl()
+ Examples: [::1], [1234:5678:9abc:def0:1234:5678:9abc:def0],
+ ip6name.domain.org
+label(TYPE_LONG)dit(long)
+ A number read with code(strtol()). The value must fit into a C long.
+label(TYPE_LONGLONG)dit(long long)
+ A number read with code(strtoll()). The value must fit into a C long long.
+label(TYPE_OFF)dit(off_t)
+ An implementation dependend signed number, usually 32 bits, read with strtol
+ or strtoll.
+label(TYPE_OFF64)dit(off64_t)
+ An implementation dependend signed number, usually 64 bits, read with strtol
+ or strtoll.
+label(TYPE_MODE_T)dit(mode_t)
+ An unsigned integer, read with code(strtoul()), specifying mode (permission)
+ bits.
+label(TYPE_PID_T)dit(pid_t)
+ A number, read with code(strtol()), specifying a process id.
+label(TYPE_PORT)dit(port)
+ A uint16_t (16 bit unsigned number) specifying a TCP or UDP port, read
+ with code(strtoul()).
+label(TYPE_PROTOCOL)dit(protocol)
+ An unsigned 8 bit number, read with code(strtoul()).
+label(TYPE_SIZE_T)dit(size_t)
+ An unsigned number with size_t limitations, read with code(strtoul).
+label(TYPE_SOCKNAME)dit(sockname)
+ A socket address. See address-option link(`bind')(OPTION_BIND)
+label(TYPE_STRING)dit(string)
+ A sequence of characters, not containing '\0' and, depending on
+ the position within the command line, ':', ',', or "!!". Note
+ that you might have to escape shell meta characters in the command line.
+label(TYPE_TCP_SERVICE)dit(TCP service)
+ A service name, not starting with a digit, that is resolved by
+ code(getservbyname()), or an unsigned int 16 bit number read with
+ code(strtoul()).
+label(TYPE_TIMEVAL)dit(timeval)
+ A double float specifying seconds; the number is mapped into a
+ struct timeval, consisting of seconds and microseconds.
+label(TYPE_TIMESPEC)dit(timespec)
+ A double float specifying seconds; the number is mapped into a
+ struct timespec, consisting of seconds and nanoseconds.
+label(TYPE_UDP_SERVICE)dit(UDP service)
+ A service name, not starting with a digit, that is resolved by
+ code(getservbyname()), or an unsigned int 16 bit number read with
+ code(strtoul()).
+label(TYPE_UNSIGNED_INT)dit(unsigned int)
+ A number read with code(strtoul()). The value must fit into a C unsigned
+ int.
+label(TYPE_USER)dit(user)
+ If the first character is a decimal digit, the value is read with
+ code(strtoul()) as unsigned integer specifying a user id. Otherwise, it must
+ be an existing user name.
+enddit()
+
+
+label(EXAMPLES)
+manpagesection(EXAMPLES)
+
+
+startdit()
+
+label(EXAMPLE_ADDRESS_TCP4_CONNECT)
+dit(bf(tt(socat - TCP4:www.domain.org:80)))
+
+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
+close the relay with ^D or abort it with ^C.
+
+label(EXAMPLE_ADDRESS_READLINE)
+label(EXAMPLE_OPTION_HISTORY)
+mancommand(\.LP)
+mancommand(\.nf)
+mancommand(\fBsocat -d -d READLINE,history=$HOME/.http_history \\
+TCP4:www.domain.org:www,crnl\fP)
+mancommand(\.fi)
+
+htmlcommand(<dt><code><strong>socat -d -d READLINE,history=$HOME/.http_history \</strong><br>
+<strong>TCP4:www.domain.org:www,crnl</strong></code><dd>)
+
+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.
+
+
+label(EXAMPLE_ADDRESS_TCP4_LISTEN)
+dit(bf(tt(socat TCP4-LISTEN:www TCP4:www.domain.org:www)))
+
+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.
+
+label(EXAMPLE_OPTION_BIND_TCP4)
+label(EXAMPLE_OPTION_REUSEADDR)
+label(EXAMPLE_OPTION_FORK)
+label(EXAMPLE_OPTION_SUBSTUSER)
+label(EXAMPLE_OPTION_RANGE)
+mancommand(\.LP)
+mancommand(\.nf)
+mancommand(\fBsocat -d -d -lmlocal2 \\
+TCP4-LISTEN:80,bind=myaddr1,reuseaddr,fork,su=nobody,range=10.0.0.0/8 \\
+TCP4:www.domain.org:80,bind=myaddr2\fP)
+mancommand(\.fi)
+
+htmlcommand(<dt><code><strong>socat -d -d -lmlocal2 \</strong><br>
+<strong>TCP4-LISTEN:80,bind=myaddr1,su=nobody,fork,range=10.0.0.0/8,reuseaddr \</strong><br>
+<strong>TCP4:www.domain.org:80,bind=myaddr2</strong></code><dd>)
+
+TCP port forwarder, each side bound to another local IP address
+(link(bind)(OPTION_BIND)). This example handles an almost
+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.
+With link(-lmlocal2)(option_lm), socat logs to stderr until successfully
+reaching the accept loop. Further logging is directed to syslog with facility
+local2.
+
+label(EXAMPLE_ADDRESS_EXEC)
+label(EXAMPLE_OPTION_TCPWRAPPERS)
+label(EXAMPLE_OPTION_CHROOT)
+label(EXAMPLE_OPTION_SUBSTUSER_DELAYED)
+label(EXAMPLE_OPTION_PTY)
+label(EXAMPLE_OPTION_STDERR)
+mancommand(\.LP)
+mancommand(\.nf)
+mancommand(\fBsocat TCP4-LISTEN:5555,fork,tcpwrap=script \\
+EXEC:/bin/myscript,chroot=/home/sandbox,su-d=sandbox,pty,stderr\fP)
+mancommand(\.fi)
+
+htmlcommand(<dt><code><strong>socat TCP4-LISTEN:5555,fork,tcpwrap=script \</strong><br>
+<strong>EXEC:/bin/myscript,chroot=/home/sandbox,su-d=sandbox,pty,stderr</strong></code><dd>)
+
+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
+/etc/hosts.allow and /etc/hosts.deny, otherwise it is refused access (see "man
+5 hosts_access").
+For link(EXEC)(ADDRESS_EXEC)'uting the program, the child process
+link(chroot)(OPTION_CHROOT)'s
+to file(/home/sandbox), link(su)(OPTION_SUBSTUSER)'s to user sandbox, and then starts
+the program file(/home/sandbox/bin/myscript). Socat() and
+myscript communicate via a pseudo tty (link(pty)(OPTION_PTY)); myscript's
+link(stderr)(OPTION_STDERR) is redirected to stdout,
+so its error messages are transferred via socat() to the connected client.
+
+label(EXAMPLE_OPTION_FDIN)
+label(EXAMPLE_OPTION_FDOUT)
+label(EXAMPLE_OPTION_CRNL)
+label(EXAMPLE_OPTION_MSS)
+mancommand(\.LP)
+mancommand(\.nf)
+mancommand(\fBsocat EXEC:"mail.sh target@domain.com",fdin=3,fdout=4 \\
+TCP4:mail.relay.org:25,crnl,bind=alias1.server.org,mss=512\fP)
+mancommand(\.fi)
+
+htmlcommand(<dt><code><strong>socat EXEC:"mail.sh target@domain.com",fdin=3,fdout=4 \</strong><br>
+<strong>TCP4:mail.relay.org:25,crnl,bind=alias1.server.org,mss=512</strong></code><dd>)
+
+file(mail.sh) is a shell script, distributed with socat(), that implements a
+simple
+SMTP client. It is programmed to "speak" SMTP on its FDs 3 (in) and 4 (out).
+The link(fdin)(OPTION_FDIN) and link(fdout)(OPTION_FDOUT) options tell socat()
+to use these FDs for communication with
+the program. Because mail.sh inherits stdin and stdout while socat() does not
+use them, the script can read a
+mail body from stdin. Socat() makes alias1 your local source address
+(link(bind)(OPTION_BIND)), cares for correct network line termination
+(link(crnl)(OPTION_CRNL)) and sends
+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)))
+
+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 `-'.
+
+
+label(EXAMPLE_ADDRESS_UNIX_LISTEN)
+label(EXAMPLE_ADDRESS_SOCKS4)
+label(EXAMPLE_OPTION_SOCKSUSER)
+label(EXAMPLE_OPTION_SOURCEPORT)
+mancommand(\.LP)
+mancommand(\.nf)
+mancommand(\fBsocat UNIX-LISTEN:/tmp/.X11-unix/X1,fork \\
+SOCKS4:host.victim.org:127.0.0.1:6000,socksuser=nobody,sourceport=20\fP)
+mancommand(\.fi)
+
+htmlcommand(<dt><code><strong>socat UNIX-LISTEN:/tmp/.X11-unix/X1,fork \</strong><br>
+<strong>SOCKS4:host.victim.org:127.0.0.1:6000,socksuser=nobody,sourceport=20</strong></code><dd>)
+
+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
+the link(SOCKS4)(ADDRESS_SOCKS4) server host.victim.org that might permit
+link(sourceport)(OPTION_SOURCEPORT) 20 based connections due to an FTP related
+weakness in its static IP filters. Socat()
+pretends to be invoked by link(socksuser)(OPTION_SOCKSUSER) nobody, and
+requests to be connected to
+loopback port 6000 (only weak sockd configurations will allow this). So we get
+a connection to the victims XWindow server and, if it does not require MIT
+cookies or Kerberos authentication, we can start work. Please note that there
+can only be one connection at a time, because TCP can establish only one
+session with a given set of addresses and ports.
+
+
+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
+(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
+reading at current end of file; use link(seek)(OPTION_SEEK)=0 or no
+seek option to first read the existing data) in a "tail -f" like mode
+(link(ignoreeof)(OPTION_IGNOREEOF)). The "file"
+might also be a listening unixdomain() socket (do not use a seek option then).
+
+
+label(EXAMPLE_OPTION_SETSID)
+label(EXAMPLE_OPTION_CTTY)
+mancommand(\.LP)
+mancommand(\.nf)
+mancommand(\fB(sleep 5; echo PASSWORD; sleep 5; echo ls; sleep 1) |
+socat - EXEC:'ssh -l user server',pty,setsid,ctty\fP)
+mancommand(\.fi)
+
+htmlcommand(<dt><code><strong>(echo PASSWORD; sleep 5; echo ls; sleep 1) |</strong><br>
+<strong>socat - EXEC:'ssh -l user server',pty,setsid,ctty</strong></code><dd>)
+
+link(EXEC)(ADDRESS_EXEC)'utes an ssh session to server. Uses a link(pty)(OPTION_PTY) for communication between socat() and
+ssh, makes it ssh's controlling tty (link(ctty)(OPTION_CTTY)),
+and makes this pty the owner of
+a new process group (link(setsid)(OPTION_SETSID)), so ssh accepts the password from socat().
+
+
+label(EXAMPLE_ADDRESS_OPEN)
+label(EXAMPLE_OPTION_CREAT)
+label(EXAMPLE_OPTION_APPEND)
+mancommand(\.LP)
+mancommand(\.nf)
+mancommand(\fBsocat -u TCP4-LISTEN:3334,reuseaddr,fork \\
+OPEN:/tmp/in.log,creat,append\fP)
+mancommand(\.fi)
+
+htmlcommand(<dt><code><strong>socat -u TCP4-LISTEN:3334,reuseaddr,fork \</strong><br>
+<strong>OPEN:/tmp/in.log,creat,append</strong></code><dd>)
+
+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.
+Option link(reuseaddr)(OPTION_REUSEADDR) allows immediate restart of the server
+process.
+
+COMMENT(
+dit(bf(tt(socat TCP4-LISTEN:3335,reuseaddr,fork OPEN:/tmp/motd,rdonly)))
+
+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.
+Messages sent by clients result in an error due to option link(rdonly)(OPTION_RDONLY).
+Option link(reuseaddr)(OPTION_REUSEADDR) allows immediate restart of the server
+process.
+)
+COMMENT(
+dit(bf(tt(socat - TCP4-LISTEN:8080,mtudiscover=0,rcvbuf=2048)))
+
+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.
+)
+
+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.
+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.
+Nevertheless, there may occur some confusion with the password and FTP
+prompts.
+
+
+label(EXAMPLE_ADDRESS_PTY)
+label(EXAMPLE_OPTION_SYMBOLIC_LINK)
+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
+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
+can be configured to use file($HOME/dev/vmodem0); its traffic will be directed
+to a modemserver via ssh where another socat instance links it with
+file(/dev/ttyS0).
+
+
+mancommand(\.LP)
+mancommand(\.nf)
+mancommand(\fBsocat TCP4-LISTEN:2022,reuseaddr,fork \\
+PROXY:proxy:www.domain.org:22,proxyport=3128,proxyauth=user:pass\fP)
+mancommand(\.fi)
+
+htmlcommand(<dt><code><strong>socat TCP4-LISTEN:2022,reuseaddr,fork \</strong><br>
+<strong>PROXY:proxy:www.domain.org:22,proxyport=3128,proxyauth=user:pass</strong></code><dd>)
+
+starts a forwarder that accepts connections on port 2022, and directs them
+through the link(proxy)(ADDRESS_PROXY_CONNECT) daemon listening on port 3128
+(link(proxyport)(OPTION_PROXYPORT)) on host proxy, using the
+CONNECT method, where they are authenticated as "user" with "pass" (link(proxyauth)(OPTION_PROXY_AUTHORIZATION)). The proxy
+should establish connections to host www.domain.org on port 22 then.
+
+
+label(EXAMPLE_ADDRESS_OPENSSL_CONNECT)
+dit(bf(tt(socat - SSL:server:4443,cafile=server.crt,cert=client.pem)))
+
+is an OpenSSL client that tries to establish a secure connection to an SSL
+server. Option link(cafile)(OPTION_OPENSSL_CAFILE) specifies a file that
+contains trust certificates: we trust the server only when it presents one of
+these certificates and proofs that it owns the related private key.
+Otherwise the connection is terminated.
+With link(cert)(OPTION_OPENSSL_CERTIFICATE) a file containing the client certificate
+and the associated private key is specified. This is required in case the
+server wishes a client authentication; many Internet servers do not.nl()
+The first address ('-') can be replaced by almost any other socat address.
+
+
+label(EXAMPLE_ADDRESS_OPENSSL_LISTEN)
+dit(bf(tt(socat SSL-LISTEN:4443,reuseaddr,pf=ip4,fork,cert=server.pem,cafile=client.crt PIPE)))
+
+is an OpenSSL server that accepts TCP connections, presents the certificate
+from the file server.pem and forces the client to present a certificate that is
+verified against cafile.crt.nl()
+The second address ('PIPE') can be replaced by almost any other socat
+address.nl()
+For instructions on generating and distributing OpenSSL keys and certificates
+see the additional socat docu tt(socat-openssl.txt).
+
+
+dit(bf(tt(echo |socat -u - file:/tmp/bigfile,create,largefile,seek=100000000000)))
+
+creates a 100GB sparse file; this requires a file system type that
+supports this (ext2, ext3, reiserfs, jfs; not minix, vfat). The operation of
+writing 1 byte might take long (reiserfs: some minutes; ext2: "no" time), and
+the resulting file can consume some disk space with just its inodes (reiserfs:
+2MB; ext2: 16KB).
+
+
+dit(bf(tt(socat tcp-l:7777,reuseaddr,fork system:'filan -i 0 -s >&2',nofork)))
+
+listens for incoming TCP connections on port 7777. For each accepted
+connection, invokes a shell. This shell has its stdin and stdout directly
+connected to the TCP socket (link(nofork)(OPTION_NOFORK)). The shell starts filan and lets it print the socket addresses to
+stderr (your terminal window).
+
+
+dit(bf(tt(echo -e "\0\14\0\0\c" |socat -u - file:/usr/bin/squid.exe,seek=0x00074420)))
+
+functions as primitive binary editor: it writes the 4 bytes 000 014 000 000 to
+the executable /usr/bin/squid at offset 0x00074420 (this is a real world patch
+to make the squid executable from Cygwin run under Windows, actual per May 2004).
+
+
+dit(bf(tt(socat - tcp:www.blackhat.org:31337,readbytes=1000)))
+
+connects to an unknown service and prevents being flooded.
+
+
+label(EXAMPLE_END_CLOSE)
+dit(bf(tt(socat -U TCP:target:9999,end-close TCP-L:8888,reuseaddr,fork)))
+
+merges data arriving from different TCP streams on port 8888 to just one stream
+to target:9999. The link(end-close)(OPTION_END_CLOSE) option prevents the child
+processes forked off by the second address from terminating the shared
+connection to 9999 (close(2) just unlinks the inode which stays active as long
+as the parent process lives; shutdown(2) would actively terminate the
+connection).
+
+
+label(EXAMPLE_ADDRESS_UDP4_BROADCAST_CLIENT)
+dit(bf(tt(socat - UDP4-DATAGRAM:192.168.1.0:123,sp=123,broadcast,range=192.168.1.0/24)))
+
+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_IP4_BROADCAST_CLIENT)
+dit(bf(tt(socat - IP4-DATAGRAM:255.255.255.255:44,broadcast,range=10.0.0.0/8)))
+
+sends a broadcast to the local network(s) using protocol 44. Accepts replies
+from the private address range only.
+
+
+label(EXAMPLE_ADDRESS_UDP4_MULTICAST)
+dit(bf(tt(socat - UDP4-DATAGRAM:224.255.0.1:6666,bind=:6666,ip-add-membership=224.255.0.1:eth0)))
+
+transfers data from stdin to the specified multicast address using UDP. Both
+local and remote ports are 6666. Tells the interface eth0 to also accept
+multicast packets of the given group. Multiple hosts on the local network can
+run this command, so all data sent by any of the hosts will be received
+by all the other ones. Note that there are many possible reasons for failure,
+including IP-filters, routing issues, wrong interface selection by the
+operating system, bridges, or a badly configured switch.
+
+
+label(EXAMPLE_ADDRESS_TUN)
+dit(bf(tt(socat TCP:host2:4443 TUN:192.168.255.1/24,up)))
+
+establishes one side of a virtual (but not private!) network with host2 where a
+similar process might run, with TCP-L and tun address 192.168.255.2. They
+can reach each other using the addresses 192.168.255.1 and
+192.168.255.2. Substitute the TCP link with an SSL connection protected by
+client and server authentication (see OpenSSL
+link(client)(EXAMPLE_ADDRESS_OPENSSL_CONNECT) and
+link(server)(EXAMPLE_ADDRESS_OPENSSL_LISTEN)).
+
+enddit()
+
+
+label(DIAGNOSTICS)
+manpagediagnostics()
+
+Socat() uses a logging mechanism that allows to filter messages by severity. The
+severities provided are more or less compatible to the appropriate syslog
+priority. With one or up to four occurrences of the -d command line option, the
+lowest priority of messages that are issued can be selected. Each message
+contains a single uppercase character specifying the messages severity (one of
+F, E, W, N, I, or D)
+
+description(
+dit(FATAL:) Conditions that require unconditional and immediate program termination.
+dit(ERROR:) Conditions that prevent proper program processing. Usually the
+program is terminated (see link(option -s)(option_s)).
+dit(WARNING:) Something did not function correctly or is in a state where
+correct further processing cannot be guaranteed, but might be possible.
+dit(NOTICE:) Interesting actions of the program, e.g. for supervising socat() in some kind of server mode.
+dit(INFO:) Description of what the program does, and maybe why it
+happens. Allows to monitor the lifecycles of file descriptors.
+dit(DEBUG:) Description of how the program works, all system or library calls and their results.
+)
+
+Log messages can be written to stderr, to a file, or to syslog.
+
+On exit, socat() gives status 0 if it terminated due to EOF or inactivity
+timeout, with a positive value on error, and with a negative value on fatal
+error.
+
+
+label(FILES)
+manpagefiles()
+
+/usr/bin/socat nl()
+/usr/bin/filan nl()
+/usr/bin/procan
+
+
+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).
+
+dit(bf(SOCAT_PREFERRED_RESOLVE_IP)) (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(HOSTNAME)) 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
+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
+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))
+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))
+Can be set with option link(path)(OPTION_PATH) for link(exec)(ADDRESS_EXEC) and
+link(system)(ADDRESS_SYSTEM) addresses.
+
+dit(bf(HOME))
+With options link(su)(OPTION_SUBSTUSER) and
+link(su-d)(OPTION_SUBSTUSER_DELAYED), HOME is set to the home directory of the
+given user.
+
+enddit()
+
+label(CREDITS)
+manpagesection(CREDITS)
+
+The work of the following groups and organizations was invaluable for this
+project:
+
+The em(FSF) (GNU, lurl(http://www.fsf.org/) project
+with their free and portable development software and
+lots of other useful tools and libraries.
+
+The em(Linux developers community) (lurl(http://www.linux.org/)) for providing a free, open source operating
+system.
+
+The em(Open Group) (lurl(http://www.unix-systems.org/)) for making their
+standard specifications available on the Internet for free.
+
+
+label(VERSION)
+manpagesection(VERSION)
+
+This man page describes version 1.6.0 of socat().
+
+
+label(BUGS)
+manpagebugs()
+
+Addresses cannot be nested, so a single socat process cannot, e.g., drive ssl
+over socks.
+
+Address option ftruncate without value uses default 1 instead of 0.
+
+Verbose modes (-x and/or -v) display line termination characters inconsistently
+when address options cr or crnl are used: They show the data em(after)
+conversion in either direction.
+
+The data transfer blocksize setting (-b) is ignored with address readline.
+
+Send bug reports to <socat@dest-unreach.org>
+
+
+label(SEEALSO)
+manpageseealso()
+
+COMMENT(procan\(1), filan\(1), )
+nc(1), netcat6(1), sock(1), rinetd(8), cage(1), socks.conf(5), openssl(1),
+stunnel(8), pty(1), rlwrap(1), setsid(1)
+
+Socat() home page lurl(http://www.dest-unreach.org/socat/)
+
+label(AUTHOR)
+manpageauthor()
+
+Gerhard Rieger <rieger@dest-unreach.org>
diff --git a/doc/xio.help b/doc/xio.help
new file mode 100644
index 0000000..937a93d
--- /dev/null
+++ b/doc/xio.help
@@ -0,0 +1,4959 @@
+# $Id: xio.help,v 1.115 2007/03/06 20:57:34 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2007
+
+Operating systems:
+
+The options and features described in this document have been implemented (but
+not always tested) on the operating systems listed below, unless otherwise
+noted:
+
+SuSE 10.1 Linux on x86
+Solaris 8 on Sparc with gcc
+FreeBSD 6.1 on x86
+HP-UX B 11.11 on PA-RISC with gcc
+
+===============================================================================
+
+The following sections describe the syntax and semantics of the socat command
+line stream arguments.
+
+Usually a socat stream argument defines a one- or bidirectional stream. There
+are two principal forms:
+* a single stream. Depending on use of the -u or -U options and implicit
+semantics of the stream, such an argument may be resolved to a one- or
+twodirectional stream.
+* two onedirectional streams, separated by '!!'. An argument of this form
+always specifies a twodirectional stream. The first single stream is only used
+for reading data, and the second is only used for writing data.
+
+
+The general structure of a single stream is:
+keyword[:required-parameters][,options]
+
+The options part starts with the first ',' of the argument. The required
+parameters are separated by ':' from their predecessor. The last required
+parameter is terminated by the end of the argument or by the first ',' that
+iitroduces the first option. The options are separated with ','. The last
+option is terminated by end-of-string or by '!!'.
+
+The are some abbreviations defined that allow to drop the keyword. In these
+cases the argument syntax is:
+required-parameter[:required-parameters][,options]
+The implemented abbreviations are:
+short form canonical form
+number FD:number # decimal number
+path GOPEN:path # must must contain at least one '/' and must not contain ':' or ',' and must not start with a decimal digit
+
+===============================================================================
+
+
+Addresses:
+
+Every address specification starts with a keyword or an abbreviation. These
+keywords are case insensitive.
+Note: because the option group ANY applies for all addresses, it is not
+mentioned explicitely below.
+
+
+Bidirectional only addresses:
+-----------------------------
+
+PIPE
+FIFO
+ECHO
+
+Opens an unnamed pipe (fifo) where outbound traffic is sent to and inbound
+traffic is read from. The special semantics of pipes results in an echo like
+behaviour.
+Option groups: FD, FIFO (no specific FIFO options are defined yet)
+
+
+Onedirectional only addresses:
+------------------------------
+
+Currently all addresses may be used bidirectional.
+Note: for regular files, behaviour when being used bidirectionally is
+undefined.
+
+
+One- and bidirectional addresses:
+---------------------------------
+
+STDIO
+- ("minus")
+
+Uses stdin (FD 0) for inbound traffic and/or stdout (FD 1) for outbound traffic
+on this address.
+Option groups: FD; others dependent on actual types of stdin and stdout (FIFO,
+CHR, BLK, REG, and/or SOCKET).
+
+
+STDIN
+
+Uses stdin for traffic. This might fail for outbound traffic.
+Option groups: FD; dependent on actual type of stdin (FIFO, CHR, BLK, REG, or
+SOCKET).
+
+
+STDOUT
+
+Uses stdout for traffic. This might fail for inbound traffic.
+Option groups: FD; dependent on actual type of stdout (FIFO, CHR, BLK, REG, or
+SOCKET).
+
+
+STDERR
+
+Uses stdout for traffic. This might fail for inbound traffic.
+Option group: FD; dependent on actual types of sterr (FIFO, CHR, BLK, REG, or
+SOCKET).
+
+
+FD:num
+num
+
+Uses the already existing file descriptor <num> for traffic.
+Option groups: FD; dependent on actual types of file descriptor (FIFO, CHR,
+BLK, REG, or SOCKET).
+
+
+READLINE
+
+Uses the GNU readline function and history capabilies (best known from bash).
+It always works on stdin and stdout; if stdio is not a tty, readline does not
+seem to work correctly.
+Because readline is blocking during line editing, it does not fit well into
+socats I/O philosophy.
+socat integrates readline by waiting in the select call as usual; when stdin
+reports available data, socat invokes readline(). readline blocks until the
+user presses ENTER or EOF. Data on socats other stream is not handling in this
+time.
+socat controls the ECHO flag of the stdin tty (off during select(), on for
+readline()).
+When using socat with readline as front end to a service like telnet, POP3 or
+an other authenticated service, please note that the password is entered as
+ordinary data, thus appears on the screen!
+Option groups: FD, READLINE, TERMIOS
+Useful options: history-file
+
+
+OPEN:path
+
+Applies an open() system call to the given path. If the path does not exist a
+file is created only if the option create is used; if a file, pipe, or device
+with this name already exists it is opened. Open for reading and/or writing
+depends on the rw parameter of the xioopen call, or on usage in a socat
+argument. If no perm option is used, xioopen uses 600 (which might be modified
+by umask then).
+Applying this function to files conforms to the semantics as described by the
+open(2) man page.
+Opening device files, like /dev/ttyS*, might block until the device gets active
+(until some peer is connected)
+With existing named pipes (fifos) please note the usual semantics:
+Opening the pipe in read/write mode results in an echo service;
+Opening the pipe in read mode blocks until a writer opens the pipe (close
+by writer gives EOF for the reader); with option nonblock the open call does
+not block.
+Opening the pipe in write mode blocks until a reader opens the pipe (close
+by reader gives "broken pipe" error on next write); with option nonblock the
+open call terminates with error "no such device or address" in absence of a
+reader.
+Opening a named UNIX stream socket with or without a listening peer might
+succeed depending on the operating system, but
+the resulting file descriptor erronously reports available data immediately,
+and the following read() or write() call always fails with "invalid
+argument". Even worse, while such a filesystem entry is identified as socket by
+"file" command and by fstat(), getsockopt() after open() gives error "Socket operation on non-socket".
+Use GOPEN for reasonable behaviour!
+Option groups: FD, OPEN, NAMED, and specific for data object type (FILE, FIFO,
+CHRDEV+TERMIOS, BLKDEV, or SOCKET).
+
+
+GOPEN:path
+path
+
+"Generic open". Tries to open the given path in a smarter way. If the path
+exists and is a socket, it is connected to; if connecting fails,
+socat assumes a datagram socket and later uses sendto() calls for data
+transfer.
+If the path exists and is not a socket, it is opened:
+in RDONLY environment for reading from position 0,
+in WRONLY environment for appending (O_APPEND),
+in RDWR env. for reading and/or writing starting from position 0.
+If the path does not exist:
+in RDONLY environment this is an error
+in WRONLY environment the file is created (O_CREAT)
+in RDWR env. for reading and/or writing starting from position 0.
+However, these flags may be overriden by user supplied options
+(e.g., "append=0")
+Option groups: FD, NAMED, and specific for data object type (FILE, FIFO,
+CHRDEV+TERMIOS, BLKDEV, or SOCKET).
+
+
+CREATE:path
+CREAT:path
+
+Opens the named file with creat(). With UNIX semantics, this address is just a
+variation of the OPEN address, see there for more details.
+Note: The creat() system call does not create a completely new file, but
+inherits some properties of the old file if it exists, e.g. permissions. Use
+option "unlink-early" to remove the old entry before.
+Option groups: FD, NAMED, FILE
+Useful options: unlink-late
+
+
+PIPE:path
+FIFO:path
+
+Creates and opens a pipe if path does not exist; opens path if it already
+exists.
+Option groups: FD, NAMED, FIFO
+Note: this address uses the mknod(2) system call to create the named pipe. On
+FreeBSD, this call requires root privilege
+
+
+EXEC:cmdline
+
+Forks off a child process after establishing a bidirectional communication
+channel (with socketpair, pipes, or pty). The child then starts "cmdline" with
+execvp().
+Note: spaces and shell meta characters in cmdline must be quoted if socat is
+invoked from the command line.
+Option groups: FD, FORK, EXEC, SOCKET, SOCK_UNIX, FIFO, TERMIOS
+Useful options: path, fdin, fdout, chroot, su, pty, stderr
+Note: on AIX, search permissions on /dev/pts/ are required to use option pty.
+
+
+SYSTEM:cmdline
+
+Forks off a child process after establishing a bidirectional communication
+channel (with socketpair, pipes, or pty). The child then starts "cmdline" with
+system().
+Note: spaces and shell meta characters in cmdline must be quoted if socat is
+invoked from the command line.
+Option groups: FD, FORK, EXEC, SOCKET, SOCK_UNIX, FIFO, TERMIOS
+Useful options: path, fdin, fdout, chroot, su, pty, stderr
+Note: there are slightly different semantics with options pty or pipes, because
+they do not communicate an EOF condition to the shell process. Therefore, the
+shell process and its child do not terminate due to EOF, but are explicitly
+killed during close of the socat file handle. Consider using
+exec:'/bin/sh -c command',pty...
+
+
+UNIX:path
+LOCAL:path
+
+Connects to a UNIX domain socket.
+Option groups: FD, SOCKET, SOCK_UNIX
+NOTE: you need rw permissions to connect to a local socket. My Linux answers
+with "connection refused" to insufficient permissions, not existing
+socket, not a socket, or just a socket entry without a listening process.
+NOTE: this address does not implement option group NAMED because its connect
+call succeeds only if there is already someone listening, but at this point the
+NAMED group actions no longer affect this socket, only the fs entry.
+
+
+UNIX-listen:path
+UNIX-l:path
+
+Create a listening UNIX domain socket. With the fork option, for each accepted
+connection a new process is forked off, and more connections are accepted on
+the parent socket. Without fork, only the first connection is accepted.
+Option groups: FD, NAMED, SOCKET, SOCK_UNIX, LISTEN, CHILD
+
+
+IP:host:protocol
+IP4:host:protocol
+
+Open a raw socket with IP4 protocol. This mode sends packets to and accepts
+them only from host. protocol is a number from 0 to 255, with 1 meaning ICMP,
+6..TCP, 17..UDP, 255..raw IP; 0 might be unsupported by the local IP stack,
+resulting in an error.
+Requires root privilege.
+Note: my Linux 2.4.10 kernel seems to drop payloads smaller than 8
+bytes on their way from the network to the application.
+Option groups: FD, SOCKET, SOCK_IP
+
+
+TCP:host:port
+TCP4:host:port
+INET:host:port
+
+Create a TCP/IP4 client socket and connect to the given host/port combination.
+Option groups: FD, SOCKET, SOCK_IP, IPAPP, IP_TCP
+Useful options: crlf, bind, tos, mtudiscover, mss, nodelay,
+
+
+TCP-l:port
+TCP-listen:port
+TCP4-l:port
+TCP4-listen:port
+INET-l:port
+INET-listen:port
+
+Create a TCP/IP4 server socket and wait for an incoming connection. With the
+fork option, for each accepted connection a new process is forked off, and more
+connections are accepted on the parent socket. Without fork, only the first
+connection is accepted.
+Option groups: FD, SOCKET, SOCK_IP, IPAPP, IP_TCP, LISTEN, RANGE, CHILD
+Useful options: fork, crlf, bind, backlog, mtu, tcpwrap
+
+
+UDP:host:port
+UDP-CONNECT:host:port
+
+ Connects to port on host using UDP/IP version 4 or 6
+ depending on address specification, name resolution, or option pf.
+ Please note that,
+ due to UDP protocol properties, no real connection is established; data has
+ to be sent for `connecting' to the server, and no end-of-file condition can
+ be transported.
+Option groups: FD, SOCKET, SOCK_IP4, SOCK_IP6, IP_UDP
+Useful options: ttl
+
+UDP4:host:port
+UDP4-CONNECT:host:port
+
+Like UDP-CONNECT, but only supports IPv4 protocol.
+Option groups: FD, SOCKET, SOCK_IP, IPAPP, IP_UDP
+
+
+UDP-listen:port
+UDP-l:port
+
+Emulates a UDP server in the same way as netcat: Create a UDP/IP4 socket and
+bind to the given port. Then wait for the first packet, get its sender address
+(without consuming its data), connect() to this address, and leave xioopen().
+Afterwards, our socket only communicates with this peer.
+Option groups: FD, SOCKET, SOCK_IP, IPAPP, IP_UDP, RANGE
+Note: with fork option, child processes might hang forever because UDP cannot
+transport EOF conditions.
+
+
+#UDP-dgram:port
+#UDP-d:port
+#
+#Create and use a pure datagram oriented UDP socket.
+#The following restrictions apply:
+#* range option does not work
+#* de facto this is a read-only endpoint: sending data to 0.0.0.0 might fail.
+
+
+TCP6:host:port
+INET6:host:port
+
+Create a TCP/IP6 client socket and connect to the given host/port combination.
+Option groups: FD, SOCKET, SOCK_IP, IPAPP, IP_TCP
+Note: Address syntax parsing is awkward, since the IPv6 address word separator
+is ':' which is used as port separator too.
+An FTP listen entry looks in netstat ":::21"!
+
+
+TCP6-l:port
+TCP6-listen:port
+INET6-l:port
+INET6-listen:port
+
+Create a TCP server socket and wait for an incoming connection. With the fork
+option, for each accepted connection a new process is forked off, and more
+connections are accepted on the parent socket. Without fork, only the first
+connection is accepted.
+Option groups: FD, SOCKET, SOCK_IP, IPAPP, IP_TCP, LISTEN, RANGE, CHILD
+
+
+SOCKS4:sockd:host:port
+SOCKS:sockd:host:port
+
+Use a socks server, socks protocol version 4, to build a TCP (IPv4) connection.
+Sockd is the name or address of the socks server, host and port specify the
+destination address. Use option socksport if the socks server does not listen
+on port 1080.
+Option groups: FD, SOCKET, SOCK_IP, IPAPP, IP_TCP, IP_SOCKS
+Useful options: sp, socksport, socksuser
+Note: If you do not specify option socksuser, xioopen tries to derive it from
+environment: LOGNAME or USER, and might therefore undisclose your identity.
+
+
+SOCKS4a:sockd:host:port
+
+Like SOCKS4, but use the socks version 4a extension for destination name
+resolution on the socks server.
+Option groups: FD, SOCKET, SOCK_IP, IPAPP, IP_TCP, IP_SOCKS
+
+
+PTY
+
+Creates a pseudo terminal (pty) and uses its master side. Another process may
+open the pty´s slave side using it like a serial line or terminal.
+Option groups: FD,NAMED,PTY,TERMIOS
+Useful options: link, openpty, mode, user, group
+
+
+OPENSSL-CONNECT:host:port
+OPENSSL:host:port
+
+Tries to establish a SSL connection to port on host using TCP/IPv4.
+Note: this is currently only an experimental integration of openssl!
+(it does not provide any trust between the peers because is does not check
+certificates!)
+Option groups: FD,SOCKET,SOCK_IP4,IP_TCP,OPENSSL,RETRY
+Useful options: cipher, method, verify, cafile, capath, certificate, bind, sourceport, retry
+
+
+OPENSSL-LISTEN:port
+
+Listens on tcp4 port. When a connection is accepted, this address behaves as
+SSL server.
+Option groups: FD,SOCKET,SOCK_IP4,TCP,LISTEN,CHILD,RANGE,OPENSSL,RETRY
+Usefule options: cipher, method, verify, cafile, capath, certificate, retry
+
+
+PROXY:proxy:host:port
+PROXY-CONNECT:proxy:host:port
+
+Connects to an HTTP proxy server on port 8080 using TCP/IPv4, and sends a
+CONNECT request for host:port. If the proxy grants access and succeeds to
+connect to the target, data transfer between socat and the target can
+start. Note that the traffic need not be HTTP but can be an arbitrary
+protocol.
+Option groups: FD,SOCKET,IP4,TCP,HTTP
+Useful options: proxyport, ignorecr, proxyauth, crnl, bind, mss, sourceport
+
+===============================================================================
+
+Option Groups:
+
+Each option is member of one option group. Address definitions specify which
+option groups they support. This allows to reject unapplyable options in an
+early stage of address processing.
+
+Address groups are identified by single bit positions. Option definitions
+specify to which group the option belongs (some options are member or more than
+one group). Addresses use a bit pattern to specify which option groups they
+support.
+
+Currently the following option groups are defined:
+
+GROUP_FD: All addresses that result in one or more file descriptors. These
+options are typically applied with fcntl() or some special calls like fchown()
+or fchmod(). There is no documented restriction to apply these functions to any
+file descriptor; but they are not always meaningful, and sometimes lead to OS
+exceptions.
+
+GROUP_APPL: All addresses. The options do not need file descriptors, because
+they manipulate the data streams at application level (ignoreeof, line
+terminator conversion).
+
+GROUP_PROCESS: For options that change process related attributes, like user id
+(setuid).
+
+GROUP_FIFO: Options for pipes. Currently not used.
+
+GROUP_CHR: Options for character devices. Currently not used.
+
+GROUP_BLK: Options for block devices. Currently not used.
+
+GROUP_REG, GROUP_FILE: Options for regular files. Currently not used.
+
+GROUP_SOCKET: Options for arbitrary type sockets, e.g. so-sndbuf, so-linger.
+
+GROUP_NAMED: Options for file system entries, e.g. user-early, unlink.
+
+GROUP_OPEN: Options that are applied with the open() system call.
+
+GROUP_EXEC: Options for program or script execution, e.g. path.
+
+GROUP_FORK: Options for communication with children processes, e.g. fdin, pty.
+
+GROUP_LISTEN: Options for listening sockets. Only backlog.
+
+GROUP_DEVICE: not used
+
+GROUP_CHILD: Options for addresses that may fork off independent child
+processes. Currently only option fork.
+
+GROUP_RETRY: Options for failure handling. Currently not used.
+
+GROUP_TERMIOS: Options for terminal settings, e.g. echo, b38400, raw.
+
+GROUP_READLINE: Options for readline (GNU line editing and history).
+
+GROUP_RANGE: Options for checking peer address. Currently only range.
+
+GROUP_SOCK_UNIX: Options for UNIX domain sockets. Currently not used.
+
+GROUP_SOCK_IP4: Options for IP4 sockets. Currently not used.
+
+GROUP_SOCK_IP6: Options for IP6 sockets. Currently not used.
+
+GROUP_SOCK_IP: Options for IP sockets, e.g. mtu, ip-options, ttl.
+
+GROUP_IP_UDP: Options for UDP sockets. Currently not used.
+
+GROUP_IP_TCP: Options for TCP sockets, e.g. maxseg, nodelay.
+
+GROUP_IPAPP: Options for UDP and TCP sockets. Currently only sourceport.
+
+GROUP_IP_SOCKS4: Options for SOCKS client connections, e.g. socksuser.
+
+GROUP_PROCESS: Options for process wide attributes, e.g. su, chroot.
+
+GROUP_APPL: Options handled by application. Currently not used.
+
+GROUP_PTY: Options for pseudo terminals. Used with addresses PTY, EXEC, and
+SYSTEM.
+
+GROUP_OPENSSL: Options for the OPENSSL address.
+
+There are "combined" group definitions too:
+#define GROUP_ANY (GROUP_PROCESS|GROUP_APPL)
+#define GROUP_ALL 0xffffffff
+
+===============================================================================
+
+Address Options
+
+Address options are identified by a case insensitive keyword. If the options
+needs a parameter value, the option syntax is always:
+OPTION=VALUE
+Currently there do not exist options that take more than one argument;
+sometimes, two values are combined to form one argument value, e.g. IP4 address
+and port:
+192.168.0.1:80
+
+Note:
+"Type" describes the type of data that may or must be given to the option and
+that is passed to the system. There are some options with boolean semantics
+(on/off or yes/no), but their values are passed to the system with an int
+parameter. This situation is indicated as "Logical type: bool" and "Physical
+type: int". In this case xioopen passes the physical value to the system,
+giving the user one more hacking playground.
+
+
+Option: append
+
+Type: BOOL
+Option group: FD
+Phase: LATE
+Platforms: all (UNIX98)
+
+Sets the O_APPEND flag via a fcntl() call and F_SETFL; with OPEN type
+addresses, this flag is applied with the open() call. All data written is
+appended to the actual file end, even if other processes have written to or
+truncated the file in the meantime.
+
+
+Option: async
+
+Type: BOOL
+Option group: FD
+Phase: LATE
+Platforms: FreeBSD, Linux, SunOS
+
+Sets the O_ASYNC (or FASYNC) flag via a fcntl() call and F_SETFL; with FILE
+addresses, this flag is applied with the open() call. Consult your kernel
+documentation for effects of this flag.
+NOTE: socat does not handle the SIGIO signal.
+
+
+Option: cloexec
+
+Type: BOOL
+Option group: FD
+Phase: LATE
+Platforms: all
+
+Sets the FD_CLOEXEC (close-on-exec) flag on the file descriptor via a
+fcntl()call with F_SETFD. Use with caution, because xioopen() makes use of this
+flag to archieve what we consider the most reasonable behaviour; using this
+option overrides xioopen's setting!
+
+
+Option: flock-ex
+Aliases: flock, lock
+
+Type: BOOL
+Option group: FD
+Phase: FD
+Platforms: FreeBSD, Linux
+
+Applies the flock(fd, LOCK_EX) call to the file descriptor(s). This locks a file
+exclusively (but only for processes also using flock() on this file - otherwise, they seem to have unrestricted access).
+If the file is already locked with flock, our flock call blocks until the other
+processes lock is released.
+Note: the "lock" option name alias applies to this option only
+ if the fcntl locking mechanism is not available on a platform.
+
+
+Option: flock-ex-nb
+Aliases: flock-nb
+
+Type: BOOL
+Option group: FD
+Phase: FD
+Platforms: FreeBSD, Linux
+
+Applies the flock(fd, LOCK_EX|LOCK_NB) call to the file descriptor(s). This locks a file
+exclusively (but only for processes also using flock() on this file -
+otherwise, they seem to have unrestricted access).
+If the file is already locked with flock, our flock call returns the error
+"Resource temporarily unavailable".
+
+
+Option: flock-sh
+
+Type: BOOL
+Option group: FD
+Phase: FD
+Platforms: FreeBSD, Linux
+
+Applies a shared advisory lock to the file using the flock(fd, LOCK_SH) call.
+This prevents processes from locking the file exclusively.
+If the file has already an exclusive lock, our flock call blocks until the
+other processes lock is released.
+
+
+Option: flock-sh-nb
+
+Type: BOOL
+Option group: FD
+Phase: FD
+Platforms: FreeBSD, Linux
+
+Applies a shared advisory lock to the file using the flock(fd, LOCK_SH|LOCK_NB) call.
+This prevents processes from locking the file exclusively.
+If the file has already an exclusive lock, our flock call returns with error
+"Resource temporarily unavailable".
+
+
+Option: f-setlk-rd
+Aliases: setlk-rd
+
+Type: BOOL
+Option group: FD
+Phase: FD
+Platforms: all
+
+Locks the complete file with fcntl(fd, F_SETLK, {F_RDLCK}) (complete means from its
+start to its maximal length). This locks the file exclusively (but only if the
+other processes accessing this file also use f-setlk or f-setlkw - otherwise,
+they seem to have unrestricted access). If the file is already locked with
+f-setlk or f-setlkw, the fcntl call blocks until release by the other process.
+
+
+Option: f-setlk-wr
+Aliases: f-setlk, setlk-wr, setlk
+
+Type: BOOL
+Option group: FD
+Phase: FD
+Platforms: all
+
+Locks the complete file with fcntl(fd, F_SETLK, {F_WRLCK}) (complete means from its
+start to its maximal length). This locks the file exclusively (but only if the
+other processes accessing this file also use f-setlk or f-setlkw - otherwise,
+they seem to have unrestricted access). If the file is already locked with
+f-setlk or f-setlkw, the fcntl call blocks until release by the other process.
+
+
+Option: f-setlkw-rd
+Aliases: setlkw-rd
+
+Type: BOOL
+Option group: FD
+Phase: FD
+Platforms: all
+
+Locks the complete file with fcntl(fd, F_SETLKW, {F_RDLCK}) (complete means from its
+start to its maximal length). This locks the file exclusively (but only if the
+other processes accessing this file also use f-setlk or f-setlkw - otherwise,
+they seem to have unrestricted access). If the file is already locked with
+f-setlk or f-setlkw, fcntl returns with EAGAIN.
+
+
+Option: f-setlkw-wr
+Aliases: setlkw-wr, f-setlkw, setlkw, lockw, lock
+
+Type: BOOL
+Option group: FD
+Phase: FD
+Platforms: all
+
+Locks the complete file with fcntl(fd, F_SETLKW, {F_WRLCK}) (complete means from its
+start to its maximal length). This locks the file exclusively (but only if the
+other processes accessing this file also use f-setlk or f-setlkw - otherwise,
+they seem to have unrestricted access). If the file is already locked with
+f-setlk or f-setlkw, fcntl returns with EAGAIN.
+
+
+Option: fork
+
+Type: BOOL
+Option group: CHILD
+Phase: PASTACCEPT
+Platforms: all
+
+Without fork (or fork=0), the listening process accepts exactly one
+connections, and terminates afterwards. With fork set, it forks off a new socat
+child process for each incoming connection.
+It is very important to understand what socat does with this fork option:
+The parent process remains in a loop of accept() and fork() calls until
+terminated from outside. The child process leaves this loop and goes on with
+the socat processing. If the fork occurs in the first address argument, the
+child process continues with parsing and activating the second address
+argument. This will in most cases be what you want or expect.
+If the fork call occurs in socats second address argument, all children will
+inherit and share the already activated first address.
+
+
+Option: group=value
+Aliases: gid=value
+
+Type: GIDT or unsigned int
+Option group: NAMED
+Type: GIDT
+Platforms: all
+
+Takes one argument, a UNIX group name or a numeric group id. The first
+character of value is a digit for group ids.
+With NAMED addresses this option is applied via a chown() call, with a
+fchown() call otherwise.
+If groupname is a name it must be a valid groupname from /etc/group and is
+converted to a group id with a getgrnam(3) call.
+On most modern operating systems, the owner of the process must be member of
+the group being set; only root may set any group, even numbers without group
+name.
+A Linux 2.2.10 kernel SIGSEGVs the process in the fchown() call when this
+option is used with a socket or pipe. Is fixed with Linux 2.4.
+LINUXBUG TESTCASE:
+SH1: socat -D - unix-l:/tmp/socket,unlink-early
+SH2: socat -d -d -d -d -D gopen:/tmp/socket,group=floppy -
+
+
+Option: group-late=value
+
+Type: GIDT or string
+Option group: FD
+Type: GIDT
+Platforms: all
+
+Takes one argument, a UNIX group name or a numeric group id. The first
+character of value is a digit for group ids.
+This option is applied via a fchown(2) call.
+If groupname is a name it must be a valid groupname from /etc/group and is
+converted to a group id with a getgrnam(3) call.
+On most modern operating systems, the owner of the process must be member of
+the group being set; only root may set any group, even numberic group ids
+without group name.
+
+
+Option: o-nonblock
+Aliases: nonblock
+
+Type: BOOL
+Option group: FD
+Phase: FD
+Platforms: all (UNIX98)
+
+Sets the O_NONBLOCK flag of a file descriptor via a fcntl(2) call and F_SETFL;
+with OPEN type addresses, this flag is applied with the open() call.
+It does not change the behaviour of socat's data transfer loop because socat
+uses select() which blocks nevertheless.
+Currently is has only two documented uses:
+1) With address TCP, the connect() call
+does not block; instead, it continues through the open step. The channel is
+passed to the select() call. If something is written to the channel before it
+is connected, this is an error. If connection fails, a read condition occurs
+and read() returns the error.
+2) Opening a named pipe does not block with this option.
+
+
+Option: o-ndelay
+Aliases: ndelay
+
+Type: BOOL
+Option group: FD
+Phase: LATE
+Platforms: HP-UX, SunOS (UNIX98)
+
+Under Solaris it sets the O_NDELAY of the file descriptor via a fcntl(2) call
+and F_SETFL; with OPEN type addresses, this flag is applied with the open()
+call.
+With all other operating systems, this is just another name for the nonblock option.
+
+
+Option: o-noatime
+Aliases: noatime
+
+Type: BOOL
+Option group: FD
+Phase: FD
+Platforms: Linux
+
+Sets the O_NOATIME flag of a file descriptor via a fcntl(2) call and F_SETFL;
+with OPEN type addresses, this flag is applied with the open() call.
+It prevents the access time from being updated during read operations.
+
+
+Option: perm=value
+Aliases: mode=value
+
+Type: MODET (mode_t)
+Option group: NAMED
+Phase: FD
+Platforms: all
+
+This option changes the mode (permissions) of an addresses inode. xioopen
+tries to apply this option already during open phase. If the address does not
+have a open phase or if the option cannot be applied there, the value is
+applied directly on the file descriptor afterwards.
+It is up to you to (1) have the permission to change the permissions, and (2)
+not to set permissions that prevent you from performing your transactions :-)
+NOTE: At least with some Linux 2.2, setting permissions on an existing file or
+device with fchmod() does not change the permissions of its inode on disk. See
+perm-early which uses chmod() instead.
+NOTE: At least with some Linux 2.2, restricting mode on file descriptors does
+not restrict this file descriptors data transfer capabilities.
+
+
+Option: perm-late=value
+
+Type: MODET (mode_t)
+Option group: FD
+Phase: LATE
+Platforms: all
+
+This option changes the mode (permissions) of a file descriptor with fchown()
+in the last phase of address processing.
+
+
+Option: seek-set=offset
+Aliases: lseek=offset, seek=offset
+
+Type: OFF32 or OFF64
+Option group: BLK
+Phase: LATE
+Platforms: HP-UX, Linux, SunOS
+
+Positions the file at the given absolute offset, using lseek() (or lseek64() if
+available) with SEEK_SET.
+
+
+Option: seek-cur=offset
+
+Type: OFF32 or OFF64
+Option group: BLK
+Phase: LATE
+Platforms: HP-UX, Linux, SunOS
+
+Positions the file at the given offset from the current position,
+using lseek() (or lseek64() if available) with SEEK_SET.
+
+
+Option: seek-end=offset
+
+Type: OFF32 or OFF64
+Option group: BLK
+Phase: LATE
+Platforms: HP-UX, Linux, SunOS
+
+Positions the file at the given offset from the file end,
+using lseek() (or lseek64() if available) with SEEK_END.
+
+
+Option: lseek32-set=offset
+Aliases: lseek32=offset
+
+Type: OFF32
+Option group: BLK
+Phase: LATE
+Platforms: HP-UX, Linux, SunOS
+
+Positions the file at the given absolute offset using lseek() with SEEK_SET.
+This call might fail for non
+random access data objects like character devices or sockets.
+NOTE: this option seems to be useless on files with O_APPEND set.
+
+
+Option: lseek32-cur=offset
+
+Type: OFF32 (instead of off_t)
+Option group: BLK
+Phase: LATE
+Platforms: HP-UX, Linux, SunOS
+
+Positions the file at the given offset from the current position using lseek()
+with SEEK_CUR. This call
+might fail for non random access data objects like character devices.
+On Linux, the seek() call fails on pipes, sockets and ttys but works on files
+and /dev/null
+NOTE: this option seems to be useless on files with O_APPEND set.
+
+
+Option: lseek32-end=offset
+
+Type: OFF32
+Option group: BLK
+Phase: LATE
+Platforms: HP-UX, Linux, SunOS
+
+Positions the file at the given offset from the file end using lseek() with
+SEEK_END. This call might fail
+for non random access data objects like character devices.
+NOTE: this option seems to be useless on files with O_APPEND set.
+
+
+Option: lseek64-set=offset
+Aliases: lseek64=offset
+
+Type: OFF64
+Option group: BLK
+Phase: LATE
+Platforms: all
+
+Positions the file at the given absolute offset using lseek64() with SEEK_SET.
+This call might fail for non
+random access data objects like character devices or sockets.
+NOTE: this option seems to be useless on files with O_APPEND set.
+
+
+Option: lseek64-cur=offset
+
+Type: OFF64
+Option group: BLK
+Phase: LATE
+Platforms: all
+
+Positions the file at the given offset from the current position using
+lseek64() with SEEK_CUR. This call
+might fail for non random access data objects like character devices.
+NOTE: this option seems to be useless on files with O_APPEND set.
+
+
+Option: lseek64-end=offset
+
+Type: OFF64
+Option group: BLK
+Phase: LATE
+Platforms: all
+
+Positions the file at the given offset from the file end using lseek64() with
+SEEK_END. This call might fail
+for non random access data objects like character devices.
+NOTE: this option seems to be useless on files with O_APPEND set.
+
+
+Option: chroot=path
+
+Type: STRING
+Option group: PROCESS
+Phase: LATE
+Platforms: all
+
+Invokes the chroot() system call with the given path after the address
+resolution, so the path names of the address must be specified with absolute
+pathes.
+Note: when you combine chroot with substuser, with substuser applied within the
+chroot environment, usually the etc/passwd and etc/group files in the chroot
+environment are used for group set etc.
+See appendix "generating a sandbox"
+
+
+Option: chroot-early=path
+
+Type: STRING
+Option group: PROCESS
+Phase: EARLY
+Platforms: all
+
+Invokes the chroot() system call with the given path before the address is
+resolved, this means before file opening in OPEN, GOPEN and before program
+execution in EXEC and SYSTEM, so their pathes must be specified related to
+their chroot directory.
+See appendix "generating a sandbox"
+
+
+Option: setgid=group
+
+Type: GIDT (gid_t or string)
+Option group: PROCESS
+Phase: LATE2
+Platforms: all
+
+Invokes setgid() with the group id. For EXEC and SYSTEM this call is performed
+for the child process after the fork and therefore does not affect the socat
+process directly. For LISTEN group addresses with fork option, this call is
+performed only on the child processes. For all other addresses, it is performed
+in the late phase of address processing, so it does not affect the address
+where it is used, but for the next address (if any), and for the data loop.
+Note: setgid() does not remove any groups from the current process group set.
+
+
+Option: setuid=user
+
+Type: UIDT (uid_t or string)
+Option group: PROCESS
+Phase: LATE2
+Platforms: all
+
+Invokes setuid() with the user id. For EXEC and SYSTEM this call is performed
+for the child process after the fork and therefore does not affect the socat
+process directly. For LISTEN group addresses with fork option, this call is
+performed only on the child processes. For all other addresses, it is performed
+in the late phase of address processing, so it does not affect the address
+where it is used, but the next address (if any), and the data loop.
+Note: setuid() is invoked AFTER setgid(), if both are applied.
+Note: setuid() does not influence the processes group set; in most cases, you
+want to prefer substuser option.
+
+
+Option: substuser=user
+Aliases: su=user
+
+Type: UIDT (uid_t or string)
+Option group: PROCESS
+Phase: LATE2
+Platforms: all
+
+Tries to switch the process to the given user and its group set.
+To make sure that the groups are set correctly for the new process owner, the
+system calls initgroups(), setgid(), and setuid() are invoked with the
+appropriate arguments.
+On sane operating system, this option requires root privileges.
+Note: this option sets the user and group ids of the process, but does not
+change the environment; therefore, all variables including $USER, $HOME,
+$LOGNAME, $SHELL etc. are inherited from the old users environment.
+Note: starting a SETUID program after applying substuser or setuid gives the
+process the SETUID owner, which might give root privileges again.
+
+
+Option: substuser-delayed=user
+Aliases: su-d=user
+
+Type: UIDT (unsigned int or string)
+Option group: PROCESS
+Phase: INIT
+Platforms: all
+
+Like substuser, but reads the user and group information in an early phase of
+address processing, but applies the appropriate system calls in a late
+phase. This allows to use user information from the host in a chroot
+environment, without exposing this data within the sandbox.
+
+
+Option: o-trunc
+Aliases: trunc
+
+Type: BOOL
+Option group: OPEN
+Phase: LATE
+Platforms: all
+
+Sets the O_TRUNC flag of the open() call, thus truncating the file to zero
+length.
+#! block devices?
+
+
+Option: ftruncate=value
+Aliases: truncate=value
+
+Type: OFF32 or OFF64
+Option group: REG
+Phase: LATE
+Platforms: HP-UX, Linux, SunOS
+
+Invokes the ftruncate() (or ftruncate64() if available) call for the file descriptor with the given value,
+thus reducing the length of the file to the given length.
+On Linux, ftruncate() fails on sockets and devices but works on regular files
+and pipes.
+#! block devices?
+Note: AIX docu says: for regular files only
+
+
+Option: ftruncate32=value
+
+Type: OFF32
+Option group: REG
+Phase: LATE
+Platforms: HP-UX, Linux, SunOS
+
+Invokes the ftruncate() call (even if ftruncate64() is available) call for the file descriptor with the given value,
+thus reducing the length of the file to the given length.
+
+
+Option: ftruncate64=value
+
+Type: OFF64
+Option group: REG
+Phase: LATE
+Platforms: all
+
+Invokes the ftruncate64() call if available, for the file descriptor with the given value,
+thus reducing the length of the file to the given length.
+
+
+Option: o-binary
+Aliases: binary, bin
+
+Type: BOOL
+Option group: FD
+Phase: OPEN
+Platforms: none; Cygwin
+
+Sets the O_BINARY flag with open() or fcntl() to avoid implicit line terminator conversions.
+
+
+Option: o-text
+Aliases: text
+
+Type: BOOL
+Option group: FD
+Phase: OPEN
+Platforms: none; Cygwin
+
+Sets the O_TEXT flag with open() or fcntl() to force implicit line terminator conversions.
+
+
+Option: o-noinherit
+Aliases: noinherit
+
+Type: BOOL
+Option group: FD
+Phase: OPEN
+Platforms: none; Cygwin
+
+Sets the O_NOINHERIT flag with open() or fcntl() to not keep this file open in a spawned process.
+
+
+Option: cool-write
+Aliases: coolwrite
+
+Type: BOOL
+Option group: FD
+Phase: INIT
+Platforms: all
+
+ Takes it easy when write fails with EPIPE or ECONNRESET and logs the message
+ with notice level instead of error.
+ This prevents the log file from being filled with useless error messages
+ when socat is used as a high volume server or proxy where clients often
+ abort the connection.
+ This option is experimental.
+
+
+Option: end-close
+Aliases: close
+
+Type: CONST
+Option group: FD
+Phase: INIT
+Platforms: all
+
+ Changes the (address dependent) method to close a connection to just close
+ the file descriptors. This is useful when the connection is to be reused by
+ or shared with other processes.
+ Normally, socket connections will be ended with shutdown(2) which
+ terminates the socket even if it is shared by multiple processes.
+ close(2) "unlinks" the socket from the process but keeps it active as
+ long as there are still links from other processes.
+ 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.
+
+
+Option: user=value
+Aliases: owner=value, uid=value
+
+Type: UIDT (unsigned int or string)
+Option group: NAMED
+Phase: FD
+Platforms: all
+
+Takes one argument, a UNIX user name or a numeric user id. The first
+character of value is a digit for user ids.
+For NAMED addresses, if the file already exists, this option is applied via a
+chown() call, with fchown() for all other cases.
+If username is a name it must be a valid username from /etc/passwd and is
+converted to a user id with a getpwnam() call.
+On sane operating systems, the owner of the process must be root to change
+the owner of a file descriptor; root may even apply undefined (unnamed) user
+ids.
+My Linux 2.2 kernel SIGSEGVs the process in the fchown() call when this
+option is used with a (UNIX, unconnected or connected) socket or pipe. Linux
+2.4.0 handles this call correctly.
+TESTCASE: ./socat -d -d -d -d - tcp:loopback:21,user=root
+
+
+Option: user-late=value
+Aliases: uid-l=value
+
+Type: UIDT (unsigned int or string)
+Option group: FD
+Phase: LATE
+Platforms: all
+
+Takes one argument, a UNIX user name or a numeric user id. The first
+character of value is a digit for user ids.
+This option is applied via a fchown() call just before xioopen_single()
+terminates.
+If username is a name it must be a valid username from /etc/passwd and is
+converted to a user id with a getpwnam() call.
+On sane operating systems, the owner of the process must be root to change
+the owner of a file descriptor; root may even apply undefined (unnamed) user
+ids.
+My Linux 2.2 kernel SIGSEGVs the process in the fchown() call when this
+option is used with a socket or pipe.
+
+
+===============================================================================
+OPEN group options
+Options of this group may be used with all addresses that support OPEN group
+options.
+
+
+Option: o-rdonly
+Aliases: rdonly
+
+Type: BOOL (inherent - no value)
+Option group: OPEN
+Phase: OPEN
+Platforms: all
+
+Use O_RDONLY with the open() call instead of the position dependend default.
+Take care not to block later write operations.
+
+
+Option: o-wronly
+Aliases: wronly
+
+Type: BOOL (inherent - no value)
+Option group: OPEN
+Phase: OPEN
+Platforms: all
+
+Use O_WRONLY with the open() call instead of the position dependend default.
+Take care not to block later write operations.
+
+
+Option: o-rdwr
+Aliases: rdwr
+
+Type: BOOL (inherent - no value)
+Option group: OPEN
+Phase: OPEN
+Platforms: all
+
+Use O_RDWR with the open() call instead of the position dependend default.
+
+
+Option: o-create
+Aliases: create, creat
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: all
+
+Sets the O_CREAT flag of the open() call. This means that it is not an error if
+the file does not exist.
+
+
+Option: o-defer
+Aliases: defer
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: none
+
+Sets the O_DEFER flag of the open() call. This means that write data is stored
+in paging space until an fsync() call.
+
+
+Option: o-delay
+Aliases: delay
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: none
+
+Sets the O_DELAY flag of the open() call. This lets open block until the share
+conditions are fulfilled (see nshare, rshare)
+
+
+Option: o-direct
+Aliases: direct
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: FreeBSD, HP-UX, Linux
+
+Sets the O_DIRECT flag of the open() call.
+
+
+Option: o-directory
+Aliases: directory
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: Linux
+
+Sets the O_DIRECTORY flag of the open() call. This lets open fail if the given
+path is not a directory. This does not seem to be useful with socat.
+
+
+Option: o-dsync
+Aliases: dsync
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: HP-UX, Linux, SunOS (UNIX98)
+
+Sets the O_DSYNC flag with the open() call. This lets write() calls wait until
+modification metainfo is physically written to media.
+
+
+Option: o-excl
+Aliases: excl
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: all
+
+Sets the O_EXCL flag of the open() call.
+
+
+Option: o-largefile
+Aliases: largefile
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: HP-UX, Linux, SunOS
+
+Sets the O_LARGEFILE flag of the open() flag.
+
+
+Option: o-noctty
+Aliases: noctty
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: all
+
+Sets the O_NOCTTY flag of the open() call, so the opened device does not become
+the controlling tty of the process.
+
+
+Option: o-nofollow
+Aliases: nofollow
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: FreeBSD, Linux
+
+Sets the O_NOFOLLOW flag of the open() call. This means that the last component
+of the open path must no be a symlink.
+
+
+Option: o-sync
+Aliases: sync
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: all (UNIX98)
+
+Sets the O_SYNC flag with the open() call. This lets write() calls wait until
+data is physically written to media.
+
+
+Option: o-rshare
+Aliases: rshare
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: none
+
+Sets the O_RSHARE flag of the open() call. This means that the file must not be
+opened for writing by other processes ("read sharing").
+
+
+Option: o-nshare
+Aliases: nshare
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: none
+
+Sets the O_NSHARE flag of the open() call. This means that the file must not be
+shared with other processes ("no sharing").
+
+
+Option: o-rsync
+Aliases: rsync
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: HP-UX, Linux, SunOS (UNIX98)
+
+Sets the O_RSYNC flag with the open() call. This lets write() calls wait until
+read metainfo is physically written to media.
+
+
+Option: o-priv
+Aliases: priv
+
+Type: BOOL
+Option group: OPEN
+Phase: OPEN
+Platforms: none (Solaris)
+
+Sets the O_PRIV flag with the open() call.
+
+===============================================================================
+NAMED group options
+This group is valid for all addresses that refer to a file system entry like
+file, device, named pipe, or named UNIX domain socket.
+
+
+Option: unlink-early
+Aliases: new
+
+Type: BOOL
+Option group: NAMED
+Phase: EARLY
+Platforms: all
+
+This options tries to remove the filesystem entry given in the address before
+starting any other processing (even before user-early, perm-early, or
+group-early). unlink() is called; note that this call, in contrast to rm(1),
+removes entries regardless of their permissions. Instead, ownership or root
+privileges and write permissions in the directory are required and sufficient.
+
+
+Option: unlink
+
+Type: BOOL
+Option group: NAMED
+Phase: PREOPEN
+Platforms: all
+
+This options tries to remove the filesystem entry given in the address before
+it is tried to open, but past user-early, perm-early, or group-early).
+unlink() is called; note that this call, in contrast to rm(1), removes entries
+regardless of their permissions. Instead, ownership or root privileges and
+write permissions in the directory are required and sufficient.
+
+
+Option: unlink-late
+
+Type: BOOL
+Option group: NAMED
+Phase: PASTOPEN
+Platforms: all
+
+This option tries to remove the filesystem entry after it has been opened.
+Options can still be applied to the file descriptor, and
+the node or files data can be used, but it can no longer be accessed by other
+processes (except by tricks?), and after closing the stream the data or node is
+completely removed.
+unlink() is called; note that this call, in contrast to rm(1), removes entries
+regardless of their permissions. Instead, ownership or root privileges and
+write permissions in the directory are required and sufficient.
+
+
+Option: perm-early=value
+
+Type: MODET (mode_t)
+Option group: NAMED
+Phase: PREOPEN
+Platforms: all
+
+This option changes the mode (permissions) of an already existing filesystem
+entry with chown() before the file is opened or after the UNIX domain socket is
+bound, but before it listens/connects.
+
+
+Option: user-early=value
+Aliases: uid-e=value
+
+Type: UIDT (unsigned int or string)
+Option group: NAMED
+Phase: PREOPEN
+Platforms: all
+
+Takes one argument, a UNIX user name or a numeric user id. The first
+character of value is a digit for user ids.
+This option is applied via a chown() call before the file system entry is
+opened or after the UNIX domain socket is bound, but before it starts to
+listen/connect.
+If username is a name it must be a valid username from /etc/passwd and is
+converted to a user id with a getpwnam() call.
+On sane operating systems, the owner of the process must be root to change
+the owner of a file descriptor; root may even apply undefined (unnamed) user
+ids.
+
+
+Option: group-early=value
+Aliases: gid-e=value
+
+Type: GIDT (unsigned int or string)
+Option group: NAMED
+Phase: PREOPEN
+Platforms: all
+
+Takes one argument, a UNIX group name or a numeric group id. The first
+character of value is a digit for group ids.
+This option is applied via a chown() call before the file system entry is
+opened or after the UNIX domain socket is bound, but before it
+listens/connects.
+If groupname is a name it must be a valid groupname from /etc/group and is
+converted to a group id with a getgrnam() call.
+On most modern operating systems, the owner of the process must be member of
+the group being set; only root may set any group, even numbers without group
+name.
+
+
+Option: umask=value
+
+Type: MODET
+Option group: NAMED
+Phase: EARLY
+Platforms: all
+
+Sets the umask before opening a file or creating a UNIX domain socket. This is
+especially useful for these sockets, because there interface does not provide a
+mode argument.
+
+
+Option: unlink-close
+
+Type: BOOL
+Option group: NAMED
+Phase: LATE
+Platforms: all
+
+Remove the addresses file system entry when closing the address.
+For named pipes, listening unix domain sockets, and the symbolic links of pty
+addresses, the default is 1; for created files, opened files, generic opened
+files, and client unix domain sockets the default is 0.
+
+
+===============================================================================
+FORK and EXEC options
+
+Option: path=string
+
+Type: STRING
+Option group: EXEC
+Phase: PREEXEC
+Platforms: all
+
+Changes the PATH environment variable in the child process before the exec() or
+system() call.
+
+
+Option: nofork
+
+Type: BOOL
+Option group: FORK
+Phase: BIGEN
+Platforms: all
+
+Does not fork a subprocess for executing the program, instead calls execvp()
+directly from the actual socat instance. This avoids the overhead of another process
+between the program and the communication peer, but introduces lots of
+restrictions:
+ * this option can only be applied to the second socat() address.
+ * the first socat address cannot be OPENSSL or READLINE
+ * socat options -b, -t, -D, -l, -v, -x, -t become useless
+ * for both addresses, options ignoreeof, cr and crnl become useless
+ * for the second address (the one with option nofork), options
+ append, async, cloexec, flock, user, group, mode, nonblock,
+ perm-late, setlk, and setpgid cannot be applied, and should be used on the
+ first address instead.
+
+
+Option: pipes
+
+Type: BOOL
+Option group: FORK
+Phase: BIGEN
+Platforms: all
+
+For communication between the exec() or system() subprocess with socat, use two
+unnamed pipes instead of creating a socket pair.
+
+
+Option: pty
+
+Type: BOOL
+Option group: FORK
+Phase: BIGEN
+Platforms: all
+
+For communication between the exec() or system() subprocess with socat, use a
+pseudo terminal instead of a socket pair. The executed program gets the slave
+side, and socat the controlling side of the pseudo terminal.
+This is especially useful if you want to use, e.g., chat with socat (see
+EXAMPLES). Plus, ptys do not buffer I/O.
+Note: implementation of pseudo terminals are differing between platforms, so
+extra porting struggles might be required for porting this feature.
+
+
+Option: fdin=num
+
+Type: USHORT
+Option group: FORK
+Phase: PASTBIGEN
+Platforms: all
+
+After forking the child process, assign the stream where the child
+receives data from socat, to file descriptor num instead of stdin.
+
+
+Option: fdout=num
+
+Type: USHORT
+Option group: FORK
+Phase: PASTBIGEN
+Platforms: all
+
+After forking the child process, assign the stream where the child
+writes data to socat, to file descriptor num instead of stdout.
+
+
+Option: stderr
+
+Type: BOOL
+Option group: FORK
+Phase: PASTFORK
+Platforms: all
+
+Normally, the stderr filedescriptor of the forked program is a clone of socat's
+stderr fd. If this option is used, the programs stderr filedescriptor is a copy
+of the "normal" data output of the program, i.e. of its stdout or fdout.
+
+
+Option: setsid
+Aliases: sid
+
+Type: BOOL
+Option group: PROCESS
+Phase: LATE
+Platforms: all
+
+Invokes setsid() to make the forked off subprocess the leader of a new
+session. This also generates a new process group with this process as leader.
+This is useful, e.g., when exec'ing ssh to get the password prompt into the I/O
+channel (see EXAMPLES)
+
+
+Option: setpgid
+Aliases: pgid
+
+Type: INT
+Option group: FORK
+Phase: LATE
+Platforms: all
+
+Invokes setpgid(0, val) from the child process.
+
+
+Option: tiocsctty
+Aliases: ctty
+
+Type: BOOL
+Option group: TERMIOS
+Phase: LATE2
+Platforms: all
+
+Applies only in combination with the pty option or its variants. Tries to make
+the pty the controlling terminal. May require option setsid to work correctly.
+
+
+Option: dash
+Aliases: login
+
+Type: BOOL
+Option group: EXEC
+Phase: PREEXEC
+Platforms: all
+
+Prefixes argv[0] for the execvp() call with '-', thus making a shell behave as
+login shell.
+
+
+Option: sighup
+
+Type: CONST
+Option group: PARENT
+Phase: LATE
+Platforms: all
+
+ Has socat pass an eventual SIGHUP signal to the sub process.
+ If no address has this option, socat terminates on SIGHUP.
+
+
+Option: sigint
+
+Type: CONST
+Option group: PARENT
+Phase: LATE
+Platforms: all
+
+ Has socat pass an eventual SIGINT signal to the sub process.
+ If no address has this option, socat terminates on SIGINT.
+
+
+Option: sigquit
+
+Type: CONST
+Option group: PARENT
+Phase: LATE
+Platforms: all
+
+ Has socat pass an eventual SIGQUIT signal to the sub process.
+ If no address has this option, socat dumps core and terminates on SIGQUIT.
+
+
+===============================================================================
+PTY options
+These options may be used with addresses that create a pseudo terminal (pty).
+In particular, these are addresses EXEC, SYSTEM, and PTY.
+
+
+Option: openpty
+
+Type: BOOL
+Option group: PTY
+Phase: BIGEN
+Platforms: FreeBSD, Linux
+
+Like pty, but only use the openpty mechanism, not any other way for pty
+generation.
+
+
+Option: ptmx
+
+Type: BOOL
+Option group: PTY
+Phase: BIGEN
+Platforms: HP-UX, Linux, SunOS
+
+Like pty, but only use the /dev/ptmx (/dev/ptc on AIX) mechanism, not any other
+way for pty generation.
+
+
+Option: symbolic-link=filename
+
+Type: FILENAME
+Option group: PTY
+Phase: LATE
+Platforms: all
+
+Generates a symbolic link that points to the actual pseudo terminal (pty). This
+might help to solve the problem that ptys are generated with more or less
+unpredictable names, making it difficult to directly access the socat generated
+pty automatically. With this option, the user can specify a "fix" point in the
+file hierarchy that helps him to access the actual pty.
+
+
+Option: pty-wait-slave
+Aliases: wait-slave, waitslave
+
+Type: BOOL
+Option group: PTY
+Phase: EARLY
+Platforms: all
+
+ Blocks the open phase until a process opens the slave side of the pty.
+ Usually, socat continues after generating the pty with opening the next
+ address or with entering the transfer engine. With the wait-slave option,
+ socat waits until some process opens the slave side of the pty before
+ continuing.
+ This option only works if the operating system provides the tt(poll())
+ system call. And it depends on an undocumented behaviour of pty's, so it
+ does not work on all operating systems. It has successfully been tested on
+ Linux, FreeBSD, NetBSD, and on Tru64 with openpty.
+
+
+Option: pty-intervall
+
+Type: TIMESPEC
+Option group: PTY
+Phase: EARLY
+Platforms: all
+
+ When the wait-slave option is set, socat periodically checks the HUP
+ condition using poll() to find if the pty's slave side has been
+ opened. The default
+ polling intervall is 1s. Use the pty-intervall option to change this value.
+
+
+===============================================================================
+SOCKET options
+These are options that may be applied to all socket type addresses: UNIX
+(LOCAL) domain sockets (even with EXEC type addresses if not pipes), IP, and
+IPv6.
+
+
+Option: so-debug
+Aliases: debug
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Sets the SO_DEBUG socket option. Requires root.
+
+
+Option: so-acceptconn
+Aliases: acceptconn
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Tries to set the SO_ACCEPTCONN socket option. Read-only!
+
+
+Option: so-broadcast
+Aliases: broadcast
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Sets the SO_BROADCAST socket option.
+
+
+Option: so-reuseaddr
+Aliases: reuseaddr
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Sets the SO_REUSEADDR socket option. Allows to bind to a port even if this
+port is already used for a connection.
+
+
+Option: so-keepalive
+Aliases: keepalive
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: FD
+Platforms: all (UNIX98)
+
+Sets the SO_KEEPALIVE socket option.
+
+
+Option: so-linger=value
+Aliases: linger=value
+
+Type: LINGER
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Activates the SO_LINGER option and sets a value (seconds) for it.
+This lets shutdown() or close() block until data transfers have finished or the
+given value timed out.
+Note: on some systems, the type for setsockopt() is struct { int; int; }
+In this case, xioopen() sets {1,value}.
+
+
+Option: so-oobinline
+Aliases: oobinline
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Sets the SO_OOBINLINE socket option.
+
+
+Option: so-sndbuf=value
+Aliases: sndbuf=value
+
+Type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Sets the SO_SNDBUF option of the socket to the given value. This option is
+applied after the socket() (or socketpair()) call.
+NOTE: The kernel might change the effective value:
+My Linux 2.2 with TCP doubles the value, but uses at least 2048.
+
+
+Option: so-sndbuf-late=value
+Aliases: sndbuf-late=value
+
+Type: INT
+Option group: SOCKET
+Phase: LATE
+Platforms: all (UNIX98)
+
+Sets the SO_SNDBUF option of the socket to the given value. This option is
+applied after the connect() or accept() (or socketpair) call.
+NOTE: The kernel might change the effective value:
+My Linux 2.2 with TCP doubles the value, but uses at least 2048, and a
+maximum of 131070 (system limit?).
+
+
+Option: so-rcvbuf=value
+Aliases: rcvbuf=value
+
+Type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Sets the SO_RCVBUF option of the socket to the given value. This option is
+applied after the socket() call.
+NOTE: The kernel might change the effective value:
+My Linux 2.2 with TCP connect doubles the value, but uses at least 256 and
+at most 131070.
+My Linux 2.2 with TCP listen doubles the value but uses at least 11772.
+NOTE: For applying the SO_RCVBUF options after the connect() or accept() calls
+see rcvbuf-late.
+
+
+Option: so-rcvbuf-late=value
+Aliases: rcvbuf-late=value
+
+Type: INT
+Option group: SOCKET
+Phase: LATE
+Platforms: all (UNIX98)
+
+Sets the SO_RCVBUF option of the socket to the given value. This option is
+applied after the connect() or listen() call.
+NOTE: The kernel might change the effective value:
+My Linux 2.2 with TCP doubles the value, but uses at least 256 and maximal
+131070.
+NOTE: sequence of this call may be relevant for the effecting value (AIX
+4.3.3). For applying the SO_RCVBUF option immediately after the socket() call
+see rcvbuf.
+
+
+Option: so-error
+Aliases: error
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Tries to set the SO_ERROR socket option which is a read-only option.
+On my Linux 2.2 it gives "protocol not available".
+
+
+Option: so-type=value
+Aliases: type=value
+
+Type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all
+
+Set the sockettype argument of the socket() or socketpair() call. This
+overrides the per
+protocol default (e.g., TCP: SOCK_STREAM). Most values might
+not be supported by a given protocol.
+The following combinations are known to work at least under one OS:
+TCP SOCK_STREAM (system default)
+UDP SOCK_DGRAM (system default)
+IP SOCK_RAW (socat default)
+UNIX SOCK_STREAM (system default)
+UNIX SOCK_DGRAM
+
+
+Option: so-dontroute
+Aliases: dontroute
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Sets the SO_DONTROUTE socket option.
+
+
+Option: so-rcvlowat=value
+Aliases: rcvlowat=value
+
+Type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Sets the SO_RCVLOWAT socket option. Cannot be changed in Linux (always
+gives "protocol not available").
+
+
+Option: so-rcvtimeo=value
+Aliases: rcvtimeo=value
+
+Provided type: double
+Physical type: TIMEVAL (long[2])
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Sets the SO_RCVTIMOE socket option. Cannot be changed in Linux (always
+gives "protocol not available").
+
+
+Option: so-sndlowat=value
+Aliases: sndlowat=value
+
+Type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Sets the SO_SNDLOWAT socket option. Cannot be changed in Linux (always
+gives "protocol not available").
+
+
+Option: so-sndtimeo=value
+Aliases: sndtimeo=value
+
+Provided type: double
+Physical type: TIMEVAL (long[2])
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all (UNIX98)
+
+Sets the SO_SNDTIMEO socket option. Cannot be changed in Linux (always
+gives "protocol not available").
+
+
+Option: so-audit
+Aliases: audit
+
+Type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: none
+
+Sets the SO_AUDIT socket option.
+
+
+Option: so-attach-filter
+Aliases: attach-filter, attachfilter
+
+Type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: Linux
+
+Linux docu recommends to use libpcap for this feature.
+"protocol not available", need kernel CONFIG_FILTER!
+
+
+Option: so-detach-filter
+Aliases: detach-filter, detachfilter
+
+Type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: Linux
+
+See Linux "man 7 socket".
+"protocol not available", need kernel CONFIG_FILTER!
+
+
+Option: so-bindtodevice=string
+Aliases: bindtodevice, interface, if
+
+Type: NAME
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: Linux
+
+Binds the socket to a net interface, e.g. lo0 or eth0 (interface names depend
+on operating system). Might require root privilege.
+
+
+Option: so-bsdcompat
+Aliases: bsdcompat
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: none
+
+Sets the SO_BSDCOMPAT socket option. See Linux "man 7 socket".
+
+
+Option: so-cksumrecv
+Aliases: cksumrecv
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: none
+
+Sets the SO_CKSUMRECV socket option.
+
+
+Option: so-kernaccept
+Aliases: kernaccept
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: none
+
+Sets the SO_KERNACCEPT socket option.
+
+
+Option: so-no-check
+Aliases: no-check, nocheck
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the SO_NO_CHECK socket option." Intentionally undocumented" under
+Linux (see "man 7 socket"), don't know what it does....
+
+
+Option: so-noreuseaddr
+Aliases: noreuseaddr
+
+Type: INT?
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: none
+
+Sets the SO_NOREUSEADDR socket option.
+
+
+Option: passcred
+Aliases: so-passcred
+
+Type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the SO_PASSCRED option of a socket.
+
+
+Option: so-peercred
+Aliases: peercred
+
+Type: INT3 or int[3]?
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: Linux
+
+Enables receiving of credentials. Read only.
+Not really implemented yet.
+Nevertheless, Gives "Protocol not available".
+
+
+Option: so-priority=value
+Aliases: priority=value
+
+Type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the protocol defined priority for all packets to be sent on this socket.
+Docu says it requires root privileges. Normal user may set 0..6 for UNIX domain
+and TCP client sockets on Linux 2.2. root may send any int value.
+
+
+Option: so-reuseport
+Aliases: reuseport
+
+Type: INT?
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: FreeBSD, HP-UX
+
+Sets the SO_REUSEPORT socket option.
+
+
+Option: so-security-authentication
+Aliases: security-authentication, securityauthentication
+
+Type: INT?
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the SO_SECURITY_AUTHENTICATION socket option. Gives "protocol not
+available" error.
+In Linux 2.2.16 source, only exists in asm-*/socket.h
+
+
+Option: so-security-encryption-network
+Aliases: security-encryption-network, securityencryptionnetwork
+
+Type: INT?
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the SO_SECURITY_ENCRYPTION_NETWORK option of the socket. Gives "protocol
+not available" error.
+In Linux 2.2.16 source, only exists in asm-*/socket.h
+
+
+Option: so-security-encryption-transport
+Aliases: security-encryption-transport, securityencryptiontransport
+
+Type: INT?
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the SO_SECURITY_ENCRYPTION_TRANSPORT option of the socket. Gives "protocol
+not available" error.
+In Linux 2.2.16 source, only exists in asm-*/socket.h
+
+
+Option: so-use-ifbufs
+Aliases: use-ifbufs, useifbufs
+
+Type: INT?
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: none
+
+Sets the SO_USE_IFBUFS socket option.
+
+
+Option: so-useloopback
+Aliases: useloopback
+
+Type: INT?
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: FreeBSD, HP-UX, SunOS
+
+Sets the SO_USELOOPBACK socket option.
+
+
+Option: so-dgram-errind
+Aliases: dgram-errind, dgramerrind
+
+Logical type: bool?
+Physical type: INT?
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: SunOS
+
+Sets the SO_DGRAM_ERRIND flag.
+
+
+Option: so-dontlinger
+Aliases: dontlinger
+
+Type: INT?
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: SunOS
+
+Sets the SO_DONTLINGER socket option.
+
+
+Option: so-prototype
+Aliases: prototype
+
+Type: INT?
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: HP-UX, SunOS
+
+Sets the SO_PROTOTYPE socket option.
+
+
+Option: type
+
+Type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all
+
+Sets the type of the socket, usually as argument to the socket() or
+socketpair() call, to <type>. Under Linux, 1 means stream oriented socket, 2
+means datagram socket, and 3 means raw socket.
+
+
+Option: protocol-family
+Aliases: pf
+
+Type: STRING
+Option group: SOCKET
+Phase: PRESOCKET
+Platforms: all
+
+Forces the use of the specified IP version. <string> can be something like
+"ip4" or "ip6".
+
+
+Option: fiosetown
+
+Logical type: bool
+Physical type: INT
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: FreeBSD, Linux
+
+Sets the FIOSETOWN ioctl (in "man 7 socket" called FIOCSETOWN).
+
+
+#Option: ciocspgrp
+#
+#Allowed in addresses: SOCKET
+#Logical type: bool
+#Physical type: int
+#
+#Sets the CIOCSPGRP ioctl.
+
+
+#Option: addr=value
+#
+#Allowed in addresses: SOCKET
+#Type: socket-address
+#
+#For client socket, sets the local (bind) address. Not yet implemented.
+
+
+Option: bind=socketaddress
+
+Type: STRING
+Option group: SOCKET
+Phase: BIND
+Platforms: all
+
+Gives the address to be used in the bind(2) system call. The format of the
+socketaddress depends on the socket type (see below). For "client" sockets this
+option inserts a bind(2) call between socket(2) and connect(2) calls. For
+"server" sockets this option is ignored! For datagram sockets behaviour of this
+option is currently unspecified.
+Note: for client sockets in the UNIX domain this option is not useful: with the
+same address as connect it will conflict with the bind call of the server
+socket; another address for bind is ignored (with Linux 2.2).
+For TCP sockets these formats are currently implemented:
+HOSTNAME
+HOSTNAME:PORT
+IPADDR
+IPADDR:PORT
+:PORT
+.PORT
+
+
+Option: connect-timeout=seconds
+
+Type: TIMEVAL
+Option group: SOCKET
+Phase: PASTSOCKET
+Platforms: all
+
+Abort the connection attempt after the given time with error status.
+
+#
+Option: backlog=value
+
+Type: INT
+Option group: LISTEN
+Phase: LISTEN
+Platforms: all
+
+Sets the value to be used with the listen(2) system call. The default is 5.
+It does not seem to work for Linux 2.2; Linux seems to allow much more
+established connections, but then they stay even after server process
+shutdown...
+
+
+Option: range=address:mask, range=address/bits
+
+Type: STRING
+Option group: RANGE
+Phase: ACCEPT
+Platforms: all
+Implementation status: only for INET (IP4) addresses
+
+Defines a subnet where clients may connect from. If other clients connect the
+accepted connection is shut down immediately after examination of the client
+address. If this option is not used, the default is 0.0.0.0:0.0.0.0, allowing
+arbitrary client addresses. bits is the number of high order bits that must
+match between the range value and the clients address.
+
+
+Option: tcpwrap, tcpwrap=name
+
+Type: STRING_NULL
+Option group: RANGE
+Phase: ACCEPT
+Platforms: (depends on libwrap installation)
+
+Uses the rules introduced by Wietse Venema's libwrap (tcpd) library to check
+if the client is allowed to connect. The configuration files are
+/etc/hosts.allow and /etc/hosts.deny. See "man 5 hosts_access" for
+more information. <name> is passed to the wrapper functions as daemon
+process name. If omitted, the basename of socats invokation (argv[0]) is
+passed.
+If both tcpwrap and and range options are applied to an address, both
+conditions must be fulfilled to allow the connection.
+
+
+Option: hosts-allow, tcpwrap-hosts-allow-table
+
+Type: FILENAME
+Option group: RANGE
+Phase: ACCEPT
+Platforms: (depends on libwrap installation)
+
+Takes the specified file instead of /etc/hosts.allow.
+
+
+Option: hosts-deny, tcpwrap-hosts-deny-table
+
+Type: FILENAME
+Option group: RANGE
+Phase: ACCEPT
+Platforms: (depends on libwrap installation)
+
+Takes the specified file instead of /etc/hosts.deny.
+
+
+Option: tcpwrap-etc, tcpwrap-dir
+
+Type: FILENAME
+Option group: RANGE
+Phase: ACCEPT
+Platforms: (depends on libwrap installation)
+
+ Looks for hosts.allow and hosts.deny in the specified directory. Is
+ overriden by options hosts-allow and hosts-deny.
+
+
+-------------------------------------------------------------------------------
+IP options
+
+
+Option: ip-options=values
+Aliases: ipoptions
+
+Type: BIN
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: all
+
+Sets the IP_OPTIONS values of the IP socket. For example, to send packets to
+destination D.D.D.D via a router G.G.G.G you have to specify G.G.G.G as the
+"normal" destination, and D.D.D.D in the source route:
+TCP:G.G.G.G:25,ip-options=x890704dddddddd
+Note that the destination will see G.G.G.G as sender of the packets, and
+therefore might not return the answers correctly.
+See RFC791 for detailed specification of IP option fields.
+Examples:
+x01 ... nop
+x8307040a000001 ... loose source route
+x890b040a000001c0c1c2c3 ... strict source route
+Note: with source routes, you should not specifiy destination address and
+hops as defined in RFC791 (first hop as IP header destination address,
+further hops and final destination in source route) because the (Linux?) kernel changes
+them to a more intuitive form (final destination as destination in IP header,
+gateways in source route). So, in destination address give the final
+destination, and in the source route the gateways!
+Note: this option may be mulitply applied per socket but the (Linux?) kernel
+pads each setting with 0' to align the options end to 4 octets. So you should
+better pad the options data with nops (01) yourself.
+
+
+Option: ip-pktinfo
+Aliases: ippktinfo, pktinfo
+
+Type: INT (should be struct in_pktinfo)
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: Linux
+Status: Not completely implemented (ancillary messages are not supported by
+socat/xio)
+
+Pass an IP_PKTINFO ancillary message.
+
+
+Option: ip-recvtos
+Aliases: iprecvtos, recvtos
+
+Logical type: bool
+Physical type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: Linux
+Status: Not completely implemented (ancillary messages are not supported by
+socat/xio)
+
+Set the IP_RECVTOS socket option which enables IP_TOS ancillary message
+passing.
+
+
+Option: ip-recvttl
+Aliases: iprecvttl, recvttl
+
+Logical type: bool
+Physical type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: all
+Implementation status: No results.
+
+Set the IP_RECVTTL socket option.
+
+
+Option: ip-recvopts
+Aliases: iprecvopts, recvopts
+
+Logical type: bool
+Physical type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: all
+Implementation status: No results.
+
+Set the IP_RECVOPTS socket option.
+
+
+Option: ip-retopts
+Aliases: ipretopts, retopts
+
+Logical type: bool
+Physical type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: all
+Implementation status: No results.
+
+Set the IP_RETOPTS socket option.
+
+
+Option: ip-tos=value
+Aliases: iptos=value, tos=value
+
+Logical type: byte
+Physical type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: all
+
+Sets the TOS (type of service) flags for the outgoing IP headers of the
+socket. My Linux 2.2 does not allow to set values other than 0 (probably
+needs some optional kernel features).
+
+
+Option: ip-ttl=value
+Aliases: ipttl=value, ttl=value
+
+Logical type: byte
+Physical type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: all
+
+Sets the TTL (time to live) field for the outgoing IP headers of the socket.
+0 does not seem to be useful and gives "invalid argument" error in Linux.
+This option can be used to implement a "poor mans traceroute" in conjunction
+with tcpdump.
+
+
+Option: ip-hdrincl
+Aliases: iphdrincl, hdrincl
+
+Logical type: bool
+Physical type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: all
+
+Set the IP_HDRINCL socket option. User will supply IP header before user
+data. For raw IP sockets only. Not tested.
+
+
+Option: ip-recverr
+Aliases: iprecverr, recverr
+
+Type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Set the IP_RECVERR socket option.
+Implementation status: No results.
+
+
+Option: ip-mtu-discover=value
+Aliases: ipmtudiscover=value, mtudiscover=value
+
+Type: INT (0..2)
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the IP_MTU_DISCOVER flag of the IP socket. In Linux there are three values
+defined: 0..dont(never), 1..want(per route), 2..do(always)
+
+
+Option: ip-mtu
+Aliases: ipmtu, mtu
+
+Type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: none
+
+Sets the MTU (maximal transfer unit) of the socket. In Linux this is a
+read-only parameter and results in a "protocol not available" error.
+
+
+Option: ip-freebind
+Aliases: ipfreebind, freebind
+
+Logical type: bool
+Physical type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: none
+
+Allows the socket to locally bind to any address, even those that are
+not covered by an interface address, alias address or a local subnet. Even
+broadcast and multicast addresses are possible.
+Note: this option has been found on Linux 2.4 in <linux/in.h>. This file might
+not be included per default, because it creates errors.
+To make this option available, "make" socat with the CCOPT environment
+variable set to "-DIP_FREEBIND=15"
+
+
+Option: ip-router-alert=value
+Aliases: iprouteralert, routeralert
+
+Type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the IP_ROUTER_ALERT socket option. Only works with raw sockets.
+"Invalid argument"
+
+
+Option: ip-add-membership=multicast-address:interface-address
+ ip-add-membership=multicast-address:interface-name
+ ip-add-membership=multicast-address:interface-index
+ ip-add-membership=multicast-address:interface-address:interface-name
+ ip-add-membership=multicast-address:interface-address:interface-index
+Aliases: add-membership
+ ip-membership
+
+Type: IP_MREQN
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: all
+
+ Makes the socket member of the specified multicast group. This is currently
+ only implemented for IPv4. The option takes the IP address of the multicast
+ group and info about the desired network interface. The most common syntax
+ is the first one, while the others are only available on systems that
+ provide tt(struct mreqn) (Linux).nl()
+ The indices of active network interfaces can be shown using the utility
+ procan().
+
+
+Option: ip-drop-membership
+
+Not implemented.
+
+
+#! Option: ipv6-join-group
+
+
+Option: ip-multicast-ttl=byte
+Aliases: ipmulticastttl, multicastttl
+
+Type: BYTE
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: all
+
+ Sets the TTL used for outgoing multicast traffic. Default is 1.
+
+
+Option: ip-multicast-loop
+Aliases: ipmulticastloop, multicastloop
+
+Logical type: bool
+Physical type: INT
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: all
+
+ Specifies if outgoing multicast traffic should loop back to the interface.
+
+
+Option: ip-multicast-if=hostname
+Aliases: multicast-if
+
+Type: IP4NAME
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: all
+
+ Specifies hostname or address of the network interface to be used for
+ multicast traffic.
+
+
+Option: ip-pktoptions
+Aliases: ippktoptions, pktoptions, pktopts
+
+Type: INT?
+Option group: SOCK_IP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Set the IP_PKTOPTIONS socket option. No docu found.
+Implementation status: "Protocol not available".
+
+
+Option: res-debug
+
+Type: BOOL
+Option group: SOCK_IP
+Phase: INIT
+Platforms: all
+
+Apply the debug resolver option to all queries of this XIO address.
+
+
+Option: res-aaonly
+Aliases: aaonly
+
+Type: BOOL
+Option group: SOCK_IP
+Phase: INIT
+Platforms: all
+
+Apply the aaonly resolver option to all queries of this XIO address.
+
+
+Option: res-usevc
+Aliases: usevc
+
+Type: BOOL
+Option group: SOCK_IP
+Phase: INIT
+Platforms: all
+
+Apply the usevc resolver option to all queries of this XIO address.
+
+
+Option: res-primary
+Aliases: primary
+
+Type: BOOL
+Option group: SOCK_IP
+Phase: INIT
+Platforms: all
+
+Apply the primary resolver option to all queries of this XIO address.
+
+
+Option: res-igntc
+Aliases: igntc
+
+Type: BOOL
+Option group: SOCK_IP
+Phase: INIT
+Platforms: all
+
+Apply the igntc resolver option to all queries of this XIO address.
+
+
+Option: res-recurse
+Aliases: recurse
+
+Type: BOOL
+Option group: SOCK_IP
+Phase: INIT
+Platforms: all
+
+Apply the recurse resolver option to all queries of this XIO address.
+
+
+Option: res-defnames
+Aliases: defnames
+
+Type: BOOL
+Option group: SOCK_IP
+Phase: INIT
+Platforms: all
+
+Apply the defnames resolver option to all queries of this XIO address.
+
+
+Option: res-stayopen
+Aliases: stayopen
+
+Type: BOOL
+Option group: SOCK_IP
+Phase: INIT
+Platforms: all
+
+Apply the stayopen resolver option to all queries of this XIO address.
+
+
+Option: res-dnsrch
+Aliases: dnsrch
+
+Type: BOOL
+Option group: SOCK_IP
+Phase: INIT
+Platforms: all
+
+Apply the dnsrch resolver option to all queries of this XIO address.
+
+
+-------------------------------------------------------------------------------
+IP6 options
+
+
+Option: ipv6-v6only=value
+Alias: ipv6only, v6only
+
+Type: BOOL
+Option group: SOCK_IP6
+Phase: PASTSOCKET
+Platforms: FreeBSD, Linux
+
+Apply the IPV6_V6ONLY socket option to the file descriptor. This controls if
+the socket listens only on the IPv6 protocol or also on IPv4.
+
+
+-------------------------------------------------------------------------------
+IPAPP (TCP and UDP) options
+
+
+Option: sourceport=value
+Alias: sp=value
+
+Type: 2BYTE
+Option group: IPAPP (IP_TCP and IP_UDP)
+Phase: LATE
+Platforms: all
+
+For outgoing (client) TCP and UDP connections, it sets the source port (local port, client side port) of
+the socket connection. For server type addresses, requires the client to use
+this sourceport, otherwise socat immediately shuts down the connection.
+On UNIX class operating systems root privilege are required to set a source
+port between 1 and 1023 incl. 0 gives a "random" port number >= 1024, which is
+the default.
+
+
+Option: lowport
+
+Type: BOOL
+Option group: IPAPP (IP_TCP and IP_UDP)
+Phase: LATE
+Platforms: all
+
+For outgoing (client) TCP and UDP connections, it sets the source
+to an unused random port between 640 and 1023 incl. On UN*X type operating
+systems, this requires root privilege, and thus guaranties the peer to be
+root authorized.
+With TCP or UDP listen addresses, socat immediately shuts down the
+connection if the client does not use a sourceport <= 1023.
+This mechanism can provide limited authorization under some circumstances.
+
+-------------------------------------------------------------------------------
+TCP options
+
+
+Option: tcp-nodelay
+Aliases: nodelay
+
+Logical type: bool
+Physical type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: all
+
+Sets the TCP_NODELAY flag of the TCP socket. This turns off Nagles algorithm.
+
+
+Option: tcp-maxseg
+Aliases: maxseg, mss
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: all
+
+Limits the MAXSEG (MSS) value of the TCP socket. This option is applied before
+the connect or listen call, so it is transferred in the SYN packet to the peer
+socket.
+Linux client: 0 gives "invalid argument", higher values are used in SYN
+negotiation, but effective MSS is n-12, at least 8.
+On AIX, this is a read-only option.
+
+
+Option: tcp-maxseg-late
+Aliases: maxseg-late, mss-late
+
+Type: INT
+Option group: IP_TCP
+Phase: CONNECTED
+Platforms: all
+
+Limits the MAXSEG (MSS) value of the TCP socket. This option is applied past
+the connect or accept call, so it is not transferred as MSS to the peer socket.
+Observation with Linux 2.2: does not influence the size of packets generated
+by the local socket.
+
+
+Option: tcp-cork
+Aliases: cork
+
+Logical type: bool
+Physical type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the TCP_CORK option.
+
+
+Option: tcp-stdurg
+Aliases: stdurg
+
+Logical type: bool
+Physical type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: none
+
+Applies the TCP_STDURG option with setsockopt. This enables RFC 1122 compliant
+urgent point handling.
+
+
+Option: tcp-rfc1323
+Aliases: rfc1323
+
+Logical type: bool
+Physical type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: none
+
+Applies the TCP_RFC1323 option with setsockopt. This enables RFC1323 TCP
+enhancements (window scale, timestamp).
+
+
+Option: tcp-keepidle
+Aliases: keepidle
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the TCP_KEEPIDLE value of the socket with setsockopt(). Starts keepalive
+after this period (in seconds?)
+
+
+Option: tcp-keepintvl
+Aliases: keepintvl
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the TCP_KEEPINTVL value of the socket with setsockopt(). Intervall between
+keepalives (in seconds?)
+
+
+Option: tcp-keepcnt
+Aliases: keepcnt
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the TCP_KEEPCNT value of the socket with setsockopt(). Number of
+keepalives before death.
+
+
+Option: tcp-syncnt
+Aliases: syncnt
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the TCP_SYNCNT value of the socket with setsockopt(). Number of SYN
+retransmits.
+
+
+Option: tcp-linger2
+Aliases: linger2
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the TCP_LINGER2 value of the socket with setsockopt(). Life time of
+orphaned FIN-WAIT-2 state.
+
+
+Option: tcp-defer-accept
+Aliases: defer-accept
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the TCP_DEFER_ACCEPT value of the socket with setsockopt(). accept() of
+the listener will only return when data arrived at the new connection. The
+value is converted to seconds by some algorithm.
+
+
+Option: tcp-window-clamp
+Aliases: window-clamp
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the TCP_WINDOW_CLAMP value of the socket with setsockopt(). "Bound advertised
+window".
+
+
+Option: tcp-info
+Aliases: info
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: FreeBSD, Linux
+
+Sets the TCP_INFO value of the socket with setsockopt(). Is a read only option,
+so it always generates an error.
+
+
+Option: tcp-quickack
+Aliases: quickack
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: Linux
+
+Sets the TCP_QUICKACK option with setsockopt().
+
+
+Option: tcp-md5sig
+Aliases: md5sig
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: none
+
+Enables generation of MD5 digests on the packets.
+
+
+Option: tcp-noopt
+Aliases: noopt
+
+Type: INT
+Option: group: IP_TCP
+Phase: PASTSOCKET
+Platforms: FreeBSD
+
+Disables use of TCP options.
+
+
+Option: tcp-nopush
+Aliases: nopush
+
+Type: INT
+Option: group: IP_TCP
+Phase: PASTSOCKET
+Platforms: FreeBSD
+
+Sets the TCP_NOPUSH option.
+
+
+Option: tcp-sack-disable
+Aliases: sack-disable
+
+Type: INT
+Option: group: IP_TCP
+Phase: PASTSOCKET
+Platforms: none
+
+Disables use the selective acknowledge feature.
+
+
+Option: tcp-signature-enable
+Aliases: signature-enable
+
+Type: INT
+Option: group: IP_TCP
+Phase: PASTSOCKET
+Platforms: none
+
+Enables generation of MD5 digests on the packets.
+
+
+Option: tcp-abort-threshold
+Aliases: abort-threshold
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: HP-UX, SunOS
+
+Sets the time to wait for an answer of the peer on an established connection.
+
+
+Option: tcp-conn-abort-threshold
+Aliases: conn-abort-threshold
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: HP-UX, SunOS
+
+Sets the time to wait for an answer of the server during the initial connect.
+
+
+Option: tcp-keepinit
+Aliases: keepinit
+
+Type: INT
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: none
+
+Sets the time to wait for an answer of the server during connect() before
+giving up. Value in half seconds, default is 150 (75s).
+
+
+Option: tcp-paws
+Aliases: paws
+
+Type: BOOL
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: none
+
+Enables the "protect against wrapped sequence numbers" feature.
+
+
+Option: tcp-sackena
+Aliases: sackena
+
+Type: BOOL
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: none
+
+Enables selective acknowledge.
+
+
+Option: tcp-tsoptena
+Aliases: tsoptena
+
+Type: BOOL
+Option group: IP_TCP
+Phase: PASTSOCKET
+Platforms: none
+
+Enables the time stamp option that allows RTT recalculation on existing
+connections.
+
+
+===============================================================================
+SOCKS options
+
+
+Option: socksport
+
+Type: STRING
+Option group: IP_SOCKS4
+Phase: LATE
+Platforms: all
+
+Overrides the default socks server port 1080
+
+
+Option: socksuser
+
+Type: NAME
+Option group: IP_SOCKS4
+Phase: LATE
+Platforms: all
+
+Overrides the system derived socks user name ($USER or $LOGNAME or "anonymous")
+
+
+===============================================================================
+HTTP options
+
+
+Option: proxyport
+
+Type: STRING
+Option group: HTTP
+Phase: LATE
+Platforms: all
+
+Overrides the default HTTP proxy port 8080.
+
+
+Option: ignorecr
+
+Type: BOOL
+Option group: HTTP
+Phase: LATE
+Platforms: all
+
+The HTTP protocol requires the use of CR+NL as line terminator. When a proxy
+server violates this standard, socat might not understand its answer.
+This option directs socat to interprete NL as line terminator and
+to ignore CR in the answer. Nevertheless, socat sends CR+NL to the proxy.
+
+
+Option: proxyauth
+
+Type: STRING
+Option group: HTTP
+Phase: LATE
+Platforms: all
+
+Provide "basic" authentication to the proxy server. The argument to the option
+must be the username followed by ':' followed by the password. This string is
+used with a "Proxy-Authorize: Base" header in base64 encoded form.
+
+
+Option: resolve
+
+Type: BOOL
+Option group: HTTP
+Phase: LATE
+Platforms: all
+
+Per default, socat sends to the proxy a CONNECT request containing the target
+hostname. With this option, socat resolves the hostname locally and sends the
+IP address.
+
+
+===============================================================================
+TERMIOS options
+
+These options are applied with tcsetattr calls with a struct termios.
+Attention: Applying these options to stdin/stdout when they refer to your
+terminal might directly effect your terminal!
+See Linux:"man 3 termios" and Linux:"man 2 stty"
+
+-------------------------------------------------------------------------------
+TERMIOS combined modes
+
+
+Option: raw
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Is equivalent to
+ignbrk=0,brkint=0,ignpar=0,parmrk=0,inpck=0,istrip=0,inlcr=0,igncr=0,icrnl=0,ixon=0,ixoff=0,iuclc=0,ixany=0,imaxbel=0,opost=0,isig=0,icanon=0,xcase=0,vmin=1,vtime=0
+
+
+Option: sane
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Is equivalent to
+cread,ignbrk=0,brkint,inlcr=0,igncr=0,icrnl,ixoff=0,iuclc=0,-ixany=0,imaxbel,opost,olcuc=0,ocrnl=0,onlcr,onocr=0,onlret=0,ofill=0,ofdel=0,nl0,cr0,tab0,bs0,vt0,ff0,isig,icanon,iexten,echo,echoe,echok,echonl=0,noflsh=0,xcase=0,tostop=0,echoprt=0,echoctl,echoke
+
+-------------------------------------------------------------------------------
+TERMIOS input mode flags
+
+
+Option: ignbrk
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the IGNBRK flag of the terminal driver.
+
+
+Option: brkint
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the BRKINT flag of the terminal driver.
+
+
+Option: ignpar
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the IGNPAR flag of the terminal driver.
+
+
+Option: parmrk
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the PARMRK flag of the terminal driver.
+
+
+Option: inpck
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the INPCK flag of the terminal driver. Enables input parity checking.
+
+
+Option: istrip
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ISTRIP flag of the terminal driver. Strips off the eighth bit.
+
+
+Option: inlcr
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the INLCR flag of the terminal driver. Translates NL to CR on input.
+
+
+Option: igncr
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the IGNCR flag of the terminal driver. Ignores CR character on input.
+
+
+Option: icrnl
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ICRNL flag of the terminal driver. Translates CR to NL on input. This
+option is ignored when IGNCR is set.
+
+
+Option: iuclc
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the IUCLC flag of the terminal driver. Changes characters in input from
+uppercase to lowercase.
+
+
+Option: ixon
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the IXON flag of the terminal driver. Enables XON/XOFF flow control on
+output (?).
+
+
+Option: ixany
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the IXANY flag of the terminal driver. Enables any character to restart
+output.
+
+
+Option: ixoff
+Aliases: tandem
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the IXOFF flag of the terminal driver. Enables XON/XOFF flow control on
+input.
+
+
+Option: imaxbel
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the IMAXBEL flag of the terminal driver. Rings the bell when the input
+queue is full.
+
+-------------------------------------------------------------------------------
+TERMIOS output mode flags
+
+
+Option: opost
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the OPOST flag of the terminal driver.
+
+
+Option: olcuc
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the OLCUC flag of the terminal driver.
+
+
+Option: onlcr
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ONLCR flag of the terminal driver.
+
+
+Option: ocrnl
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the OCRNL flag of the terminal driver.
+
+
+Option: onocr
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ONOCR flag of the terminal driver.
+
+
+Option: onlret
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ONLRET flag of the terminal driver.
+
+
+Option: ofill
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the OFILL flag of the terminal driver.
+
+
+Option: ofdel
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the OFDEL flag of the terminal driver.
+
+
+Option: nldly
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the NLDLY flag of the terminal driver. 0 sets the value to NL0, and 1 to
+NL1. See nl0, nl1.
+
+
+Option: nl0
+
+Type: CONST (const bool, always sets 0)
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the field NLDLY to the value NL0.
+
+
+Option: nl1
+
+Type: CONST (const bool, always sets 1)
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the field NLDLY to the value NL1.
+
+
+Option: crdly=value
+
+Type: UINT (0..3)
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the field CRDLY to the given value.
+See cr0, cr1, cr2, cr3.
+
+
+Option: cr0
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the CRDLY field to the value CR0.
+See crdly.
+
+
+Option: cr1
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the CRDLY field to the value CR1.
+See crdly.
+
+
+Option: cr2
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the CRDLY field to the value CR2.
+See crdly.
+
+
+Option: cr3
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the CRDLY field to the value CR3.
+See crdly.
+
+
+Option: tab0
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the horizontal tab delay mask to TAB0.
+See tabdly.
+
+
+Option: tab1
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the horizontal tab delay mask to TAB1.
+See tabdly.
+
+
+Option: tab2
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the horizontal tab delay mask to TAB2.
+See tabdly.
+
+
+Option: tab3
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the horizontal tab delay mask to TAB3.
+See tabdly.
+
+
+Option: tabdly=value
+
+Type: UINT (0..3)
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the field TABDLY to the given value.
+See tab0, tab1, tab2, and tab3.
+
+
+Option: xtabs
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the horizontal tab delay mask to XTABS.
+
+
+Option: bs0
+
+Type: CONST (0)
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the field BSDLY to the value BS0
+
+
+Option: bs1
+
+Type: CONST (1)
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the field BSDLY to the value BS1
+
+
+Option: bsdly
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the BSDLY flag of the terminal driver. 0 sets the value to BS0, and 1 to
+BS1. See bs0, bs1.
+
+
+Option: vt0
+
+Type: CONST (0)
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the field VTDLY to the value VT0
+
+
+Option: vt1
+
+Type: CONST (1)
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the field VTDLY to the value VT1
+
+
+Option: vtdly
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the VTDLY flag of the terminal driver. 0 sets the value to VT0, and 1 to
+VT1. See vt0, vt1.
+
+
+Option: ff0
+
+Type: CONST (0)
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the field FFDLY to the value FF0
+See ffdly.
+
+
+Option: ff1
+
+Type: CONST (1)
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the field FFDLY to the value FF1
+See ffdly.
+
+
+Option: ffdly
+
+Type: BOOL (0..1)
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the FFDLY flag of the terminal driver. 0 sets the value to FF0, and 1 to
+FF1. See ff0, ff1.
+
+
+
+-------------------------------------------------------------------------------
+TERMIOS control mode flags
+
+
+Option: cs5
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the field CSIZE to the value CS5
+
+
+Option: cs6
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the field CSIZE to the value CS6
+
+
+Option: cs7
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the field CSIZE to the value CS7
+
+
+Option: cs8
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the field CSIZE to the value CS8
+
+
+Option: csize
+
+Type: UINT (0..3)
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the field CSIZE. 0..CS5, 1..CS6, 2..CS7, 3..CS8
+
+
+Option: cstopb
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the flag CSTOPB.
+
+
+Option: cread
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the value of the CREAD flag.
+
+
+Option: parenb
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the PARENB flag of the terminal driver.
+
+
+Option: parodd
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the PARODD flag of the terminal driver.
+
+
+Option: hupcl
+Aliases: hup
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the HUPCL flag of the terminal driver.
+
+
+Option: clocal
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the CLOCAL flag of the terminal driver.
+
+
+Option: crtscts
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: FreeBSD, Linux, SunOS
+
+Sets the CRTSCTS flag of the terminal driver.
+
+
+Option: b0 (HP-UX, Linux, SunOS)
+Option: b50 (HP-UX, Linux, SunOS)
+Option: b75 (HP-UX, Linux, SunOS)
+Option: b110 (HP-UX, Linux, SunOS)
+Option: b134 (HP-UX, Linux, SunOS)
+Option: b150 (HP-UX, Linux, SunOS)
+Option: b200 (HP-UX, Linux, SunOS)
+Option: b300 (HP-UX, Linux, SunOS)
+Option: b600 (HP-UX, Linux, SunOS)
+Option: b900 (HP-UX)
+Option: b1200 (HP-UX, Linux, SunOS)
+Option: b1800 (HP-UX, Linux, SunOS)
+Option: b2400 (HP-UX, Linux, SunOS)
+Option: b3600 (HP-UX)
+Option: b4800 (HP-UX, Linux, SunOS)
+Option: b7200 (HP-UX)
+Option: b9600 (HP-UX, Linux, SunOS)
+Option: b19200 (HP-UX, Linux, SunOS)
+Option: b38400 (HP-UX, Linux, SunOS)
+Option: b57600 (HP-UX, Linux, SunOS)
+Option: b115200 (HP-UX, Linux, SunOS)
+Option: b230400 (HP-UX, Linux, SunOS)
+Option: b460800 (HP-UX, Linux, SunOS)
+Option: b500000 (Linux)
+Option: b576000 (Linux)
+Option: b921600 (Linux)
+Option: b1000000 (Linux)
+Option: b1152000 (Linux)
+Option: b1500000 (Linux)
+Option: b2000000 (Linux)
+Option: b2500000 (Linux)
+Option: b3000000 (Linux)
+Option: b3500000 (Linux)
+Option: b4000000 (Linux)
+
+Type: CONST
+Option group: TERMIOS
+Phase: FD
+
+Sets the baud rate to the implied value. b0 "hangs up" the connection.
+
+
+Option: ispeed
+
+Type: UINT
+Option group: TERMIOS
+Phase: FD
+Platforms: FreeBSD, Linux
+
+Sets the input baud rate to the specified value. This works on systems where
+struct termios has a special c_ispeed field.
+
+
+Option: ospeed
+
+Type: UINT
+Option group: TERMIOS
+Phase: FD
+Platforms: FreeBSD, Linux
+
+Sets the input baud rate to the specified value. This works on systems where
+struct termios has a special c_ospeed field.
+
+
+
+
+-------------------------------------------------------------------------------
+TERMIOS local mode flags
+
+
+Option: isig
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ISIG flag of the terminal driver.
+
+
+Option: icanon
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ICANON flag of the terminal driver.
+
+
+Option: xcase
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: HP-UX, Linux, SunOS
+
+Sets the XCASE flag of the terminal driver.
+
+
+Option: echo
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ECHO flag of the terminal driver.
+
+
+Option: echoe
+Aliases: crterase
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ECHOE flag of the terminal driver.
+
+
+Option: echok
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ECHOK flag of the terminal driver.
+
+
+Option: echonl
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ECHONL flag of the terminal driver.
+
+
+Option: echoctl
+Aliases: ctlecho
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ECHOCTL flag of the terminal driver.
+
+
+Option: echoprt
+Aliases: prterase
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ECHOPRT flag of the terminal driver.
+
+
+Option: echoke
+Aliases: crtkill
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the ECHOKE flag of the terminal driver.
+
+
+Option: flusho
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the FLUSHO flag of the terminal driver.
+
+
+Option: noflsh
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the NOFLSH flag of the terminal driver.
+
+
+Option: tostop
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the TOSTOP flag of the terminal driver.
+
+
+Option: pendin
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the PENDIN flag of the terminal driver.
+
+
+Option: iexten
+
+Type: BOOL
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+
+Sets the IEXTEN flag of the terminal driver.
+
+
+-------------------------------------------------------------------------------
+TERMIOS options for functional characters
+
+Option: vintr=value
+Aliases: intr=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: tested
+
+Sets the value for the VINTR character that interrupts the current process.
+On UNIX systems the preset value usually is 3 (^C).
+
+
+Option: vquit=value
+Aliases: quit=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: tested
+
+Sets the value for the VQUIT character that quits the current process.
+On my Linux 2.2 system the preset value is 0x1c (^\).
+
+
+Option: verase=value
+Aliases: erase=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: tested
+
+Sets the value for the VERASE character that erases the last character.
+On many UNIX systems the preset value is 0x7f.
+
+
+Option: vkill=value
+Aliases: kill=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: tested
+
+Sets the value for the VKILL character that kills (erases) the current line.
+On my Linux 2.2 system systems the preset value is 0x15 (^U).
+
+
+Option: veof=value
+Aliases: eof=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: tested
+
+Sets the value for the VEOF character that kills indicate end of file.
+On most UNIX systems the preset value is 0x04 (^D).
+
+
+Option: vtime=value
+Aliases: time=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: not tested
+
+Sets the value of VTIME. See "man 1 stty" / time.
+On my Linux 2.2 system the preset value is 0.
+
+
+Option: vmin=value
+Aliases: min=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: not tested
+
+Sets the value of VMIN. See "man 1 stty" / time.
+On my Linux 2.2 system the preset value is 1.
+
+
+Option: vswtc=value
+Aliases: swtc=value, swtch=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: Linux
+Status: not tested
+
+Sets the value of VSWTC. "Switches to a different shell layer".
+On my Linux 2.2 system the preset value is 0.
+
+
+Option: vstart=value
+Aliases: start=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: tested
+
+Sets the value for the VSTART character that resumes data flow after a stop.
+Usually the preset value is 0x11 (^Q).
+
+
+Option: vstop=value
+Aliases: stop=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: tested
+
+Sets the value for the VSTOP character that stops output.
+Usually the preset value is 0x13 (^S)
+
+
+Option: vsusp=value
+Aliases: susp=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: tested
+
+Sets the value for the VSUSP character that suspends the current foreground
+process and reactivates the shell.
+Usually the preset value is 0x1a (^Z)
+
+
+Option: vdsusp=value
+Aliases: dsusp=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: FreeBSD, HP-UX, SunOS
+Status: tested
+
+Sets the value for the VDSUSP character that suspends the current foreground
+process and reactivates the shell.
+
+
+Option: veol=value
+Aliases: eol=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: tested with awkward results
+
+Sets the value for the VEOL character that should indicate end of line.
+Not clear what differentiates it from the return key; xterm window put "xterm"
+into the input buffer.
+On my Linux 2.2 system the preset value is 0 (disabled)
+
+
+Option: vreprint=value
+Aliases: reprint=value, rprnt=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: FreeBSD, Linux, SunOS
+Status: not tested
+
+Sets the value for the VREPRINT character that should reprint the current line.
+On my Linux 2.2 system the preset value is 0x12 (^R). Nevertheless, bash
+enters backward search mode.
+
+
+Option: vdiscard=value
+Aliases: discard=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: FreeBSD, Linux, SunOS
+Status: not tested
+
+Sets the value for the VDISCARD character.
+On my Linux 2.2 system the preset value is 0x0f (^O)
+
+
+Option: vwerase=value
+Aliases: werase=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: tested
+
+Sets the value for the VWERASE character that erases the last word.
+On my Linux 2.2 system the preset value is 0x17 (^W)
+
+
+Option: vlnext=value
+Aliases: lnext=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: tested
+
+Sets the value for the VLNEXT character that lets the next input character raw
+(not interpreted).
+On my Linux 2.2 system the preset value is 0x16 (^V)
+
+
+Option: veol2=value
+Aliases: eol2=value
+
+Type: BYTE
+Option group: TERMIOS
+Phase: FD
+Platforms: all
+Status: not tested
+
+Sets the value for the VEOL2 character.
+On my Linux 2.2 system the preset value is 0 (disabled).
+
+
+===============================================================================
+READLINE options
+
+Option: history-file=filename
+Aliases: history=filename
+
+Type: STRING
+Option group: READLINE
+Phase: LATE
+Platforms: (depends on libreadline installation)
+
+Without this option, the readline address uses only a per process history
+list. With this option, socat tries to read history lines during initialization
+from the given file, and on termination writes the old and new lines to the
+file.
+NOTE: currently, no mechanism is implemented for limiting the length of the
+history file.
+NOTE: filename must be a valid relativ or absolute path; "~" is not supported!
+
+
+Option: noprompt
+
+Type: BOOL
+Option group: READLINE
+Phase: LATE
+Platforms: all
+
+Since version 1.3.3, socat per default tries to determine a prompt -
+that is then passed to the readline call - by remembering the last
+incomplete line of the output. With this option, socat does not pass a
+prompt to the readline call, so it might set the cursor to the first column
+of the terminal.
+
+
+Option: noecho
+
+Type: STRING
+Option group: READLINE
+Phase: LATE
+Platforms: all
+
+Specifies a regular pattern for a prompt that prevents the following input
+line from being displayed on the screen and from being added to the history.
+The prompt is defined as the text that was output to the readline address
+after the lastest newline character and before an input character was
+typed. The pattern is a regular expression, e.g.
+"^[Pp]assword:.*$" or "([Uu]ser:|[Pp]assword:)". See regex(7) for details.
+
+
+Option: prompt
+
+Type: STRING
+Option group: READLINE
+Phase: LATE
+Platforms: all
+
+Passes the string as prompt to the readline function. readline prints this
+prompt when stepping through the history. If this string matches a constant
+prompt issued by an interactive program on the other socat address,
+consistent look and feel can be archieved.
+
+===============================================================================
+OPENSSL options
+
+Option: openssl-cipherlist=string
+Aliases: cipherlist=string, ciphers=string, cipher=string
+
+Type: STRING
+Option group: OPENSSL
+Phase: SPEC
+Platforms: (depends on openssl installation)
+
+Selects the list of ciphers that may be used for the connection.
+See the man page ciphers(1), section CIPHER LIST FORMAT, for
+detailed information about syntax, values, and default of the cipherlist
+string.
+Several cipher strings may be given, separated by ':'.
+Some simple cipher strings:
+ 3DES Uses a cipher suite with triple DES.
+ MD5 Uses a cipher suite with MD5.
+ aNULL Uses a cipher suite without authentication.
+ NULL Does not use encryption.
+ HIGH Uses a cipher suite with "high" encryption.
+Note that the peer must support the selected property, or the negotiation
+will fail.
+
+
+Option: openssl-method=string
+Aliases: method=string
+
+Type: STRING
+Option group: OPENSSL
+Phase: SPEC
+Platforms: (depends on openssl installation)
+
+Sets the protocol version to be used. Valid strings (not case sensitive) are:
+ SSLv2 Select SSL protocol version 2.
+ SSLv3 Select SSL protocol version 3.
+ SSLv23 Select SSL protocol version 2 or 3. This is the default when
+ this option is not provided.
+ TLSv1 Select TLS protocol version 1.
+
+
+Option: openssl-verify=bool
+Aliases: verify=bool
+
+Type: BOOL
+Option group: OPENSSL
+Phase: SPEC
+Platforms: (depends on openssl installation)
+
+ Controls check of the peer's certificate. Default is 1 (true). Disabling
+ verify might open your socket for everyone!
+
+
+Option: openssl-certificate=file
+Aliases: cert=file
+
+Type: FILENAME
+Option group: OPENSSL
+Phase: SPEC
+Platforms: (depends on openssl installation)
+
+Specifies the file with the certificate. The certificate must be
+in OpenSSL format (*.pem). With openssl-listen, this option is strongly
+recommended: except with cipher aNULL, "no shared ciphers" error might
+occur when no certificate is given.
+
+
+Option: openssl-key=file
+Aliases: key
+
+Type: FILENAME
+Option group: OPENSSL
+Phase: SPEC
+Platforms: (depends on openssl installation)
+
+Specifies the file with the private key. The private key may be in this
+file or in the file given with the ref(cert) option. The party that has
+to proof that it is the owner of a certificate needs the private key.
+
+
+Option: openssl-cafile=file
+Aliases: cafile
+
+Type: FILENAME
+Option group: OPENSSL
+Phase: SPEC
+Platforms: (depends on openssl installation)
+
+Specifies the file with the trusted (root) authority certificates. The file
+must be in PEM format and should contain one or more certificates.
+
+
+Option: openssl-capath=directory
+Aliases: capath
+
+Type: FILENAME
+Option group: OPENSSL
+Phase: SPEC
+Platforms: (depends on openssl installation)
+
+Specify the directory with the trusted (root) certificates. The directory
+must contain certificates in PEM format and their hashes (see OpenSSL
+documentation)
+
+
+Option: openssl-egd=file
+Aliases: egd
+
+Type: FILENAME
+Option group: OPENSSL
+Phase: SPEC
+Platforms: (depends on openssl installation)
+
+On some systems, openssl requires an explicit source of random data. Specify
+the socket name where an entropy gathering daemon like egd provides random
+data, e.g. /dev/egd-pool.
+
+
+Option: openssl-pseudo
+Aliases: pseudo
+
+Type: BOOL
+Option group: OPENSSL
+Phase: SPEC
+Platforms: (depends on openssl installation)
+
+On systems where openssl cannot find an entropy source and where no entropy
+gathering daemon can be utilized, this option activates a mechanism for
+providing pseudo entropy. This is archieved by taking the current time in
+microseconds for feeding the libc pseudo random number generator with an
+initial value. openssl is then feeded with output from random calls.
+NOTE:This mechanism is not sufficient for generation of secure keys!
+
+
+Option: openssl-fips
+Aliases: fips
+
+Type: BOOL
+Option group: BOOL
+Phase: SPEC
+Platforms: (depends on OpenSSL installation and FIPS implementation)
+
+Enables FIPS mode if compiled in. For info about the FIPS encryption
+implementation standard see http://oss-institute.org/fips-faq.html.
+This mode might require that the involved certificates are generated with a
+FIPS enabled version of openssl. Setting or clearing this option on one
+socat address affects all OpenSSL addresses of this process.
+
+
+===============================================================================
+Application specific address options
+
+
+Option: ignoreeof
+Aliases: ignoreof
+
+Type: BOOL
+Option group: APPL
+Phase: LATE
+Platforms: all
+
+This option has to be supported by the application. For socat it means that an
+EOF condition on this data source does not trigger termination procedures, but
+instead the read/write loop waits for one second and then tries to read more
+input data. This behaviour emulates "tail -f" and might not be useful for all
+kinds of input devices, but regular files and /dev/null are good candidates.
+Termination of socat then can only occur by EOF condition of the other input
+device, an error, or by external events.
+
+
+Option: cr
+
+Type: CONST
+Option group: APPL
+Phase: LATE
+Platforms: all
+
+The appropriate data endpoint uses CR ('\r', 0x0d) as line terminator
+character. Convert data to and from this stream appropriately.
+This is useful for, e.g., modems.
+
+
+Option: crnl
+Aliases: crlf
+
+Type: CONST
+Option group: APPL
+Phase: LATE
+Platforms: all
+
+The appropriate data endpoint uses CR+LF ("\r\n", 0x0d0a ) as line terminator
+string. Convert data to and from this stream appropriately.
+This is useful for, e.g., TCP protocols like SMTP and FTP.
+
+
+Option: readbytes=num
+Aliases: bytes
+
+Type: SIZE_T
+Option group: APPL
+Phase: LATE
+Platforms: all
+
+socat reads only so many bytes from this address (the address provides
+only so many bytes for transfer and pretends to be at EOF afterwards).
+
+
+Option: lockfile=filename
+
+Type: FILENAME
+Option group: APPL
+Phase: INIT
+Platforms: all
+
+If lockfile exists, exits with error. If lockfile does not exist, creates it
+and continues; removes lockfile on exit.
+
+
+Option: waitlock=filename
+
+Type: FILENAME
+Option group: APPL
+Phase: INIT
+Platforms: all
+
+If lockfile exists, waits until it disappears. When lockfile does not exist,
+creates it and continues; removes lockfile on exit.
+
+===============================================================================
+RETRY options
+
+Option: retry=<num>
+
+Type: UINT
+Option group: RETRY
+Phase: INIT
+Platforms: all
+
+Number of retries before the connection or listen attempt is aborted.
+Default is 0, which means just one attempt.
+
+
+Option: intervall=<double>
+
+Type: TIMESPEC
+Option group: RETRY
+Phase: INIT
+Platforms: all
+
+Time between consecutive attempts (seconds). Default is 1 second.
+
+
+Option: forever
+
+Type: BOOL
+Option group: RETRY
+Phase: INIT
+Platforms: all
+
+Performs an unlimited number of retry attempts.
+
+===============================================================================
+EXT2 options
+
+Option: ext2-secrm=<bool>
+Aliases: secrm=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: Linux
+
+Sets the secrm file attribute on the file.
+
+
+Option: ext2-unrm=<bool>
+Aliases: unrm=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: Linux
+
+Sets the unrm file attribute on the file.
+
+
+Option: ext2-compr=<bool>
+Aliases: compr=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: Linux
+
+Sets the compr file attribute on the file.
+
+
+Option: ext2-sync=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: all
+
+Sets the sync file attribute on the file.
+
+
+Option: ext2-immutable=<bool>
+Aliases: immutable=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: Linux
+
+Sets the immutable file attribute on the file.
+
+
+Option: ext2-append=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: all
+
+Sets the append file attribute on the file.
+
+
+Option: ext2-nodump=<bool>
+Aliases: nodump=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: Linux
+
+Sets the nodump file attribute on the file.
+
+
+Option: ext2-noatime=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: Linux
+
+Sets the noatime file attribute on the file.
+
+
+Option: ext2-journal-data=<bool>
+Aliases: journal-data=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: Linux
+
+Sets the journal-data file attribute on the file.
+
+
+Option: ext2-notail=<bool>
+Aliases: notail=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: none
+
+Sets the notail file attribute on the file.
+
+
+Option: ext2-dirsync=<bool>
+Aliases: dirsync=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: Linux
+
+Sets the dirsync file attribute on the file.
+
+
+Option: ext2-topdir=<bool>
+Aliases: topdir=<bool>
+
+Type: BOOL
+Option group: REG
+Phase: FD
+Platforms: Linux
+
+Sets the topdir file attribute on the file.
+
+
+===============================================================================
+
+Appendix: generating a sandbox (chroot environment)
+
+While it is possible to generate a sandbox almost anywhere in the file system,
+I recommend to use a file system that has been mounted with restrictions,
+especially nosuid and maybe nodev, or even ro.
+
+You may mount a dedicated file system for the sandbox, so it gets a little
+harder for the guests to determine for sure if they are within a sandbox when
+using "ls -id /"
+
+The following desribes typical steps for generating a sandbox. Depending on
+your operating system, application, and security requirements, your mileage may
+vary. With the below steps, you will be able to run some check programs to play
+around with the sandbox.
+
+I Installation
+1) Create a sandbox group - but give it and all following "sandbox" ids a more
+cryptic name!
+2) Create a sandbox user, only in sandbox group. If this user must never login,
+give it a useless shell like /bin/false
+3) Check the sandbox home directory (e.g. /home/sandbox) and save and remove
+all .profile, public_html/ etc.
+4) Optionally mount a new file system over the new home directory
+5) Generate subdirectories bin, lib, etc, usr, usr/bin, usr/lib.
+Set their permissions and ownership equal to the original directories (or use
+only root.root)
+6) Generate subdirectory home/sandbox (or similarly; like sandbox home)
+7) Generate etc/passwd with users sandbox and root, but do not store original
+password hashes there!
+8) Generate etc/group with only groups sandbox and root (or system on AIX)
+9) Copy test programs and utilities to bin, e.g. su, id, ls, mount, strace (but
+without SUID/SGID)
+10) Copy the required shared libraries and the shared library loader to their
+directories.
+On Linux, e.g. /lib/ld-linux.so.2, /lib/libnss_compat.so.2
+Note: it is often difficult to find out what shared libraries are (still) not
+installed in the sandbox. The programs invoked in the sandbox typically do not
+give useful error messages. If chroot's exec call gives an error like "no such
+file or directory", and you do not know if it even found the program itself,
+then remove the test programs execute permission; the error message should
+change to "execute permission denied" or so. Redo the execute permissions and
+look for the shared libraries...
+List required libraries of a program:
+Linux: ldd <program>
+AIX: xdb <program>
+ map
+
+11) For testing purposes, install id, ls, su, mount, strace, and maybe sh in
+the sandbox. Test it.
+
+II Customization
+12) Copy your applications, configuration files, and data to the appropriate
+directories within the sandbox.
+Test function of the application in the sandbox, and add missing files and
+libraries. If an application program gets killed immediately after start, it
+might miss a shared library.
+
+III Cleanup, check
+13) Implement your own tricks how to improve security of the sandbox
+14) Remove test programs like bin/sh, id, ls, mount, strace
+
+
+===============================================================================
+socket types, modes and their security features:
+IP.v4.TCP.connect
+IP.v4.TCP.listen range tcpwrap srcport lowport
+IP.v4.UDP.connect
+IP.v4.UDP.listen range tcpwrap srcport lowport
+IP.v4.UDP.sendto
+IP.v4.UDP.recvfrom range tcpwrap srcport lowport
+IP.v4.UDP.recv range tcpwrap srcport lowport
+IP.v4.raw.sendto
+IP.v4.raw.recvfrom range tcpwrap
+IP.v4.raw.recv range tcpwrap
+IP.v6.TCP.connect
+IP.v6.TCP.listen range tcpwrap srcport lowport
+IP.v6.UDP.connect
+IP.v6.UDP.listen range tcpwrap srcport lowport
+IP.v6.UDP.sendto
+IP.v6.UDP.recvfrom range tcpwrap srcport lowport
+IP.v6.UDP.recv range tcpwrap srcport lowport
+IP.v6.raw.sendto
+IP.v6.raw.recvfrom range tcpwrap
+IP.v6.raw.recv srcport lowport
+UNIX.stream.connect
+UNIX.stream.listen
+UNIX.dgram.sendto
+UNIX.dgram.recvfrom
+UNIX.dgram.recv
+OPENSSL.connect
+OPENSSL.TCP4.listen range tcpwrap srcport lowport
+OPENSSL.TCP6.listen range tcpwrap srcport lowport
+
+===============================================================================
+Missing features and Caveats:
+
+. no support for SIGIO mechanism
+. no support for socket ancillary messages
+. Probably many ioctls not implemented due to missing documentation
+. only limited implementation of raw sockets and interfaces,
+. no support for high level sockets beyond UNIX, INET, and INET6 domains
diff --git a/error.c b/error.c
new file mode 100644
index 0000000..3345979
--- /dev/null
+++ b/error.c
@@ -0,0 +1,249 @@
+/* $Id: error.c,v 1.29 2007/02/08 18:22:23 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* the logging subsystem */
+
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <errno.h>
+#if HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+#include <sys/utsname.h>
+#include <time.h> /* time_t, strftime() */
+#include <sys/time.h> /* gettimeofday() */
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "mytypes.h"
+#include "compat.h"
+#include "utils.h"
+
+#include "error.h"
+
+/* translate MSG level to SYSLOG level */
+int syslevel[] = {
+ LOG_DEBUG,
+ LOG_INFO,
+ LOG_NOTICE,
+ LOG_WARNING,
+ LOG_ERR,
+ LOG_CRIT };
+
+struct diag_opts {
+ const char *progname;
+ int msglevel;
+ int exitlevel;
+ int logstderr;
+ int syslog;
+ FILE *logfile;
+ int logfacility;
+ bool micros;
+ int exitstatus; /* pass signal number to error exit */
+ bool withhostname; /* in custom logs add hostname */
+ char *hostname;
+} ;
+
+
+struct diag_opts diagopts =
+ { NULL, E_ERROR, E_ERROR, 1, 0, NULL, LOG_DAEMON, false, 0 } ;
+
+static void _msg(int level, const char *buff, const char *syslp);
+
+static struct wordent facilitynames[] = {
+ {"auth", (void *)LOG_AUTH},
+#ifdef LOG_AUTHPRIV
+ {"authpriv", (void *)LOG_AUTHPRIV},
+#endif
+#ifdef LOG_CONSOLE
+ {"console", (void *)LOG_CONSOLE},
+#endif
+ {"cron", (void *)LOG_CRON},
+ {"daemon", (void *)LOG_DAEMON},
+#ifdef LOG_FTP
+ {"ftp", (void *)LOG_FTP},
+#endif
+ {"kern", (void *)LOG_KERN},
+ {"local0", (void *)LOG_LOCAL0},
+ {"local1", (void *)LOG_LOCAL1},
+ {"local2", (void *)LOG_LOCAL2},
+ {"local3", (void *)LOG_LOCAL3},
+ {"local4", (void *)LOG_LOCAL4},
+ {"local5", (void *)LOG_LOCAL5},
+ {"local6", (void *)LOG_LOCAL6},
+ {"local7", (void *)LOG_LOCAL7},
+ {"lpr", (void *)LOG_LPR},
+ {"mail", (void *)LOG_MAIL},
+ {"news", (void *)LOG_NEWS},
+#ifdef LOG_SECURITY
+ {"security", (void *)LOG_SECURITY},
+#endif
+ {"syslog", (void *)LOG_SYSLOG},
+ {"user", (void *)LOG_USER},
+ {"uucp", (void *)LOG_UUCP}
+} ;
+
+
+void diag_set(char what, const char *arg) {
+ switch (what) {
+ const struct wordent *keywd;
+
+ case 'y': diagopts.syslog = true;
+ if (arg && arg[0]) {
+ if ((keywd =
+ keyw(facilitynames, arg,
+ sizeof(facilitynames)/sizeof(struct wordent))) == NULL) {
+ Error1("unknown syslog facility \"%s\"", arg);
+ } else {
+ diagopts.logfacility = (int)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;
+ }
+ case 's': diagopts.logstderr = true; break; /* logging to stderr is default */
+ case 'p': diagopts.progname = arg;
+ openlog(diagopts.progname, LOG_PID, diagopts.logfacility);
+ break;
+ case 'd': --diagopts.msglevel; break;
+ case 'u': diagopts.micros = true; break;
+ default: msg(E_ERROR, "unknown diagnostic option %c", what);
+ }
+}
+
+void diag_set_int(char what, int arg) {
+ switch (what) {
+ case 'D': diagopts.msglevel = arg; break;
+ case 'e': diagopts.exitlevel = arg; break;
+ case 'x': diagopts.exitstatus = arg; break;
+ case 'h': diagopts.withhostname = arg;
+ if ((diagopts.hostname = getenv("HOSTNAME")) == NULL) {
+ struct utsname ubuf;
+ uname(&ubuf);
+ diagopts.hostname = strdup(ubuf.nodename);
+ }
+ break;
+ default: msg(E_ERROR, "unknown diagnostic option %c", what);
+ }
+}
+
+int diag_get_int(char what) {
+ switch (what) {
+ case 'y': return diagopts.syslog;
+ case 's': return diagopts.logstderr;
+ case 'd': case 'D': return diagopts.msglevel;
+ case 'e': return diagopts.exitlevel;
+ }
+ return -1;
+}
+
+const char *diag_get_string(char what) {
+ switch (what) {
+ case 'p': return diagopts.progname;
+ }
+ return NULL;
+}
+
+/* Linux and AIX syslog format:
+Oct 4 17:10:37 hostname socat[52798]: D signal(13, 1)
+*/
+void msg(int level, const char *format, ...) {
+#if HAVE_GETTIMEOFDAY || 1
+ struct timeval now;
+ int result;
+ time_t nowt;
+#else /* !HAVE_GETTIMEOFDAY */
+ time_t now;
+#endif /* !HAVE_GETTIMEOFDAY */
+#define BUFLEN 512
+ char buff[BUFLEN], *bufp, *syslp;
+ size_t bytes;
+ va_list ap;
+
+ if (level < diagopts.msglevel) return;
+ va_start(ap, format);
+#if HAVE_GETTIMEOFDAY || 1
+ result = gettimeofday(&now, NULL);
+ if (result < 0) {
+ /* invoking msg() might create endless recursion; by hand instead */
+ sprintf(buff, "cannot read time: %s["F_pid"] E %s",
+ diagopts.progname, getpid(), strerror(errno));
+ _msg(LOG_ERR, buff, strstr(buff, " E "+1));
+ strcpy(buff, "unknown time "); bytes = 20;
+ } else {
+ nowt = now.tv_sec;
+#if HAVE_STRFTIME
+ if (diagopts.micros) {
+ bytes = strftime(buff, 20, "%Y/%m/%d %H:%M:%S", localtime(&nowt));
+ bytes += sprintf(buff+19, "."F_tv_usec" ", now.tv_usec);
+ } else {
+ bytes =
+ strftime(buff, 21, "%Y/%m/%d %H:%M:%S ", localtime(&nowt));
+ }
+#else
+ strcpy(buff, ctime(&nowt));
+ bytes = strlen(buff);
+#endif
+ }
+#else /* !HAVE_GETTIMEOFDAY */
+ now = time(NULL); if (now == (time_t)-1) {
+ /* invoking msg() might create endless recursion; by hand instead */
+ sprintf(buff, "cannot read time: %s["F_pid"] E %s",
+ diagopts.progname, getpid(), strerror(errno));
+ _msg(LOG_ERR, buff, strstr(buff, " E "+1));
+ strcpy(buff, "unknown time "); bytes = 20;
+ } else {
+#if HAVE_STRFTIME
+ bytes = strftime(buff, 21, "%Y/%m/%d %H:%M:%S ", localtime(&now));
+#else
+ strcpy(buff, ctime(&now));
+ bytes = strlen(buff);
+#endif
+ }
+#endif /* !HAVE_GETTIMEOFDAY */
+ bufp = buff + bytes;
+ if (diagopts.withhostname) {
+ bytes = sprintf(bufp, "%s ", diagopts.hostname), bufp+=bytes;
+ }
+ bytes = sprintf(bufp, "%s["F_pid"] ", diagopts.progname, getpid());
+ bufp += bytes;
+ syslp = bufp;
+ *bufp++ = "DINWEF"[level];
+ *bufp++ = ' ';
+ vsnprintf(bufp, BUFLEN-(bufp-buff)-1, format, ap);
+ strcat(bufp, "\n");
+ _msg(level, buff, syslp);
+ if (level >= diagopts.exitlevel) {
+ va_end(ap);
+ if (E_NOTICE >= diagopts.msglevel) {
+ sprintf(syslp, "N exit(1)\n");
+ _msg(E_NOTICE, buff, syslp);
+ }
+ exit(diagopts.exitstatus ? diagopts.exitstatus : 1);
+ }
+ va_end(ap);
+}
+
+
+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);
+ }
+ if (diagopts.logfile) {
+ fputs(buff, diagopts.logfile); fflush(diagopts.logfile);
+ }
+}
diff --git a/error.h b/error.h
new file mode 100644
index 0000000..72eb85b
--- /dev/null
+++ b/error.h
@@ -0,0 +1,208 @@
+/* $Id: error.h,v 1.14 2007/03/06 21:19:18 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __error_h_included
+#define __error_h_included 1
+
+/* these must be defines because they are used by cpp! */
+#define E_DEBUG 0 /* all, including trace */
+#define E_INFO 1 /* all status changes etc. */
+#define E_NOTICE 2 /* all interesting, e.g. for firewall relay */
+#define E_WARN 3 /* all unusual */
+#define E_ERROR 4 /* errors */
+#define E_FATAL 5 /* emergency abort */
+
+
+/* here are the macros for diag invocation; use WITH_MSGLEVEL to specify the
+ lowest priority that is compiled into your program */
+#ifndef WITH_MSGLEVEL
+# define WITH_MSGLEVEL E_NOTICE
+#endif
+
+#if WITH_MSGLEVEL <= E_FATAL
+#define Fatal(m) msg(E_FATAL,"%s",m)
+#define Fatal1(m,a1) msg(E_FATAL,m,a1)
+#define Fatal2(m,a1,a2) msg(E_FATAL,m,a1,a2)
+#define Fatal3(m,a1,a2,a3) msg(E_FATAL,m,a1,a2,a3)
+#define Fatal4(m,a1,a2,a3,a4) msg(E_FATAL,m,a1,a2,a3,a4)
+#define Fatal5(m,a1,a2,a3,a4,a5) msg(E_FATAL,m,a1,a2,a3,a4,a5)
+#define Fatal6(m,a1,a2,a3,a4,a5,a6) msg(E_FATAL,m,a1,a2,a3,a4,a5,a6)
+#define Fatal7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_FATAL,m,a1,a2,a3,a4,a5,a6,a7)
+#else /* !(WITH_MSGLEVEL <= E_FATAL) */
+#define Fatal(m)
+#define Fatal1(m,a1)
+#define Fatal2(m,a1,a2)
+#define Fatal3(m,a1,a2,a3)
+#define Fatal4(m,a1,a2,a3,a4)
+#define Fatal5(m,a1,a2,a3,a4,a5)
+#define Fatal6(m,a1,a2,a3,a4,a5,a6)
+#define Fatal7(m,a1,a2,a3,a4,a5,a6,a7)
+#endif /* !(WITH_MSGLEVEL <= E_FATAL) */
+
+#if WITH_MSGLEVEL <= E_ERROR
+#define Error(m) msg(E_ERROR,"%s",m)
+#define Error1(m,a1) msg(E_ERROR,m,a1)
+#define Error2(m,a1,a2) msg(E_ERROR,m,a1,a2)
+#define Error3(m,a1,a2,a3) msg(E_ERROR,m,a1,a2,a3)
+#define Error4(m,a1,a2,a3,a4) msg(E_ERROR,m,a1,a2,a3,a4)
+#define Error5(m,a1,a2,a3,a4,a5) msg(E_ERROR,m,a1,a2,a3,a4,a5)
+#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)
+#else /* !(WITH_MSGLEVEL >= E_ERROR) */
+#define Error(m)
+#define Error1(m,a1)
+#define Error2(m,a1,a2)
+#define Error3(m,a1,a2,a3)
+#define Error4(m,a1,a2,a3,a4)
+#define Error5(m,a1,a2,a3,a4,a5)
+#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)
+#endif /* !(WITH_MSGLEVEL <= E_ERROR) */
+
+#if WITH_MSGLEVEL <= E_WARN
+#define Warn(m) msg(E_WARN,"%s",m)
+#define Warn1(m,a1) msg(E_WARN,m,a1)
+#define Warn2(m,a1,a2) msg(E_WARN,m,a1,a2)
+#define Warn3(m,a1,a2,a3) msg(E_WARN,m,a1,a2,a3)
+#define Warn4(m,a1,a2,a3,a4) msg(E_WARN,m,a1,a2,a3,a4)
+#define Warn5(m,a1,a2,a3,a4,a5) msg(E_WARN,m,a1,a2,a3,a4,a5)
+#define Warn6(m,a1,a2,a3,a4,a5,a6) msg(E_WARN,m,a1,a2,a3,a4,a5,a6)
+#define Warn7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_WARN,m,a1,a2,a3,a4,a5,a6,a7)
+#else /* !(WITH_MSGLEVEL <= E_WARN) */
+#define Warn(m)
+#define Warn1(m,a1)
+#define Warn2(m,a1,a2)
+#define Warn3(m,a1,a2,a3)
+#define Warn4(m,a1,a2,a3,a4)
+#define Warn5(m,a1,a2,a3,a4,a5)
+#define Warn6(m,a1,a2,a3,a4,a5,a6)
+#define Warn7(m,a1,a2,a3,a4,a5,a6,a7)
+#endif /* !(WITH_MSGLEVEL <= E_WARN) */
+
+#if WITH_MSGLEVEL <= E_NOTICE
+#define Notice(m) msg(E_NOTICE,"%s",m)
+#define Notice1(m,a1) msg(E_NOTICE,m,a1)
+#define Notice2(m,a1,a2) msg(E_NOTICE,m,a1,a2)
+#define Notice3(m,a1,a2,a3) msg(E_NOTICE,m,a1,a2,a3)
+#define Notice4(m,a1,a2,a3,a4) msg(E_NOTICE,m,a1,a2,a3,a4)
+#define Notice5(m,a1,a2,a3,a4,a5) msg(E_NOTICE,m,a1,a2,a3,a4,a5)
+#define Notice6(m,a1,a2,a3,a4,a5,a6) msg(E_NOTICE,m,a1,a2,a3,a4,a5,a6)
+#define Notice7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_NOTICE,m,a1,a2,a3,a4,a5,a6,a7)
+#define Notice8(m,a1,a2,a3,a4,a5,a6,a7,a8) msg(E_NOTICE,m,a1,a2,a3,a4,a5,a6,a7,a8)
+#define Notice9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9) msg(E_NOTICE,m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
+#else /* !(WITH_MSGLEVEL <= E_NOTICE) */
+#define Notice(m)
+#define Notice1(m,a1)
+#define Notice2(m,a1,a2)
+#define Notice3(m,a1,a2,a3)
+#define Notice4(m,a1,a2,a3,a4)
+#define Notice5(m,a1,a2,a3,a4,a5)
+#define Notice6(m,a1,a2,a3,a4,a5,a6)
+#define Notice7(m,a1,a2,a3,a4,a5,a6,a7)
+#define Notice8(m,a1,a2,a3,a4,a5,a6,a7,a8)
+#define Notice9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
+#endif /* !(WITH_MSGLEVEL <= E_NOTICE) */
+
+#if WITH_MSGLEVEL <= E_INFO
+#define Info(m) msg(E_INFO,"%s",m)
+#define Info1(m,a1) msg(E_INFO,m,a1)
+#define Info2(m,a1,a2) msg(E_INFO,m,a1,a2)
+#define Info3(m,a1,a2,a3) msg(E_INFO,m,a1,a2,a3)
+#define Info4(m,a1,a2,a3,a4) msg(E_INFO,m,a1,a2,a3,a4)
+#define Info5(m,a1,a2,a3,a4,a5) msg(E_INFO,m,a1,a2,a3,a4,a5)
+#define Info6(m,a1,a2,a3,a4,a5,a6) msg(E_INFO,m,a1,a2,a3,a4,a5,a6)
+#define Info7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_INFO,m,a1,a2,a3,a4,a5,a6,a7)
+#define Info8(m,a1,a2,a3,a4,a5,a6,a7,a8) msg(E_INFO,m,a1,a2,a3,a4,a5,a6,a7,a8)
+#define Info9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9) msg(E_INFO,m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
+#define Info10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) msg(E_INFO,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+#define Info11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) msg(E_INFO,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
+#else /* !(WITH_MSGLEVEL <= E_INFO) */
+#define Info(m)
+#define Info1(m,a1)
+#define Info2(m,a1,a2)
+#define Info3(m,a1,a2,a3)
+#define Info4(m,a1,a2,a3,a4)
+#define Info5(m,a1,a2,a3,a4,a5)
+#define Info6(m,a1,a2,a3,a4,a5,a6)
+#define Info7(m,a1,a2,a3,a4,a5,a6,a7)
+#define Info8(m,a1,a2,a3,a4,a5,a6,a7,a8)
+#define Info9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
+#define Info10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+#define Info11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
+#endif /* !(WITH_MSGLEVEL <= E_INFO) */
+
+#if WITH_MSGLEVEL <= E_DEBUG
+#define Debug(m) msg(E_DEBUG,"%s",m)
+#define Debug1(m,a1) msg(E_DEBUG,m,a1)
+#define Debug2(m,a1,a2) msg(E_DEBUG,m,a1,a2)
+#define Debug3(m,a1,a2,a3) msg(E_DEBUG,m,a1,a2,a3)
+#define Debug4(m,a1,a2,a3,a4) msg(E_DEBUG,m,a1,a2,a3,a4)
+#define Debug5(m,a1,a2,a3,a4,a5) msg(E_DEBUG,m,a1,a2,a3,a4,a5)
+#define Debug6(m,a1,a2,a3,a4,a5,a6) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6)
+#define Debug7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7)
+#define Debug8(m,a1,a2,a3,a4,a5,a6,a7,a8) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8)
+#define Debug9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
+#define Debug10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+#define Debug11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
+#define Debug12(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)
+#define Debug13(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)
+#define Debug14(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)
+#define Debug15(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
+#define Debug16(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16)
+#define Debug17(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17)
+#define Debug18(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18)
+#else /* !(WITH_MSGLEVEL <= E_DEBUG) */
+#define Debug(m)
+#define Debug1(m,a1)
+#define Debug2(m,a1,a2)
+#define Debug3(m,a1,a2,a3)
+#define Debug4(m,a1,a2,a3,a4)
+#define Debug5(m,a1,a2,a3,a4,a5)
+#define Debug6(m,a1,a2,a3,a4,a5,a6)
+#define Debug7(m,a1,a2,a3,a4,a5,a6,a7)
+#define Debug8(m,a1,a2,a3,a4,a5,a6,a7,a8)
+#define Debug9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
+#define Debug10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
+#define Debug11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
+#define Debug12(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)
+#define Debug13(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)
+#define Debug14(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)
+#define Debug15(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
+#define Debug16(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16)
+#define Debug17(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17)
+#define Debug18(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18)
+#endif /* !(WITH_MSGLEVEL <= E_DEBUG) */
+
+/* message with software controlled serverity */
+#if WITH_MSGLEVEL <= E_FATAL
+#define Msg(l,m) msg(l,"%s",m)
+#define Msg1(l,m,a1) msg(l,m,a1)
+#define Msg2(l,m,a1,a2) msg(l,m,a1,a2)
+#define Msg3(l,m,a1,a2,a3) msg(l,m,a1,a2,a3)
+#define Msg4(l,m,a1,a2,a3,a4) msg(l,m,a1,a2,a3,a4)
+#define Msg5(l,m,a1,a2,a3,a4,a5) msg(l,m,a1,a2,a3,a4,a5)
+#define Msg6(l,m,a1,a2,a3,a4,a5,a6) msg(l,m,a1,a2,a3,a4,a5,a6)
+#define Msg7(l,m,a1,a2,a3,a4,a5,a6,a7) msg(l,m,a1,a2,a3,a4,a5,a6,a7)
+#else /* !(WITH_MSGLEVEL >= E_FATAL) */
+#define Msg(l,m)
+#define Msg1(l,m,a1)
+#define Msg2(l,m,a1,a2)
+#define Msg3(l,m,a1,a2,a3)
+#define Msg4(l,m,a1,a2,a3,a4)
+#define Msg5(l,m,a1,a2,a3,a4,a5)
+#define Msg6(l,m,a1,a2,a3,a4,a5,a6)
+#define Msg7(l,m,a1,a2,a3,a4,a5,a6,a7)
+#endif /* !(WITH_MSGLEVEL <= E_FATAL) */
+
+
+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 void msg(int level, const char *format, ...);
+
+#endif /* !defined(__error_h_included) */
diff --git a/fdname.c b/fdname.c
new file mode 100644
index 0000000..f48e736
--- /dev/null
+++ b/fdname.c
@@ -0,0 +1,327 @@
+/* $Id: fdname.c,v 1.9 2007/02/08 18:27:00 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2003-2007 */
+/* 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
+ NOTE: it works on UNIX (kernel) file descriptors, not on libc files! */
+
+#include "config.h"
+#include "xioconfig.h" /* what features are enabled */
+
+#include "sysincludes.h"
+
+#include "mytypes.h"
+#include "compat.h"
+#include "error.h"
+#include "sycls.h"
+#include "sysutils.h"
+
+#include "filan.h"
+
+
+struct sockopt {
+ int so;
+ char *name;
+};
+
+
+int statname(const char *file, int fd, int filetype, FILE *outfile);
+int cdevname(int fd, FILE *outfile);
+int sockname(int fd, FILE *outfile);
+int unixame(int fd, FILE *outfile);
+int tcpname(int fd, FILE *outfile);
+
+
+int fdname(const char *file, int fd, FILE *outfile) {
+ struct stat buf = {0};
+ int filetype;
+ Debug1("checking file descriptor %u", fd);
+ if (fd >= 0) {
+ if (Fstat(fd, &buf) < 0) {
+ if (errno == EBADF) {
+ Debug2("fstat(%d): %s", fd, strerror(errno));
+ return -1;
+ } else {
+ Error2("fstat(%d): %s", fd, strerror(errno));
+ }
+ }
+ filetype = (buf.st_mode&S_IFMT)>>12;
+ return statname(file, fd, filetype, outfile);
+ } else {
+ if (Stat(file, &buf) < 0) {
+ Error2("stat(\"%s\"): %s", file, strerror(errno));
+ }
+ filetype = (buf.st_mode&S_IFMT)>>12;
+ return statname(file, -1, filetype, outfile);
+ }
+}
+
+#if HAVE_PROC_DIR_FD
+static int procgetfdname(int fd, char *filepath, size_t pathsize) {
+ static pid_t pid = -1;
+ char procpath[PATH_MAX];
+ int len;
+
+ /* even if configure has shown that we have /proc, we must check if it
+ exists at runtime, because we might be in a chroot environment */
+#if HAVE_STAT64
+ {
+ struct stat64 buf;
+ if (Stat64("/proc", &buf) < 0) {
+ return -1;
+ }
+ if (!S_ISDIR(buf.st_mode)) {
+ return -1;
+ }
+ }
+#else /* !HAVE_STAT64 */
+ {
+ struct stat buf;
+ if (Stat("/proc", &buf) < 0) {
+ return -1;
+ }
+ if (!S_ISDIR(buf.st_mode)) {
+ return -1;
+ }
+ }
+#endif /* !HAVE_STAT64 */
+
+ if (pid < 0) pid = Getpid();
+ snprintf(procpath, sizeof(procpath), "/proc/"F_pid"/fd/%d", pid, fd);
+ if ((len = Readlink(procpath, filepath, pathsize-1)) < 0) {
+ Error4("readlink(\"%s\", %p, "F_Zu"): %s",
+ procpath, filepath, pathsize, strerror(errno));
+ return -1;
+ }
+ filepath[len] = '\0';
+ return 0;
+}
+#endif /* HAVE_PROC_DIR_FD */
+
+int statname(const char *file, int fd, int filetype, FILE *outfile) {
+ char filepath[PATH_MAX];
+ int result;
+
+ filepath[0] = '\0';
+#if HAVE_PROC_DIR_FD
+ if (fd >= 0) {
+ procgetfdname(fd, filepath, sizeof(filepath));
+ if (filepath[0] == '/') {
+ file = filepath;
+ }
+ }
+#endif /* HAVE_PROC_DIR_FD */
+ /* now see for type specific infos */
+ switch (filetype) {
+ case (S_IFIFO>>12): /* 1, FIFO */
+ fputs("pipe", outfile);
+ if (file) fprintf(outfile, " %s", file);
+ break;
+ case (S_IFCHR>>12): /* 2, character device */
+ if (cdevname(fd, outfile) == 0) {
+ if (file) fprintf(outfile, " %s", file);
+ }
+ break;
+ case (S_IFDIR>>12): /* 4, directory */
+ fputs("dir", outfile);
+ if (file) fprintf(outfile, " %s", file);
+ break;
+ case (S_IFBLK>>12): /* 6, block device */
+ fputs("blkdev", outfile);
+ if (file) fprintf(outfile, " %s", file);
+ break;
+ case (S_IFREG>>12): /* 8, regular file */
+ fputs("file", outfile);
+ if (file) fprintf(outfile, " %s", file);
+ break;
+ case (S_IFLNK>>12): /* 10, symbolic link */
+ fputs("link", outfile);
+ if (file) fprintf(outfile, " %s", file);
+ break;
+ case (S_IFSOCK>>12): /* 12, socket */
+#if WITH_SOCKET
+ if (fd >= 0) {
+ result = sockname(fd, outfile);
+ } else if (file) {
+ fprintf(outfile, "socket %s", file);
+ } else {
+ fputs("socket", outfile);
+ }
+#else
+ Error("SOCKET support not compiled in");
+ return -1;
+#endif /* !WITH_SOCKET */
+ break;
+ }
+ /* ioctl() */
+ fputc('\n', outfile);
+
+ return 0;
+}
+
+
+/* character device analysis */
+/* return -1 on error, 0 if no name was found, or 1 if it printed ttyname */
+int cdevname(int fd, FILE *outfile) {
+ int ret;
+
+ if ((ret = Isatty(fd)) < 0) {
+ Error2("isatty(%d): %s", fd, strerror(errno));
+ return -1;
+ }
+ if (ret > 0) {
+ char *name;
+
+ fputs("tty", outfile);
+ if ((name = Ttyname(fd)) != NULL) {
+ fputc(' ', outfile);
+ fputs(name, outfile);
+ return 1;
+ }
+ } else {
+ fputs("chrdev", outfile);
+ }
+ return 0;
+}
+
+
+#if WITH_SOCKET
+int sockname(int fd, FILE *outfile) {
+#define FDNAME_OPTLEN 256
+#define FDNAME_NAMELEN 256
+ socklen_t optlen;
+ int opttype;
+#ifdef SO_ACCEPTCONN
+ int optacceptconn;
+#endif
+ int result /*0, i*/;
+ char namebuff[FDNAME_NAMELEN];
+ char peerbuff[FDNAME_NAMELEN];
+ /* in Linux these optcodes are 'enum', but on AIX they are bits! */
+ union sockaddr_union sockname, peername; /* the longest I know of */
+ socklen_t namelen;
+#if 0 && defined(SIOCGIFNAME)
+ /*Linux struct ifreq ifc = {{{ 0 }}};*/
+ struct ifreq ifc = {{ 0 }};
+#endif
+
+ optlen = FDNAME_OPTLEN;
+
+ Getsockopt(fd, SOL_SOCKET, SO_TYPE, &opttype, &optlen);
+#ifdef SO_ACCEPTCONN
+ Getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &optacceptconn, &optlen);
+#endif
+
+ namelen = sizeof(sockname);
+ result = Getsockname(fd, &sockname.soa, &namelen);
+ if (result < 0) {
+ Error2("getsockname(%d): %s", fd, strerror(errno));
+ return -1;
+ }
+
+ namelen = sizeof(peername);
+ result = Getpeername(fd, (struct sockaddr *)&peername, &namelen);
+ if (result < 0) {
+ Error2("getpeername(%d): %s", fd, strerror(errno));
+ }
+
+ switch (sockname.soa.sa_family) {
+#if WITH_UNIX
+ case AF_UNIX:
+ fprintf(outfile, "unix%s%s %s",
+ opttype==SOCK_DGRAM?"datagram":"",
+#ifdef SO_ACCEPTCONN
+ optacceptconn?"(listening)":
+#endif
+ "",
+ sockaddr_unix_info(&sockname.un, namelen,
+ namebuff, sizeof(namebuff)));
+ break;
+#endif
+#if WITH_IP4
+ case AF_INET:
+ switch (opttype) {
+#if WITH_TCP
+ case SOCK_STREAM:
+ fprintf(outfile, "tcp%s %s %s",
+#ifdef SO_ACCEPTCONN
+ optacceptconn?"(listening)":
+#endif
+ "",
+ sockaddr_inet4_info(&sockname.ip4,
+ namebuff, sizeof(namebuff)),
+ sockaddr_inet4_info(&peername.ip4,
+ peerbuff, sizeof(peerbuff)));
+ break;
+#endif
+#if WITH_UDP
+ case SOCK_DGRAM:
+ fprintf(outfile, "udp%s %s %s",
+#ifdef SO_ACCEPTCONN
+ optacceptconn?"(listening)":
+#endif
+ "",
+ sockaddr_inet4_info(&sockname.ip4,
+ namebuff, sizeof(namebuff)),
+ sockaddr_inet4_info(&peername.ip4,
+ peerbuff, sizeof(peerbuff)));
+ break;
+#endif
+ default:
+ fprintf(outfile, "ip %s",
+ sockaddr_inet4_info(&sockname.ip4,
+ namebuff, sizeof(namebuff)));
+ break;
+ }
+ break;
+#endif /* WITH_IP4 */
+
+#if WITH_IP6
+ case AF_INET6:
+ switch (opttype) {
+#if WITH_TCP
+ case SOCK_STREAM:
+ fprintf(outfile, "tcp6%s %s %s",
+#ifdef SO_ACCEPTCONN
+ optacceptconn?"(listening)":
+#endif
+ "",
+ sockaddr_inet6_info(&sockname.ip6,
+ namebuff, sizeof(namebuff)),
+ sockaddr_inet6_info(&peername.ip6,
+ peerbuff, sizeof(peerbuff)));
+ break;
+#endif
+#if WITH_UDP
+ case SOCK_DGRAM:
+ fprintf(outfile, "udp6%s %s %s",
+#ifdef SO_ACCEPTCONN
+ optacceptconn?"(listening)":
+#endif
+ "",
+ sockaddr_inet6_info(&sockname.ip6,
+ namebuff, sizeof(namebuff)),
+ sockaddr_inet6_info(&peername.ip6,
+ peerbuff, sizeof(peerbuff)));
+ break;
+#endif
+ default:
+ fprintf(outfile, "ip6 %s",
+ sockaddr_inet6_info(&sockname.ip6,
+ namebuff, sizeof(namebuff)));
+ break;
+ }
+#endif /* WITH_IP6 */
+ default:
+ fputs("socket", outfile);
+ }
+
+ return result;
+#undef FDNAME_OPTLEN
+#undef FDNAME_NAMELEN
+}
+#endif /* WITH_SOCKET */
+
+
+
+
diff --git a/filan.c b/filan.c
new file mode 100644
index 0000000..b486389
--- /dev/null
+++ b/filan.c
@@ -0,0 +1,918 @@
+/* $Id: filan.c,v 1.45 2007/02/08 19:42:34 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* the subroutine filan makes a "FILe descriptor ANalysis". It checks the
+ type of file descriptor and tries to retrieve as much info about it as
+ possible without modifying its state.
+ NOTE: it works on UNIX (kernel) file descriptors, not on libc files! */
+
+#include "config.h"
+#include "xioconfig.h" /* what features are enabled */
+
+#include "sysincludes.h"
+
+#include "mytypes.h"
+#include "compat.h"
+#include "error.h"
+#include "sycls.h"
+#include "sysutils.h"
+
+#include "filan.h"
+
+
+struct sockopt {
+ int so;
+ char *name;
+};
+
+/* dirty workaround so we dont get an error on AIX when getting linked with
+ libwrap */
+int allow_severity, deny_severity;
+
+/* global variables for configuring filan */
+bool filan_followsymlinks;
+bool filan_rawoutput;
+
+
+int sockoptan(int fd, const struct sockopt *optname, int socklay, FILE *outfile);
+int tcpan(int fd, FILE *outfile);
+const char *getfiletypestring(int st_mode);
+
+static int printtime(FILE *outfile, time_t time);
+
+static int headprinted;
+
+/* analyse a file system entry, referred by file name */
+int filan_file(const char *filename, FILE *outfile) {
+ int fd = -1;
+ int result;
+#if HAVE_STAT64
+ struct stat64 buf = {0};
+#else
+ struct stat buf = {0};
+#endif /* !HAVE_STAT64 */
+
+ if (filan_followsymlinks) {
+#if HAVE_STAT64
+ result = Stat64(filename, &buf);
+#else
+ result = Stat(filename, &buf);
+#endif /* !HAVE_STAT64 */
+ if (result < 0) {
+ Warn3("stat(\"%s\", %p): %s", filename, &buf, strerror(errno));
+ }
+ } else {
+#if HAVE_STAT64
+ result = Lstat64(filename, &buf);
+#else
+ result = Lstat(filename, &buf);
+#endif /* !HAVE_STAT64 */
+ if (result < 0) {
+ Warn3("lstat(\"%s\", %p): %s", filename, &buf, strerror(errno));
+ }
+ }
+ switch (buf.st_mode&S_IFMT) {
+#ifdef S_IFSOCK
+ case S_IFSOCK: /* probably, it's useless to make a socket and describe it */
+ break;
+#endif /* S_IFSOCK */
+ default:
+ if ((fd =
+ Open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK
+#ifdef O_LARGEFILE
+ |O_LARGEFILE
+#endif
+ , 0700))
+ < 0) {
+ Warn2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s",
+ filename, strerror(errno));
+ }
+ }
+
+ result = filan_stat(&buf, fd, -1, outfile);
+ fputc('\n', outfile);
+ return result;
+}
+
+/* analyze a file descriptor */
+int filan_fd(int fd, FILE *outfile) {
+#if HAVE_STAT64
+ struct stat64 buf = {0};
+#else
+ struct stat buf = {0};
+#endif /* !HAVE_STAT64 */
+ int result;
+
+ Debug1("checking file descriptor %u", fd);
+#if HAVE_STAT64
+ result = Fstat64(fd, &buf);
+#else
+ result = Fstat(fd, &buf);
+#endif /* !HAVE_STAT64 */
+ if (result < 0) {
+ if (errno == EBADF) {
+ Debug2("fstat(%d): %s", fd, strerror(errno));
+ } else {
+ Warn2("fstat(%d): %s", fd, strerror(errno));
+ }
+ return -1;
+ }
+ Debug2("fd %d is a %s", fd, getfiletypestring(buf.st_mode));
+
+ result = filan_stat(&buf, fd, fd, outfile);
+
+ if (result >= 0) {
+ /* even more dynamic info */
+ { /* see if data is available */
+ struct pollfd ufds;
+ ufds.fd = fd;
+ ufds.events = POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|POLLWRNORM|POLLWRBAND
+#ifdef POLLMSG
+ |POLLMSG
+#endif
+ ;
+ if (Poll(&ufds, 1, 0) < 0) {
+ Warn4("poll({%d, %hd, %hd}, 1, 0): %s",
+ ufds.fd, ufds.events, ufds.revents, strerror(errno));
+ } else {
+ fputs("poll: ", outfile);
+ if (ufds.revents & POLLIN) fputs("IN,", outfile);
+ if (ufds.revents & POLLPRI) fputs("PRI,", outfile);
+ if (ufds.revents & POLLOUT) fputs("OUT,", outfile);
+ if (ufds.revents & POLLERR) fputs("ERR,", outfile);
+ if (ufds.revents & POLLNVAL) fputs("NVAL,", outfile);
+#ifdef FIONREAD
+ if (ufds.revents & POLLIN) {
+ size_t sizet;
+ if ((result = Ioctl(fd, FIONREAD, &sizet) >= 0)) {
+ fprintf (outfile, "; FIONREAD="F_Zu, sizet);
+ }
+ }
+#endif /* defined(FIONREAD) */
+#if WITH_SOCKET && defined(MSG_DONTWAIT)
+ if ((ufds.revents & POLLIN) && isasocket(fd)) {
+ char _peername[SOCKADDR_MAX];
+ struct sockaddr *pa = (struct sockaddr *)_peername;
+ struct msghdr msgh = {0};
+ char peekbuff[1]; /* [0] fails with some compilers */
+#if HAVE_STRUCT_IOVEC
+ struct iovec iovec;
+#endif
+ char ctrlbuff[5120];
+ ssize_t bytes;
+
+ fputs("; ", outfile);
+ msgh.msg_name = pa;
+ msgh.msg_namelen = sizeof(*pa);
+#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);
+#endif
+#if HAVE_STRUCT_MSGHDR_MSGFLAGS
+ msgh.msg_flags = 0;
+#endif
+ if ((bytes = Recvmsg(fd, &msgh, MSG_PEEK|MSG_DONTWAIT)) < 0) {
+ Warn1("recvmsg(): %s", strerror(errno));
+ } else {
+ fprintf(outfile, "recvmsg="F_Zd", ", bytes);
+ }
+ }
+#endif /* WITH_SOCKET && defined(MSG_DONTWAIT) */
+ }
+ }
+ }
+ fputc('\n', outfile);
+ return 0;
+}
+
+
+int filan_stat(
+#if HAVE_STAT64
+ struct stat64 *buf
+#else
+ struct stat *buf
+#endif /* !HAVE_STAT64 */
+ , int statfd, int dynfd, FILE *outfile) {
+ char stdevstr[8];
+ int result;
+
+ /* print header */
+ if (!headprinted) {
+ if (filan_rawoutput) {
+ fputs(" FD type\tdevice\tinode\tmode\tlinks\tuid\tgid"
+#if HAVE_ST_RDEV
+ "\trdev"
+#endif
+ "\tsize"
+#if HAVE_ST_BLKSIZE
+ "\tblksize"
+#endif
+#if HAVE_ST_BLOCKS
+ "\tblocks"
+#endif
+ "\tatime\t\tmtime\t\tctime\t\tcloexec\tflags"
+#if defined(F_GETOWN)
+ "\tsigown"
+#endif
+ , outfile);
+ } else /* !rawoutput */ {
+ fputs(" FD type\tdevice\tinode\tmode\tlinks\tuid\tgid"
+#if HAVE_ST_RDEV
+ "\trdev"
+#endif
+ "\tsize"
+#if HAVE_ST_BLKSIZE
+ "\tblksize"
+#endif
+#if HAVE_ST_BLOCKS
+ "\tblocks"
+#endif
+ "\tatime\t\t\t\tmtime\t\t\t\tctime\t\t\t\tcloexec\tflags"
+#if defined(F_GETOWN)
+ "\tsigown"
+#endif
+ , outfile);
+
+ } /* endif !rawoutput */
+
+#if defined(F_GETSIG)
+ fputs("\tsigio", outfile);
+#endif /* defined(F_GETSIG) */
+ fputc('\n', outfile);
+ headprinted = 1;
+ }
+ if (filan_rawoutput) {
+ snprintf(stdevstr, 8, F_st_dev, buf->st_dev);
+ } else {
+ snprintf(stdevstr, 8, "%hu,%hu", (unsigned short)buf->st_dev>>8, (unsigned short)buf->st_dev&0xff);
+ }
+ fprintf(outfile, "%4d: %s\t%s\t"
+#if HAVE_STAT64
+ F_st64_ino
+#else
+ F_st_ino
+#endif /* HAVE_STAT64 */
+ "\t"F_mode"\t"F_st_nlink"\t"F_uid"\t"F_gid
+#if HAVE_ST_RDEV
+ "\t%hu,%hu"
+#endif
+ "\t"
+#if HAVE_STAT64
+ F_st64_size
+#else
+ F_st_size
+#endif /* HAVE_STAT64 */
+#if HAVE_ST_BLKSIZE
+ "\t"F_st_blksize
+#endif
+#if HAVE_ST_BLOCKS
+#if HAVE_STAT64
+ "\t"F_st64_blocks
+#else
+ "\t"F_st_blocks
+#endif /* HAVE_STAT64 */
+#endif
+ ,
+ (dynfd>=0?dynfd:statfd), getfiletypestring(buf->st_mode),
+ stdevstr,
+ buf->st_ino,
+ buf->st_mode, buf->st_nlink, buf->st_uid,
+ buf->st_gid,
+#if HAVE_ST_RDEV
+ (unsigned short)buf->st_rdev>>8, (unsigned short)buf->st_rdev&0xff,
+#endif
+ buf->st_size
+#if HAVE_ST_BLKSIZE
+ , buf->st_blksize
+#endif
+#if HAVE_ST_BLOCKS
+ , buf->st_blocks /* on Linux, this applies to stat and stat64 */
+#endif
+ );
+
+ printtime(outfile, buf->st_atime);
+ printtime(outfile, buf->st_mtime);
+ printtime(outfile, buf->st_ctime);
+
+#if 0
+ {
+ fputc('\t', outfile);
+ time = asctime(localtime(&buf->st_mtime));
+ if (strchr(time, '\n')) *strchr(time, '\n') = '\0';
+ fputs(time, outfile);
+
+ fputc('\t', outfile);
+ time = asctime(localtime(&buf->st_ctime));
+ if (strchr(time, '\n')) *strchr(time, '\n') = '\0';
+ fputs(time, outfile);
+ }
+#endif
+
+ /* here comes dynamic info - it is only meaningful with preexisting FDs */
+ if (dynfd >= 0) { /*!indent */
+ int cloexec, flags;
+#if defined(F_GETOWN)
+ int sigown;
+#endif
+#if defined(F_GETSIG)
+ int sigio;
+#endif /* defined(F_GETSIG) */
+
+ cloexec = Fcntl(dynfd, F_GETFD);
+ flags = Fcntl(dynfd, F_GETFL);
+#if defined(F_GETOWN)
+ sigown = Fcntl(dynfd, F_GETOWN);
+#endif
+#if defined(F_GETSIG)
+ sigio = Fcntl(dynfd, F_GETSIG);
+#endif /* defined(F_GETSIG) */
+ fprintf(outfile, "\t%d\tx%06x", cloexec, flags);
+#if defined(F_GETOWN)
+ fprintf(outfile, "\t%d", sigown);
+#endif
+#if defined(F_GETSIG)
+ fprintf(outfile, "\t%d", sigio);
+#endif /* defined(F_GETSIG) */
+ } else {
+ fputs("\t\t"
+#if defined(F_GETOWN)
+ "\t"
+#endif
+#if defined(F_GETSIG)
+ "\t"
+#endif /* defined(F_GETSIG) */
+ , outfile);
+ }
+
+ /* now see for type specific infos */
+ if (statfd >= 0) { /*!indent */
+ switch (buf->st_mode&S_IFMT) {
+ case (S_IFIFO): /* 1, FIFO */
+ break;
+ case (S_IFCHR): /* 2, character device */
+ result = cdevan(statfd, outfile);
+ break;
+ case (S_IFDIR): /* 4, directory */
+ break;
+ case (S_IFBLK): /* 6, block device */
+ break;
+ case (S_IFREG): /* 8, regular file */
+ break;
+ case (S_IFLNK): /* 10, symbolic link */
+ break;
+#ifdef S_IFSOCK
+ case (S_IFSOCK): /* 12, socket */
+#if WITH_SOCKET
+ result = sockan(statfd, outfile);
+#else
+ Warn("SOCKET support not compiled in");
+ return -1;
+#endif /* !WITH_SOCKET */
+ break;
+#endif /* S_IFSOCK */
+ }
+ }
+ /* ioctl() */
+ return 0;
+}
+
+
+#if LATER
+int fdinfo(int fd) {
+ int result;
+
+ result = Fcntl(fd, F_GETFD);
+ fcntl(fd, F_GETFL, );
+ fcntl(fd, F_GETLK, );
+#ifdef F_GETOWN
+ fcntl(fd, F_GETOWN, );
+#endif
+#ifdef F_GETSIG
+ fcntl(fd, F_GETSIG, );
+#endif
+}
+
+
+int devinfo(int fd) {
+ ioctl();
+}
+#endif
+
+
+/* character device analysis */
+int cdevan(int fd, FILE *outfile) {
+ int ret;
+
+ if ((ret = Isatty(fd)) < 0) {
+ Warn2("isatty(%d): %s", fd, strerror(errno));
+ return -1;
+ }
+ if (ret > 0) {
+ struct termios termarg;
+ char *name;
+ int i;
+
+ if ((name = Ttyname(fd)) == NULL) {
+ /*Warn2("ttyname(%d): %s", fd, strerror(errno));*/
+ fputs("\tNULL", outfile);
+ } else {
+ fprintf(outfile, "\t%s", name);
+ }
+ if (Tcgetattr(fd, &termarg) < 0) {
+ Warn3("tcgetattr(%d, %p): %s", fd, &termarg, strerror(errno));
+ return -1;
+ }
+ fprintf(outfile, " \tIFLAGS=%08x OFLAGS=%08x CFLAGS=%08x LFLAGS=%08x",
+ termarg.c_iflag, termarg.c_oflag, termarg.c_cflag, termarg.c_lflag);
+
+ /* and the control characters */
+ if (filan_rawoutput) {
+ for (i=0; i<NCCS; ++i) {
+ fprintf(outfile, " cc[%d]=%d", i, termarg.c_cc[i]);
+ }
+ } else {
+ for (i=0; i<NCCS; ++i) {
+ int ch;
+ unsigned char s[4];
+ ch = termarg.c_cc[i];
+ if (isprint(ch)) {
+ s[0] = ch; s[1]= '\0';
+ } else if (ch < ' ') {
+ s[0] = '^'; s[1] = ch+'@'; s[2] = '\0';
+ } else {
+ s[0] = 'x';
+ s[1] = (ch>>4)>=10?(ch>>4)-10+'A':(ch>>4)+'0';
+ s[2] = (ch&0x0f)>=10?(ch&0x0f)-10+'A':(ch&0x0f)+'0';
+ s[3] = '\0';
+ }
+ fprintf(outfile, " cc[%d]=%s", i, s);
+ }
+ }
+ }
+ return 0;
+}
+
+
+#if WITH_SOCKET
+int sockan(int fd, FILE *outfile) {
+#define FILAN_OPTLEN 256
+#define FILAN_NAMELEN 256
+ socklen_t optlen;
+ int result /*0, i*/;
+ static const char *socktypes[] = {
+ "undef", "STREAM", "DGRAM", "RAW", "RDM",
+ "SEQPACKET", "undef", "undef", "undef", "undef",
+ "PACKET", "undef" } ;
+ char nambuff[FILAN_NAMELEN];
+ /* in Linux these optcodes are 'enum', but on AIX they are bits! */
+ static const struct sockopt sockopts[] = {
+ {SO_DEBUG, "DEBUG"},
+ {SO_REUSEADDR, "REUSEADDR"},
+ {SO_TYPE, "TYPE"},
+ {SO_ERROR, "ERROR"},
+ {SO_DONTROUTE, "DONTROUTE"},
+ {SO_BROADCAST, "BROADCAST"},
+ {SO_SNDBUF, "SNDBUF"},
+ {SO_RCVBUF, "RCVBUF"},
+ {SO_KEEPALIVE, "KEEPALIVE"},
+ {SO_OOBINLINE, "OOBINLINE"},
+#ifdef SO_NO_CHECK
+ {SO_NO_CHECK, "NO_CHECK"},
+#endif
+#ifdef SO_PRIORITY
+ {SO_PRIORITY, "PRIORITY"},
+#endif
+ {SO_LINGER, "LINGER"},
+#ifdef SO_BSDCOMPAT
+ {SO_BSDCOMPAT, "BSDCOMPAT"},
+#endif
+#ifdef SO_REUSEPORT
+ {SO_REUSEPORT, "REUSEPORT"},
+#endif /* defined(SO_REUSEPORT) */
+#ifdef SO_PASSCRED
+ {SO_PASSCRED, "PASSCRED"},
+#endif
+#ifdef SO_PEERCRED
+ {SO_PEERCRED, "PEERCRED"},
+#endif
+#ifdef SO_RCVLOWAT
+ {SO_RCVLOWAT, "RCVLOWAT"},
+#endif
+#ifdef SO_SNDLOWAT
+ {SO_SNDLOWAT, "SNDLOWAT"},
+#endif
+#ifdef SO_RCVTIMEO
+ {SO_RCVTIMEO, "RCVTIMEO"},
+#endif
+#ifdef SO_SNDTIMEO
+ {SO_SNDTIMEO, "SNDTIMEO"},
+#endif
+#ifdef SO_SECURITY_AUTHENTICATION
+ {SO_SECURITY_AUTHENTICATION, "SECURITY_AUTHENTICATION"},
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
+ {SO_SECURITY_ENCRYPTION_TRANSPORT, "SECURITY_ENCRYPTION_TRANSPORT"},
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_NETWORK
+ {SO_SECURITY_ENCRYPTION_NETWORK, "SECURITY_ENCRYPTION_NETWORK"},
+#endif
+#ifdef SO_BINDTODEVICE
+ {SO_BINDTODEVICE, "BINDTODEVICE"},
+#endif
+#ifdef SO_ATTACH_FILTER
+ {SO_ATTACH_FILTER, "ATTACH_FILTER"},
+#endif
+#ifdef SO_DETACH_FILTER
+ {SO_DETACH_FILTER, "DETACH_FILTER"},
+#endif
+ {0, NULL} } ;
+ char optval[FILAN_OPTLEN];
+ const struct sockopt *optname;
+ union sockaddr_union sockname, peername; /* the longest I know of */
+ socklen_t namelen;
+#if 0 && defined(SIOCGIFNAME)
+ /*Linux struct ifreq ifc = {{{ 0 }}};*/
+ struct ifreq ifc = {{ 0 }};
+#endif
+
+ optlen = FILAN_OPTLEN;
+ result = Getsockopt(fd, SOL_SOCKET, SO_TYPE, optval, &optlen);
+ if (result < 0) {
+ Debug4("getsockopt(%d, SOL_SOCKET, SO_TYPE, %p, {"F_socklen"}): %s",
+ fd, optval, optlen, strerror(errno));
+ } else {
+ Debug3("fd %d: socket of type %d (\"%s\")", fd, *(int *)optval,
+ socktypes[*(int *)optval]);
+ }
+
+ optname = sockopts; while (optname->so) {
+ optlen = FILAN_OPTLEN;
+ result =
+ Getsockopt(fd, SOL_SOCKET, optname->so, (void *)optval, &optlen);
+ if (result < 0) {
+ Debug5("getsockopt(%d, SOL_SOCKET, %d, %p, {"F_socklen"}): %s",
+ fd, optname->so, optval, optlen, strerror(errno));
+ fputc('\t', outfile);
+ } else if (optlen == sizeof(int)) {
+ Debug2("getsockopt(,,, {%d}, %d)",
+ *(int *)optval, optlen);
+ /*Info2("%s: %d", optname->name, *(int *)optval);*/
+ fprintf(outfile, "%s=%d\t", optname->name, *(int *)optval);
+ } else {
+ Debug3("getsockopt(,,, {%d,%d}, %d)",
+ ((int *)optval)[0], ((int *)optval)[1], optlen);
+ fprintf(outfile, "%s={%d,%d}\t", optname->name,
+ ((int *)optval)[0], ((int *)optval)[1]);
+ }
+ ++optname;
+ }
+
+ namelen = sizeof(sockname);
+ result = Getsockname(fd, (struct sockaddr *)&sockname, &namelen);
+ if (result < 0) {
+ putc('\n', outfile);
+ Warn2("getsockname(%d): %s", fd, strerror(errno));
+ return -1;
+ }
+ fputc('\t', outfile);
+ fputs(sockaddr_info((struct sockaddr *)&sockname, namelen, nambuff, sizeof(nambuff)),
+ outfile);
+
+ namelen = sizeof(peername);
+ result = Getpeername(fd, (struct sockaddr *)&peername, &namelen);
+ if (result < 0) {
+ putc('\n', outfile);
+ Warn2("getpeername(%d): %s", fd, strerror(errno));
+ } else {
+ /* only valid if getpeername() succeeded */
+ fputs(" <-> ", outfile);
+ fprintf(outfile, "%s\t",
+ sockaddr_info((struct sockaddr *)&peername, namelen,
+ nambuff, sizeof(nambuff)));
+ }
+
+#if 0 && defined(SIOCGIFNAME)
+ if ((result = Ioctl(fd, SIOCGIFNAME, &ifc)) < 0) {
+ Warn3("ioctl(%d, SIOCGIFNAME, %p): %s", fd, &ifc, strerror(errno));
+ } else {
+ fprintf(outfile, "IFNAME=\"%s\"\t", ifc.ifr_name);
+ }
+#endif /* SIOCGIFNAME */
+
+ switch (((struct sockaddr *)&sockname)->sa_family) {
+#if WITH_UNIX
+ case AF_UNIX:
+ /* no options for unix domain sockets known yet -> no unixan() */
+ result = 0;
+ break;
+#endif
+#if WITH_IP4
+ case AF_INET:
+ result = ipan(fd, outfile);
+ break;
+#endif
+#if WITH_IP6
+ case AF_INET6:
+ result = ipan(fd, outfile);
+ result |= ip6an(fd, outfile);
+ break;
+#endif
+ default:
+ fputs("**** NO FURTHER ANALYSIS FOR THIS SOCKET TYPE IMPLEMENTED", outfile);
+ result = 0;
+ }
+ return result;
+#undef FILAN_OPTLEN
+#undef FILAN_NAMELEN
+}
+#endif /* WITH_SOCKET */
+
+
+#if WITH_IP4 || WITH_IP6
+/* prints the option values for the IP protocol and the IP based protocols */
+/* no distinction between IP4 and IP6 yet */
+int ipan(int fd, FILE *outfile) {
+ /* in Linux these optcodes are 'enum', but on AIX they are bits! */
+ static const struct sockopt ipopts[] = {
+ {IP_TOS, "IP_TOS"},
+ {IP_TTL, "IP_TTL"},
+#ifdef IP_HDRINCL
+ {IP_HDRINCL, "IP_HDRINCL"},
+#endif
+#ifdef IP_OPTIONS
+ {IP_OPTIONS, "IP_OPTIONS"},
+#endif
+#ifdef IP_ROUTER_ALERT
+ {IP_ROUTER_ALERT, "IP_ROUTER_ALERT"},
+#endif
+#ifdef IP_RECVOPTS
+ {IP_RECVOPTS, "IP_RECVOPTS"},
+#endif
+#ifdef IP_RETOPTS
+ {IP_RETOPTS, "IP_RETOPTS"},
+#endif
+#ifdef IP_PKTINFO
+ {IP_PKTINFO, "IP_PKTINFO"},
+#endif
+#ifdef IP_PKTOPTIONS
+ {IP_PKTOPTIONS, "IP_PKTOPTIONS"},
+#endif
+#ifdef IP_MTU_DISCOVER
+ {IP_MTU_DISCOVER, "IP_MTU_DISCOVER"},
+#endif
+#ifdef IP_RECVERR
+ {IP_RECVERR, "IP_RECVERR"},
+#endif
+#ifdef IP_RECVTTL
+ {IP_RECVTTL, "IP_RECVTTL"},
+#endif
+#ifdef IP_RECVTOS
+ {IP_RECVTOS, "IP_RECVTOS"},
+#endif
+#ifdef IP_MTU
+ {IP_MTU, "IP_MTU"},
+#endif
+#ifdef IP_FREEBIND
+ {IP_FREEBIND, "IP_FREEBIND"},
+#endif
+#ifdef IP_MULTICAST_TTL
+ {IP_MULTICAST_TTL, "IP_MULTICAST_TTL"},
+#endif
+#ifdef IP_MULTICAST_LOOP
+ {IP_MULTICAST_LOOP, "IP_MULTICAST_LOOP"},
+#endif
+ {0, NULL} } ;
+ const struct sockopt *optname;
+ int opttype;
+ socklen_t optlen = sizeof(opttype);
+
+ optname = ipopts; while (optname->so) {
+ sockoptan(fd, optname, SOL_IP, outfile);
+ ++optname;
+ }
+ /* want to pass the fd to the next layer protocol. dont know how to get the
+ protocol number from the fd? use TYPE to identify TCP. */
+ if (Getsockopt(fd, SOL_SOCKET, SO_TYPE, &opttype, &optlen) >= 0) {
+ switch (opttype) {
+#if WITH_TCP
+ case SOCK_STREAM: tcpan(fd, outfile); break;
+#endif
+ }
+ }
+ return 0;
+}
+#endif /* WITH_IP */
+
+
+#if WITH_IP6
+/* prints the option values for the IPv6 protocol */
+int ip6an(int fd, FILE *outfile) {
+ static const struct sockopt ip6opts[] = {
+#ifdef IPV6_V6ONLY
+ {IPV6_V6ONLY, "IPV6_V6ONLY"},
+#endif
+ {0, NULL} } ;
+ const struct sockopt *optname;
+
+ optname = ip6opts; while (optname->so) {
+ sockoptan(fd, optname, SOL_IPV6, outfile);
+ ++optname;
+ }
+ return 0;
+}
+#endif /* WITH_IP6 */
+
+
+#if WITH_TCP
+int tcpan(int fd, FILE *outfile) {
+ static const struct sockopt tcpopts[] = {
+#ifdef TCP_NODELAY
+ { TCP_NODELAY, "TCP_NODELAY" },
+#endif
+#ifdef TCP_MAXSEG
+ { TCP_MAXSEG, "TCP_MAXSEG" },
+#endif
+#ifdef TCP_STDURG
+ { TCP_STDURG, "TCP_STDURG" },
+#endif
+#ifdef TCP_RFC1323
+ { TCP_RFC1323, "TCP_RFC1323" },
+#endif
+#ifdef TCP_CORK
+ { TCP_CORK, "TCP_CORK" },
+#endif
+#ifdef TCP_KEEPIDLE
+ { TCP_KEEPIDLE, "TCP_KEEPIDLE" },
+#endif
+#ifdef TCP_KEEPINTVL
+ { TCP_KEEPINTVL, "TCP_KEEPINTVL" },
+#endif
+#ifdef TCP_KEEPCNT
+ { TCP_KEEPCNT, "TCP_KEEPCNT" },
+#endif
+#ifdef TCP_SYNCNT
+ { TCP_SYNCNT, "TCP_SYNCNT" },
+#endif
+#ifdef TCP_LINGER2
+ { TCP_LINGER2, "TCP_LINGER2" },
+#endif
+#ifdef TCP_DEFER_ACCEPT
+ { TCP_DEFER_ACCEPT, "TCP_ACCEPT" },
+#endif
+#ifdef TCP_WINDOW_CLAMP
+ { TCP_WINDOW_CLAMP, "TCP_WINDOW_CLAMP" },
+#endif
+#ifdef TCP_INFO
+ { TCP_INFO, "TCP_INFO" },
+#endif
+#ifdef TCP_QUICKACK
+ { TCP_QUICKACK, "TCP_QUICKACK" },
+#endif
+#ifdef TCP_MD5SIG
+ { TCP_MD5SIG, "TCP_MD5SIG" },
+#endif
+#ifdef TCP_NOOPT
+ { TCP_NOOPT, "TCP_NOOPT" },
+#endif
+#ifdef TCP_NOPUSH
+ { TCP_NOPUSH, "TCP_NOPUSH" },
+#endif
+#ifdef TCP_SACK_DISABLE
+ { TCP_SACK_DISABLE, "TCP_SACK_DISABLE" },
+#endif
+#ifdef TCP_SIGNATURE_ENABLE
+ { TCP_SIGNATURE_ENABLE, "TCP_SIGNATURE_ENABLE" },
+#endif
+#ifdef TCP_ABORT_THRESHOLD
+ { TCP_ABORT_THRESHOLD, "TCP_ABORT_THRESHOLD" },
+#endif
+#ifdef TCP_CONN_ABORT_THRESHOLD
+ { TCP_CONN_ABORT_THRESHOLD, "TCP_CONN_ABORT_THRESHOLD" },
+#endif
+#ifdef TCP_KEEPINIT
+ { TCP_KEEPINIT, "TCP_KEEPINIT" },
+#endif
+#ifdef TCP_PAWS
+ { TCP_PAWS, "TCP_PAWS" },
+#endif
+#ifdef TCP_SACKENA
+ { TCP_SACKENA, "TCP_SACKENA" },
+#endif
+#ifdef TCP_TSOPTENA
+ { TCP_TSOPTENA, "TCP_TSOPTENA" },
+#endif
+ {0, NULL}
+ } ;
+ const struct sockopt *optname;
+
+ optname = tcpopts; while (optname->so) {
+ sockoptan(fd, optname, SOL_TCP, outfile);
+ ++optname;
+ }
+ return 0;
+}
+#endif /* WITH_TCP */
+
+
+#if WITH_SOCKET
+int sockoptan(int fd, const struct sockopt *optname, int socklay, FILE *outfile) {
+#define FILAN_OPTLEN 256
+ char optval[FILAN_OPTLEN];
+ socklen_t optlen;
+ int result;
+
+ optlen = FILAN_OPTLEN;
+ result =
+ Getsockopt(fd, socklay, optname->so, (void *)optval, &optlen);
+ if (result < 0) {
+ Debug6("getsockopt(%d, %d, %d, %p, {"F_socklen"}): %s",
+ fd, socklay, optname->so, optval, optlen, strerror(errno));
+ fputc('\t', outfile);
+ return -1;
+ } else if (optlen == 0) {
+ Debug1("getsockopt(,,, {}, %d)", optlen);
+ fprintf(outfile, "%s=\"\"\t", optname->name);
+ } else if (optlen == sizeof(int)) {
+ Debug2("getsockopt(,,, {%d}, %d)",
+ *(int *)optval, optlen);
+ fprintf(outfile, "%s=%d\t", optname->name, *(int *)optval);
+ } else {
+ char outbuf[FILAN_OPTLEN*9+128], *cp = outbuf;
+ int i;
+ for (i = 0; i < optlen/sizeof(unsigned int); ++i) {
+ cp += sprintf(cp, "%08x ", ((unsigned int *)optval)[i]);
+ }
+ *--cp = '\0'; /* delete trailing space */
+ Debug2("getsockopt(,,, {%s}, %d)", outbuf, optlen);
+ fflush(outfile);
+ fprintf(outfile, "%s={%s}\t", optname->name, outbuf);
+ }
+ return 0;
+#undef FILAN_OPTLEN
+}
+#endif /* WITH_SOCKET */
+
+
+#if WITH_SOCKET
+int isasocket(int fd) {
+ int retval;
+#if HAVE_STAT64
+ struct stat64 props;
+#else
+ struct stat props;
+#endif /* HAVE_STAT64 */
+ retval =
+#if HAVE_STAT64
+ Fstat64(fd, &props);
+#else
+ Fstat(fd, &props);
+#endif
+ if (retval < 0) {
+ Info3("fstat(%d, %p): %s", fd, &props, strerror(errno));
+ return 0;
+ }
+ /* note: when S_ISSOCK was undefined, it always gives 0 */
+ return S_ISSOCK(props.st_mode);
+}
+#endif /* WITH_SOCKET */
+
+
+const char *getfiletypestring(int st_mode) {
+ const char *s;
+
+ switch (st_mode&S_IFMT) {
+ case S_IFIFO: s = "pipe"; break;
+ case S_IFCHR: s = "chrdev"; break;
+ case S_IFDIR: s = "dir"; break;
+ case S_IFBLK: s = "blkdev"; break;
+ case S_IFREG: s = "file"; break;
+ case S_IFLNK: s = "symlink"; break;
+ case S_IFSOCK: s = "socket"; break;
+ /*! AIX: MT? */
+ default: s = "undef"; break;
+ }
+ return s;
+}
+
+static int printtime(FILE *outfile, time_t time) {
+ const char *s;
+
+ if (filan_rawoutput) {
+ fprintf(outfile, "\t"F_time, time);
+ } else {
+ fputc('\t', outfile);
+ s = asctime(localtime(&time));
+ if (strchr(s, '\n')) *strchr(s, '\n') = '\0';
+ fputs(s, outfile);
+ }
+ return 0;
+}
diff --git a/filan.h b/filan.h
new file mode 100644
index 0000000..604ab03
--- /dev/null
+++ b/filan.h
@@ -0,0 +1,38 @@
+/* $Id: filan.h,v 1.8 2007/03/06 21:19:18 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __filan_h_included
+#define __filan_h_included 1
+
+struct sockaddr; /* prevent gcc from spitting silly warning */
+struct sockaddr_un; /* prevent gcc from spitting silly warning */
+struct sockaddr_in; /* prevent gcc from spitting silly warning */
+struct sockaddr_in6; /* prevent gcc from spitting silly warning */
+
+extern bool filan_followsymlinks;
+extern bool filan_rawoutput;
+
+extern int filan_file(const char *filename, FILE *outfile);
+extern int filan_fd(int fd, FILE *outfile);
+extern int filan_stat(
+#if HAVE_STAT64
+ struct stat64 *buf
+#else
+ struct stat *buf
+#endif /* !HAVE_STAT64 */
+ , int statfd, int dynfd, FILE *outfile);
+
+extern int cdevan(int fd, FILE *outfile);
+
+#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 */
+
+extern int fdname(const char *file, int fd, FILE *outfile);
+
+#endif /* !defined(__filan_h_included) */
diff --git a/filan_main.c b/filan_main.c
new file mode 100644
index 0000000..1231263
--- /dev/null
+++ b/filan_main.c
@@ -0,0 +1,240 @@
+/* $Id: filan_main.c,v 1.19 2006/07/12 21:59:15 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* 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/";
+
+#include "config.h"
+#include "xioconfig.h"
+#include "sysincludes.h"
+
+#include "mytypes.h"
+#include "compat.h"
+#include "error.h"
+#include "sycls.h"
+#include "filan.h"
+
+
+#define WITH_HELP 1
+
+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 i;
+ int style = 0;
+ struct timespec waittime = { 0, 0 };
+ FILE *fdout = stdout;
+ const char *outfname = NULL;
+ unsigned long fildes;
+
+ diag_set('p', strchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
+
+ arg1 = argv+1; --argc;
+ while (arg1[0] && (arg1[0][0] == '-')) {
+ switch (arg1[0][1]) {
+#if WITH_HELP
+ case '?': case 'h':
+ filan_usage(stdout); exit(0);
+#endif
+#if LATER
+ case 'V': filan_version(stdout); exit(0);
+#endif
+ case 'L': filan_followsymlinks = true; break;
+ case 'd': diag_set('d', NULL); break;
+ case 's': style = 1; break;
+ case 'r': filan_rawoutput = true; break;
+ case 'i': if (arg1[0][2]) {
+ a = *arg1+2;
+ } else {
+ ++arg1, --argc;
+ if ((a = *arg1) == NULL) {
+ Error("option -i requires an argument");
+ filan_usage(stderr); exit(1);
+ }
+ }
+ m = strtoul(a, (char **)&a, 0);
+ n = m+1;
+ break;
+ case 'n': if (arg1[0][2]) {
+ a = *arg1+2;
+ } else {
+ ++arg1, --argc;
+ if ((a = *arg1) == NULL) {
+ Error("option -n requires an argument");
+ filan_usage(stderr); exit(1);
+ }
+ }
+ n = strtoul(a, (char **)&a, 0);
+ break;
+ case 'f': if (arg1[0][2]) {
+ filename = *arg1+2;
+ } else {
+ ++arg1, --argc;
+ if ((filename = *arg1) == NULL) {
+ Error("option -f requires an argument");
+ filan_usage(stderr); exit(1);
+ }
+ }
+ break;
+ case 'T': if (arg1[0][2]) {
+ waittimetxt = *arg1+2;
+ } else {
+ ++arg1, --argc;
+ if ((waittimetxt = *arg1) == NULL) {
+ Error("option -T requires an argument");
+ filan_usage(stderr); exit(1);
+ }
+ }
+ {
+ double waittimedbl;
+ waittimedbl = strtod(waittimetxt, NULL);
+ waittime.tv_sec = waittimedbl;
+ waittime.tv_nsec = (waittimedbl-waittime.tv_sec) * 1000000000;
+ }
+ break;
+ case 'o': if (arg1[0][2]) {
+ outfname = *arg1+2;
+ } else {
+ ++arg1, --argc;
+ if ((outfname = *arg1) == NULL) {
+ Error("option -o requires an argument");
+ filan_usage(stderr); exit(1);
+ }
+ }
+ break;
+ case '\0': break;
+ default:
+ diag_set_int('e', E_FATAL);
+ Error1("unknown option %s", arg1[0]);
+#if WITH_HELP
+ filan_usage(stderr);
+#endif
+ exit(1);
+ }
+#if 0
+ if (arg1[0][1] == '\0')
+ break;
+#endif
+ ++arg1; --argc;
+ }
+ if (argc != 0) {
+ Error1("%d superfluous arguments", argc);
+ filan_usage(stderr);
+ exit(1);
+ }
+ if (outfname) {
+ // special cases
+ if (!strcmp(outfname,"stdin")) { fdout=stdin; }
+ else if (!strcmp(outfname,"stdout")) { fdout=stdout; }
+ else if (!strcmp(outfname,"stderr")) { fdout=stderr; }
+ // file descriptor
+ else if (*outfname == '+') {
+ a = outfname+1;
+ fildes = strtoul(a, (char **)&a, 0);
+ if ((fdout = fdopen(fildes, "w")) == NULL) {
+ Error2("can't fdopen file descriptor %lu: %s\n", fildes, strerror(errno));
+ exit(1);
+ }
+ } else {
+ // file name
+ if ((fdout = fopen(outfname, "w")) == NULL) {
+ Error2("can't fopen '%s': %s\n",
+ outfname, strerror(errno));
+ exit(1);
+ }
+ }
+ }
+
+ Nanosleep(&waittime, NULL);
+
+ if (style == 0) {
+ /* this style gives detailled infos, but requires a file descriptor */
+ if (filename) {
+#if LATER /* this is just in case that S_ISSOCK does not work */
+ struct stat buf;
+ int fd;
+
+ if (Stat(filename, &buf) < 0) {
+ Error3("stat(\"%s\", %p): %s", filename, &buf, strerror(errno));
+ }
+ /* note: when S_ISSOCK was undefined, it always gives 0 */
+ if (S_ISSOCK(buf.st_mode)) {
+ Error("cannot analyze UNIX domain socket");
+ }
+#endif
+ filan_file(filename, fdout);
+ } else {
+ for (i = m; i < n; ++i) {
+ filan_fd(i, fdout);
+ }
+ }
+ } else {
+ /* this style gives only type and path / socket addresses, and works from
+ file descriptor or filename (with restrictions) */
+ if (filename) {
+ /* filename: NULL means yet unknown; "" means no name at all */
+#if LATER
+ int fd;
+ if ((fd =
+ Open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK
+#ifdef O_LARGEFILE
+ |O_LARGEFILE
+#endif
+ , 0700))
+ < 0) {
+ Debug2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s",
+ filename, strerror(errno));
+ }
+ fdname(filename, fd, fdout);
+#endif
+ fdname(filename, -1, fdout);
+ } else {
+ for (i = m; i < n; ++i) {
+ fdname("", i, fdout);
+ }
+ }
+ }
+ if (outfname && fdout != stdout && fdout != stderr) {
+ fclose(fdout);
+ }
+ return 0;
+}
+
+
+#if WITH_HELP
+static void filan_usage(FILE *fd) {
+ fputs(copyright, fd); fputc('\n', fd);
+ fputs("Analyze file descriptors of the process\n", fd);
+ fputs("Usage:\n", fd);
+ fputs("filan [options]\n", fd);
+ fputs(" options:\n", fd);
+#if LATER
+ fputs(" -V print version information to stdout, and exit\n", fd);
+#endif
+#if WITH_HELP
+ fputs(" -?|-h print this help text\n", fd);
+ fputs(" -d increase verbosity (use up to 4 times)\n", fd);
+#endif
+#if 0
+ fputs(" -ly[facility] log to syslog, using facility (default is daemon)\n", fd);
+ fputs(" -lf<logfile> log to file\n", fd);
+ fputs(" -ls log to stderr (default if no other log)\n", fd);
+#endif
+ fputs(" -i<fdnum> only analyze this fd\n", fd);
+ fputs(" -n<fdnum> analyze all fds from 0 up to fdnum-1 (default: 1024)\n", fd);
+ fputs(" -s simple output with just type and socket address or path\n", fd);
+/* fputs(" -c alternate device visualization\n", fd);*/
+ fputs(" -f<filename> analyze file system entry\n", fd);
+ fputs(" -T<seconds> wait before analyzing, useful to connect with debugger\n", fd);
+ fputs(" -r raw output for time stamps and rdev\n", fd);
+ fputs(" -L show symlink properties instead of following it\n", fd);
+ fputs(" -o<filename> output goes to filename, that can be:\n", fd);
+ fputs(" a regular file name, the output goes to that\n", fd);
+ fputs(" +<filedes> , output goes to the file descriptor (which must be open writable)\n", fd);
+ fputs(" the 3 special names stdin stdout and stderr\n", fd);
+}
+#endif /* WITH_HELP */
diff --git a/ftp.sh b/ftp.sh
new file mode 100755
index 0000000..91e768d
--- /dev/null
+++ b/ftp.sh
@@ -0,0 +1,158 @@
+#! /bin/sh
+# $Id: ftp.sh,v 1.11 2006/12/28 07:27:01 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2006
+# Published under the GNU General Public License V.2, see file COPYING
+
+# example how to write a shell script that communicates with stdio on the front
+# end and with a socat address on the back end
+
+# usage:
+# ftp.sh [opts] server directory/ # show directory contents on stdout
+# ftp.sh [opts] server file # print file contents to stdout
+# opts:
+# -socks socksserver # use given socks server, port 1080
+# -proxy proxyserver # use given proxy server, port 8080
+# # must be http proxy that accepts CONNECT
+# # method to ports 21 and >=1024
+# -user username # default: "ftp"
+# -passwd password # default: "anonymous@domain.org"
+# -t # shell script trace+debug
+# -d # debug on control connection (use up to 4 times)
+# -D # debug on data connection (use up to 4 times)
+# -b # block size for data connection
+# -v # verbose
+# -l* # socat logging options
+# example:
+# ftp.sh -v -d -d -D -D -D -b 65536 -proxy proxy ftp.ftp.org /README >README
+
+user="ftp"
+passwd="anonymous@domain.org"
+#method="socks4:socks" # socks4 is address spec, socks is socks server name
+method=tcp
+addropts=
+
+# socat options
+SO1=
+SO2=
+
+while :; do
+ case "$1" in
+ -socks|-socks4) shift;
+ case "$1" in
+ *:*) method="socks4:${1%%:*}"; addropts="socksport=${1#*:}" ;;
+ *) method="socks4:$1" ;;
+ esac ;;
+ -socks4a) shift;
+ case "$1" in
+ *:*) method="socks4a:${1%%:*}"; addropts="socksport=${1#*:}" ;;
+ *) method="socks4a:$1" ;;
+ esac ;;
+ -proxy) shift;
+ case "$1" in
+ *:*) method="proxy:${1%%:*}"; addropts="proxyport=${1#*:}" ;;
+ *) method="proxy:$1" ;;
+ esac ;;
+ -user) shift; user="$1" ;;
+ -passwd) shift; passwd="$1" ;;
+ -t) set -vx ;;
+ -d) SO1="$SO1 -d" ;;
+ -D) SO2="$SO2 -d" ;;
+ -b) SO2="$SO2 -b $2"; shift ;;
+ -v) SO1="$SO1 -v" ;;
+ -l*) SO1="$SO1 $1"; SO2="$SO2 $1" ;;
+ -*) echo "unknown option \"$1\"" >&2; exit 1;;
+ *) break ;;
+ esac
+ shift
+done
+export SO2
+
+server="$1"
+dir="$2"
+
+echo "addr=$method:$server:21,$addropts"; exit
+
+### this is the central part to establish communication with socat ###
+### copy these lines to make new communication shell scripts
+TMPDIR=$(if [ -x /bin/mktemp ]; then
+ /bin/mktemp -d /tmp/$USER/FTPSH.XXXXXX
+ else
+ (umask 077; d=/tmp/$USER/FTPSH.$$; mkdir $d; echo $d)
+ fi)
+TO="$TMPDIR/to"; FROM="$TMPDIR/from"
+socat $SO1 fifo:$TO,nonblock,ignoreeof!!fifo:$FROM $method:$server:21,$addropts &
+S1=$!
+while ! [ -p "$TO" -a -p "$FROM" ]; do sleep 1; done
+exec 4>$TMPDIR/to 3<$TMPDIR/from
+trap "S1=" 17
+#trap "echo cleaning up...>&2; rm -r $TMPDIR; [ -n "$S1" ] && kill $S1" 0 3
+trap "rm -r $TMPDIR" 0 3
+### here the central part ends
+
+
+# this function waits for a complete server message, checks if its status
+# is in the permitted range (terminates session if not), and returns.
+ftp_chat () {
+ local cmd="$1"
+ local errlevel="$2"; [ -z "$errlevel" ] && errlevel=300
+ if [ -n "$cmd" ]; then echo "$cmd" >&4; fi
+ while read status message <&3;
+ ( case "$status" in [0-9][0-9][0-9]-*) exit 0;; [0-9][0-9][0-9]*) exit 1;; *) exit 1;; esac )
+ do :; done
+ #echo "got \"$status $message\"" >&2
+ if [ -z "$status" ]; then echo ftp data connection failed >&2; exit; fi
+ if [ "$status" -ge "$errlevel" ]; then
+ echo $message >&2
+ echo "QUIT" >&4; exit 1
+ fi
+set +vx
+}
+
+
+# wait for server greeting
+ftp_chat
+
+ftp_chat "USER $user" 400
+
+ftp_chat "PASS $passwd"
+
+#ftp_chat "CWD $dir"
+
+case "$dir" in
+*/) ftp_chat "TYPE A" ;;
+*) ftp_chat "TYPE I" ;;
+esac
+
+echo "PASV" >&4; read status message <&3
+info=$(expr "$message" : '.*[^0-9]\([0-9]*,[0-9]*,[0-9]*,[0-9]*,[0-9]*,[0-9]*\).*')
+echo $info |tr ',' ' ' |(read i1 i2 i3 i4 p1 p2
+
+ addr=$i1.$i2.$i3.$i4
+ port=$(echo "256*$p1+$p2" |bc)
+ #echo $addr:$port
+
+ trap : 20
+ # open data connection and transfer data
+ socat -u $SO2 $method:$server:$port,$addropts -
+) &
+S2=$!
+
+case "$dir" in
+*/) ftp_chat "NLST $dir" ;;
+#*/) ftp_chat "LIST $dir" ;;
+*) ftp_chat "RETR $dir" ;;
+esac
+case "$status" in
+ [45]*) kill $S2;;
+esac
+
+#echo "waiting for process $S2 to terminate" >&2
+wait $S2
+
+ftp_chat
+
+ftp_chat "QUIT"
+
+#echo "waiting for process $S1 to terminate" >&2
+wait $S1
+exit
diff --git a/gatherinfo.sh b/gatherinfo.sh
new file mode 100755
index 0000000..18083bd
--- /dev/null
+++ b/gatherinfo.sh
@@ -0,0 +1,172 @@
+#! /bin/sh
+# $Id: gatherinfo.sh,v 1.12 2007/03/06 21:01:07 gerhard Exp $
+# Copyright Gerhard Rieger 2001, 2002
+# Published under the GNU General Public License V.2, see file COPYING
+
+#set -vx
+
+# use this script after successful porting
+# provide the platform name as argument with no dots, e.g. HPUX-11-0
+# it generates the files:
+# Config/Makefile.PLATFORM
+# Config/config.PLATFORM.h
+# Config/socat.PLATFORM.out
+#
+# Config/config.PLATFORM.log
+# Config/compile.PLATFORM.log
+# Config/test.PLATFORM.log
+
+VERBOSE=
+LOGGING=
+INTERACTIVE=
+CONFOPTS=
+PLATFORM=
+OUTPUT='>/dev/null'
+
+# how to echo special characters?
+if [ `echo "x\c"` = "x" ]; then E=""
+elif [ `echo -e "x\c"` = "x" ]; then E="-e"
+fi
+
+while [ -n "$1" ]; do
+ case "$1" in
+ -v) VERBOSE=1; shift;; # tell about progress
+ -d) LOGGING=1; shift;; # show complete output
+ -i) INTERACTIVE=1; shift;; # diff and ask before overriding old files
+ -*) CONFOPTS="$CONFOPTS $1"; shift;;
+ *) PLATFORM="$1"; break;;
+ esac
+done
+
+#if [ -z "$PLATFORM" ]; then
+# echo "please specify a configuration name, e.g. `uname -s`-`uname -r|tr '.' '-'`!" >&2; exit 1;
+#fi
+
+if [ $# -eq 0 ]; then
+ echo $E "usage: $0 [-v] [-i] [configure options ...] platform" >&2
+ echo $E "\t-v\t\tverbose (print actual command)" >&2
+ echo $E "\t-d\t\tdump command outputs" >&2
+ echo $E "\t-i\t\tinteractive (ask before overwriting something)" >&2
+ echo $E "\tconfigure options\toptions for configure script, e.g. --disable-ip6" >&2
+ echo $E "\tplatform\tdescribe your OS, e.g. `uname -s`-`uname -r|tr '.' '-'`" >&2
+ exit 1
+fi
+
+case "$PLATFORM" in
+*.*) echo "platform name must not contain '.'" >&2; exit 1;;
+esac
+
+
+# now, lets begin!
+
+if [ -f Makefile ]; then
+ COMMAND="make distclean"
+ [ "$VERBOSE" ] && echo "$COMMAND"
+ $COMMAND >/dev/null 2>&1 || echo "*** failed: $COMMAND" 1>&2
+fi
+
+# implicitly generates Makefile, config.h, config.log
+COMMAND="./configure $CONFOPTS"
+LOGFILE="compile.log"
+[ "$VERBOSE" ] && echo "$COMMAND"
+if [ "$LOGGING" ]; then
+ { $COMMAND; echo "$?" >socat.rc; } 2>&1 |tee $LOGFILE;
+ if [ `cat socat.rc` -ne 0 ]; then echo "*** failed: $COMMAND" 1>&2; exit 1; fi
+else
+ $COMMAND >$LOGFILE 2>&1 || { echo "*** failed: $COMMAND" 1>&2; exit 1; }
+fi
+
+COMMAND="make -k"
+LOGFILE="compile.log"
+[ "$VERBOSE" ] && echo "$COMMAND"
+if [ "$LOGGING" ]; then
+ { $COMMAND; echo "$?" >socat.rc; } 2>&1 |tee -a $LOGFILE;
+ if [ `cat socat.rc` -ne 0 ]; then echo "*** failed: $COMMAND" 1>&2; exit 1; fi
+else
+ $COMMAND >>$LOGFILE 2>&1 || { echo "*** failed: $COMMAND" 1>&2; exit 1; }
+fi
+
+# generates socat.out
+COMMAND="make info"
+[ "$VERBOSE" ] && echo "$COMMAND"
+$COMMAND >/dev/null || echo "*** failed: $COMMAND" 1>&2
+
+COMMAND="./test.sh"
+LOGFILE="test.log"
+[ "$VERBOSE" ] && echo "$COMMAND"
+if [ "$LOGGING" ]; then
+ { $COMMAND; echo "$?" >socat.rc; } 2>&1 |tee $LOGFILE;
+ if [ `cat socat.rc` -ne 0 ]; then
+ echo "*** failed: $COMMAND" 1>&2
+ if [ `cat socat.rc` -ge 128 ]; then
+ exit 1
+ fi
+ fi
+else
+ $COMMAND >$LOGFILE 2>&1 || echo "*** failed: $COMMAND" 1>&2
+fi
+
+FILES=
+
+b=Makefile; e=; f=$b; p=Config/$b.$PLATFORM
+if [ "$INTERACTIVE" -a -f $p ]; then
+ if ! diff $p $f; then
+ cp -pi $f $p
+ fi
+else
+ cp -p $f $p
+fi
+FILES="$p"
+
+b=config; e=h; f=$b.$e; p=Config/$b.$PLATFORM.$e
+if [ "$INTERACTIVE" -a -f $p ]; then
+ if ! diff $p $f; then
+ cp -pi $f $p
+ fi
+else
+ cp -p $f $p
+fi
+FILES="$FILES $p"
+
+b=socat; e=out; f=$b.$e; p=Config/$b.$PLATFORM.$e
+if [ "$INTERACTIVE" -a -f $p ]; then
+ if ! diff $p $f; then
+ cp -pi $f $p
+ fi
+else
+ cp -p $f $p
+fi
+FILES="$FILES $p"
+
+b=config; e=log; f=$b.$e; p=Config/$b.$PLATFORM.$e
+if [ "$INTERACTIVE" -a -f $p ]; then
+ if ! diff $p $f; then
+ cp -pi $f $p
+ fi
+else
+ cp -p $f $p
+fi
+FILES="$FILES $p"
+
+b=compile; e=log; f=$b.$e; p=Config/$b.$PLATFORM.$e
+if [ "$INTERACTIVE" -a -f $p ]; then
+ if ! diff $p $f; then
+ cp -pi $f $p
+ fi
+else
+ cp -p $f $p
+fi
+FILES="$FILES $p"
+
+b=test; e=log; f=$b.$e; p=Config/$b.$PLATFORM.$e
+if [ "$INTERACTIVE" -a -f $p ]; then
+ if ! diff $p $f; then
+ cp -pi $f $p
+ fi
+else
+ cp -p $f $p
+fi
+FILES="$FILES $p"
+
+echo "output files:"
+echo "$FILES"
diff --git a/hostan.c b/hostan.c
new file mode 100644
index 0000000..75501e0
--- /dev/null
+++ b/hostan.c
@@ -0,0 +1,82 @@
+/* $Id: hostan.c,v 1.2 2007/03/06 21:02:01 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2006-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* the subroutine hostan makes a "HOST ANalysis". It gathers information
+ about the host environment it is running in without modifying its state
+ (almost).
+ */
+
+#include "xiosysincludes.h"
+#include "mytypes.h"
+#include "compat.h"
+#include "error.h"
+#include "sycls.h"
+#include "sysutils.h"
+#include "filan.h"
+
+#include "hostan.h"
+
+static int iffan(FILE *outfile);
+
+int hostan(FILE *outfile) {
+#if WITH_SOCKET
+ iffan(outfile);
+#endif
+ return 0;
+}
+
+#if WITH_SOCKET
+static int iffan(FILE *outfile) {
+ /* Linux: man 7 netdevice */
+ /* FreeBSD: 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;
+ unsigned char buff[IFBUFSIZ];
+ struct ifconf ic;
+ int i;
+
+ if ((s = Socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
+ Error1("socket(PF_INET, SOCK_DGRAM, IPPROTO_IP): %s", strerror(errno));
+ return -1;
+ }
+
+ for (i=0; i < IFBUFSIZ; ++i) {
+ buff[i] = 255;
+ }
+ ic.ifc_len = sizeof(buff);
+ ic.ifc_ifcu.ifcu_buf = (caddr_t)buff;
+ if (Ioctl(s, SIOCGIFCONF, &ic) < 0) {
+ Error3("ioctl(%d, SIOCGIFCONF, %p): %s", s, &ic, strerror(errno));
+ return -1;
+ }
+
+ for (i = 0; i < ic.ifc_len; i += sizeof(struct ifreq)) {
+ struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i);
+ struct ifreq ifr;
+
+ 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 */
+ }
+ Close(s);
+#endif /* defined(SIOCGIFCONF) */
+#endif /* defined(SIOCGIFINDEX) */
+ return 0;
+}
+#endif /* WITH_SOCKET */
diff --git a/hostan.h b/hostan.h
new file mode 100644
index 0000000..ab9b8e0
--- /dev/null
+++ b/hostan.h
@@ -0,0 +1,10 @@
+/* $Id: hostan.h,v 1.1 2006/12/31 17:49:25 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __hostan_h_included
+#define __hostan_h_included 1
+
+extern int hostan(FILE *outfile);
+
+#endif /* !defined(__hostan_h_included) */
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..ebc6691
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/mail.sh b/mail.sh
new file mode 100755
index 0000000..669ac75
--- /dev/null
+++ b/mail.sh
@@ -0,0 +1,71 @@
+#! /bin/sh
+# $Id: mail.sh,v 1.11 2005/09/10 16:48:38 gerhard Exp $
+# Copyright Gerhard Rieger 2001-2005
+# Published under the GNU General Public License V.2, see file COPYING
+
+#set -vx
+
+# This is an example for a shell script that can be fed to socat with exec.
+# Its clue is that it does not use stdin/stdout for communication with socat,
+# so you may feed the mail message via stdin to the script. The message should
+# contain appropriate mail headers.
+# Lines with only a dot are not permitted - use two dots as escape.
+# This script supports multiline answers from server, but not much more yet.
+
+# Usage: cat message.txt |socat exec:"mail.sh target@domain.com",fdin=3,fdout=4 tcp:mail.relay.org:25,crlf
+
+while [ "$1" ]; do
+ case "$1" in
+ -f) shift; mailfrom="$1"; shift;;
+ *) break;;
+ esac
+done
+
+rcptto="$1"
+[ -z "$1" ] && rcptto="root@loopback"
+#server=$(expr "$rcptto" : '[^@]*@\(.*\)')
+[ -z "$mailfrom" ] && mailfrom="$USER@$(hostname)"
+
+# this function waits for a complete server message, checks if its status
+# is in the permitted range (terminates session if not), and returns.
+mail_chat () {
+ local cmd="$1"
+ local errlevel="$2"; [ -z "$errlevel" ] && errlevel=300
+
+ if [ "$cmd" ]; then echo "> $cmd" >&2; fi
+ if [ -n "$cmd" ]; then echo "$cmd" >&4; fi
+ while read status message <&3;
+ (
+ case "$status" in
+ [0-9][0-9][0-9]-*) exit 0;;
+ [0-9][0-9][0-9]*) exit 1;;
+ *) exit 1;;
+ esac
+ )
+ do :; done
+ if [ -z "$status" ]; then echo smtp connection failed >&2; exit; fi
+ echo "< $status $message" >&2
+ if [ "$status" -ge "$errlevel" ]; then
+ echo $message >&2
+ echo "QUIT" >&4; exit 1
+ fi
+}
+
+
+# expect server greeting
+mail_chat
+
+mail_chat "HELO $(hostname)"
+
+mail_chat "MAIL FROM: $mailfrom"
+
+mail_chat "RCPT TO: $rcptto"
+
+mail_chat "DATA" 400
+
+while read l; do echo "$l" >&4; done
+mail_chat "."
+
+mail_chat "QUIT"
+
+exit 0
diff --git a/mytypes.h b/mytypes.h
new file mode 100644
index 0000000..f96eaa2
--- /dev/null
+++ b/mytypes.h
@@ -0,0 +1,17 @@
+/* $Id: mytypes.h,v 1.4 2006/05/06 14:15:47 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __mytypes_h_included
+#define __mytypes_h_included 1
+
+/* some types and macros I miss in C89 */
+
+typedef enum { false, true } bool;
+
+#define Min(x,y) ((x)<=(y)?(x):(y))
+#define Max(x,y) ((x)>=(y)?(x):(y))
+
+#define SOCKADDR_MAX UNIX_PATH_MAX
+
+#endif /* __mytypes_h_included */
diff --git a/nestlex.c b/nestlex.c
new file mode 100644
index 0000000..a9099ef
--- /dev/null
+++ b/nestlex.c
@@ -0,0 +1,237 @@
+/* $Id: nestlex.c,v 1.4 2006/06/23 17:04:36 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* a function for lexical scanning of nested character patterns */
+
+#include "config.h"
+#include "mytypes.h"
+
+#include "sysincludes.h"
+
+
+/* sub: scan a string and copy its value to output string
+ end scanning when an unescaped, unnested string from ends array is found
+ does not copy the end pattern
+ does not write a trailing \0 to token
+ allows escaping with \ and quoting (\ and quotes are removed)
+ allows nesting with div. parens
+ returns -1 if out string was too small
+ returns 1 if addr ended unexpectedly
+ returns 0 if token could be extracted successfully
+*/
+int nestlex(const char **addr, /* input string; aft points to end token */
+ char **token, /* output token; aft points to first unwritten
+ char (caller might want to set it to \0) */
+ size_t *len, /* remaining bytes in token space (incl. \0) */
+ const char *ends[], /* list of end strings */
+ const char *hquotes[],/* list of strings that quote (hard qu.) */
+ const char *squotes[],/* list of strings that quote softly */
+ const char *nests[],/* list of strings that start nesting;
+ every second one is matching end */
+ bool dropquotes, /* drop the outermost quotes */
+ bool c_esc, /* solve C char escapes: \n \t \0 etc */
+ bool html_esc /* solve HTML char escapes: %0d %08 etc */
+ ) {
+ const char *in = *addr; /* pointer into input string */
+ const char **endx; /* loops over end patterns */
+ const char **quotx; /* loops over quote patterns */
+ const char **nestx; /* loops over nest patterns */
+ char *out = *token; /* pointer into output token */
+ char c;
+ int i;
+ int result;
+
+ while (true) {
+
+ /* is this end of input string? */
+ if (*in == 0) {
+
+ break; /* end of string */
+ }
+
+ /* first check the end patterns (e.g. for ']') */
+ endx = ends; i = 0;
+ while (*endx) {
+ if (!strncmp(in, *endx, strlen(*endx))) {
+ /* this end pattern matches */
+ *addr = in;
+ *token = out;
+ return 0;
+ }
+ ++endx;
+ }
+
+ /* check for hard quoting pattern */
+ quotx = hquotes;
+ while (hquotes && *quotx) {
+ if (!strncmp(in, *quotx, strlen(*quotx))) {
+ /* this quote pattern matches */
+ const char *endnest[2];
+ if (dropquotes) {
+ /* we strip this quote */
+ in += strlen(*quotx);
+ } else {
+ for (i = strlen(*quotx); i > 0; --i) {
+ *out++ = *in++;
+ if (--*len <= 0) { *addr = in; *token = out; return -1; }
+ }
+ }
+ /* we call nestlex recursively */
+ endnest[0] = *quotx;
+ endnest[1] = NULL;
+ result =
+ nestlex(&in, &out, len, endnest, NULL/*hquotes*/,
+ NULL/*squotes*/, NULL/*nests*/,
+ false, c_esc, html_esc);
+ if (result == 0 && dropquotes) {
+ /* we strip this quote */
+ in += strlen(*quotx);
+ } else {
+ /* we copy the trailing quote */
+ for (i = strlen(*quotx); i > 0; --i) {
+ *out++ = *in++;
+ if (--*len <= 0) { *addr = in; *token = out; return -1; }
+ }
+ }
+
+ break;
+ }
+ ++quotx;
+ }
+ if (hquotes && *quotx != NULL) {
+ /* there was a quote; string might continue with hard quote */
+ continue;
+ }
+
+ /* check for soft quoting pattern */
+ quotx = squotes;
+ while (squotes && *quotx) {
+ if (!strncmp(in, *quotx, strlen(*quotx))) {
+ /* this quote pattern matches */
+ /* we strip this quote */
+ /* we call nestlex recursively */
+ const char *endnest[2];
+ if (dropquotes) {
+ /* we strip this quote */
+ in += strlen(*quotx);
+ } else {
+ for (i = strlen(*quotx); i > 0; --i) {
+ *out++ = *in++;
+ if (--*len <= 0) { *addr = in; *token = out; return -1; }
+ }
+ }
+ endnest[0] = *quotx;
+ endnest[1] = NULL;
+ result =
+ nestlex(&in, &out, len, endnest, hquotes,
+ squotes, nests,
+ false, c_esc, html_esc);
+
+ if (result == 0 && dropquotes) {
+ /* we strip the trailing quote */
+ in += strlen(*quotx);
+ } else {
+ /* we copy the trailing quote */
+ for (i = strlen(*quotx); i > 0; --i) {
+ *out++ = *in++;
+ if (--*len <= 0) { *addr = in; *token = out; return -1; }
+ }
+ }
+ break;
+ }
+ ++quotx;
+ }
+ if (squotes && *quotx != NULL) {
+ /* there was a soft quote; string might continue with any quote */
+ continue;
+ }
+
+ /* check patterns that start a nested clause */
+ nestx = nests; i = 0;
+ while (nests && *nestx) {
+ if (!strncmp(in, *nestx, strlen(*nestx))) {
+ /* this nest pattern matches */
+ const char *endnest[2];
+ endnest[0] = nestx[1];
+ endnest[1] = NULL;
+
+ for (i = strlen(nestx[1]); i > 0; --i) {
+ *out++ = *in++;
+ if (--*len <= 0) { *addr = in; *token = out; return -1; }
+ }
+
+ result =
+ nestlex(&in, &out, len, endnest, hquotes, squotes, nests,
+ false, c_esc, html_esc);
+ if (result == 0) {
+ /* copy endnest */
+ i = strlen(nestx[1]); while (i > 0) {
+ *out++ = *in++;
+ if (--*len <= 0) {
+ *addr = in;
+ *token = out;
+ return -1;
+ }
+ --i;
+ }
+ }
+ break;
+ }
+ nestx += 2; /* skip matching end pattern in table */
+ }
+ if (nests && *nestx) {
+ /* we handled a nested expression, continue loop */
+ continue;
+ }
+
+ /* "normal" data, possibly escaped */
+ c = *in++;
+ if (c == '\\') {
+ /* found a plain \ escaped part */
+ c = *in++;
+ if (c == 0) { /* Warn("trailing '\\'");*/ break; }
+ if (c_esc) { /* solve C char escapes: \n \t \0 etc */
+ switch (c) {
+ case '0': c = '\0'; break;
+ case 'a': c = '\a'; break;
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+#if LATER
+ case 'x': !!! 1 to 2 hex digits; break;
+ case 'u': !!! 4 hex digits?; break;
+ case 'U': !!! 8 hex digits?; break;
+#endif
+ default: break;
+ }
+ }
+ *out++ = c;
+ --*len;
+ if (len == 0) {
+ *addr = in;
+ *token = out;
+ return -1; /* output overflow */
+ }
+ continue;
+ }
+
+ /* just a simple char */
+ *out++ = c;
+ --*len;
+ if (len == 0) {
+ *addr = in;
+ *token = out;
+ return -1; /* output overflow */
+ }
+
+ }
+ /* never come here? */
+
+ *addr = in;
+ *token = out;
+ return 0; /* OK */
+}
diff --git a/nestlex.h b/nestlex.h
new file mode 100644
index 0000000..af0828a
--- /dev/null
+++ b/nestlex.h
@@ -0,0 +1,23 @@
+/* $Id: nestlex.h,v 1.3 2006/06/23 17:04:39 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __nestlex_h_included
+#define __nestlex_h_included 1
+
+extern
+int nestlex(const char **addr, /* input string; aft points to end token */
+ char **token, /* output token; aft points to first unwritten
+ char (caller might want to set it to \0) */
+ size_t *len, /* remaining bytes in token space (incl. \0) */
+ const char *ends[], /* list of end strings */
+ const char *hquotes[],/* list of strings that quote (hard qu.) */
+ const char *squotes[],/* list of strings that quote softly */
+ const char *nests[],/* list of strings that start nesting;
+ every second one is matching end */
+ bool dropquotes, /* drop the outermost quotes */
+ bool c_esc, /* solve C char escapes: \n \t \0 etc */
+ bool html_esc /* solve HTML char escapes: %0d %08 etc */
+ );
+
+#endif /* !defined(__nestlex_h_included) */
diff --git a/procan.c b/procan.c
new file mode 100644
index 0000000..b25efee
--- /dev/null
+++ b/procan.c
@@ -0,0 +1,169 @@
+/* $Id: procan.c,v 1.17 2006/12/28 07:25:01 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* the subroutine procan makes a "PROCess ANalysis". It gathers information
+ about the process environment it is running in without modifying its state
+ (almost).
+ */
+
+#include "xiosysincludes.h"
+#include "mytypes.h"
+#include "compat.h"
+#include "error.h"
+#include "sycls.h"
+#include "sysutils.h"
+#include "filan.h"
+
+#include <sys/resource.h>
+
+#include "procan.h"
+
+/* dirty workaround so we dont get an error on AIX when getting linked with
+ libwrap */
+int allow_severity, deny_severity;
+
+
+int procan(FILE *outfile) {
+
+ /*filan(0, outfile);*/
+
+ /* controlling terminal */
+ fprintf(outfile, "process id = "F_pid"\n", Getpid());
+ fprintf(outfile, "process parent id = "F_pid"\n", Getppid());
+ {
+ int fd;
+ if ((fd = Open("/dev/tty", O_NOCTTY, 0)) < 0) {
+ fprintf(outfile, "controlling terminal: -\n");
+ } else {
+#if 1
+ fprintf(outfile, "controlling terminal: \"%s\"\n", Ttyname(fd));
+#else
+ char procpath[PATH_MAX], devpath[PATH_MAX+1];
+ int devlen;
+ sprintf(procpath, "/proc/"F_pid"/fd/%d", Getpid(), 0 /*! fd*/);
+ if ((devlen = Readlink(procpath, devpath, sizeof(devpath))) < 0) {
+ ;
+ } else {
+ devpath[devlen] = '\0';
+ fprintf(outfile, "controlling terminal: \"%s\"\n", devpath);
+ }
+#endif
+ }
+ }
+ fprintf(outfile, "process group id = "F_pid"\n", Getpgrp());
+#if HAVE_GETSID
+ fprintf(outfile, "process session id = "F_pid"\n", Getsid(0));
+#endif
+ fprintf(outfile, "process group id if fg process / stdin = "F_pid"\n", Tcgetpgrp(0));
+ fprintf(outfile, "process group id if fg process / stdout = "F_pid"\n", Tcgetpgrp(1));
+ fprintf(outfile, "process group id if fg process / stderr = "F_pid"\n", Tcgetpgrp(2));
+ {
+ int fd;
+ if ((fd = Open("/dev/tty", O_RDWR, 0600)) >= 0) {
+ fprintf(outfile, "process has a controlling terminal\n");
+ Close(fd);
+ } else {
+ fprintf(outfile, "process does not have a controlling terminal\n");
+ }
+ }
+
+ /* process owner, groups */
+ fprintf(outfile, "user id = "F_uid"\n", Getuid());
+ fprintf(outfile, "effective user id = "F_uid"\n", Geteuid());
+ fprintf(outfile, "group id = "F_gid"\n", Getgid());
+ fprintf(outfile, "effective group id = "F_gid"\n", Getegid());
+
+ {
+ struct rlimit rlim;
+
+ fprintf(outfile, "\nRESOURCE LIMITS\n");
+ fprintf(outfile, "resource current maximum\n");
+ if (getrlimit(RLIMIT_CPU, &rlim) < 0) {
+ Warn2("getrlimit(RLIMIT_CPU, %p): %s", &rlim, strerror(errno));
+ } else {
+ fprintf(outfile,
+ "cpu time (seconds) %16"F_rlim_max"%16"F_rlim_max"\n",
+ rlim.rlim_cur, rlim.rlim_max);
+ }
+ if (getrlimit(RLIMIT_FSIZE, &rlim) < 0) {
+ Warn2("getrlimit(RLIMIT_FSIZE, %p): %s", &rlim, strerror(errno));
+ } else {
+ fprintf(outfile,
+ "file size (blocks) %16"F_rlim_max"%16"F_rlim_max"\n",
+ rlim.rlim_cur, rlim.rlim_max);
+ }
+ if (getrlimit(RLIMIT_DATA, &rlim) < 0) {
+ Warn2("getrlimit(RLIMIT_DATA, %p): %s", &rlim, strerror(errno));
+ } else {
+ fprintf(outfile,
+ "data seg size (kbytes) %16"F_rlim_max"%16"F_rlim_max"\n",
+ rlim.rlim_cur, rlim.rlim_max);
+ }
+ if (getrlimit(RLIMIT_STACK, &rlim) < 0) {
+ Warn2("getrlimit(RLIMIT_STACK, %p): %s", &rlim, strerror(errno));
+ } else {
+ fprintf(outfile,
+ "stack size (blocks) %16"F_rlim_max"%16"F_rlim_max"\n",
+ rlim.rlim_cur, rlim.rlim_max);
+ }
+ if (getrlimit(RLIMIT_CORE, &rlim) < 0) {
+ Warn2("getrlimit(RLIMIT_CORE, %p): %s", &rlim, strerror(errno));
+ } else {
+ fprintf(outfile,
+ "core file size (blocks) %16"F_rlim_max"%16"F_rlim_max"\n",
+ rlim.rlim_cur, rlim.rlim_max);
+ }
+#ifdef RLIMIT_RSS /* Linux, AIX; not Cygwin */
+ if (getrlimit(RLIMIT_RSS, &rlim) < 0) {
+ Warn2("getrlimit(RLIMIT_RSS, %p): %s", &rlim, strerror(errno));
+ } else {
+ fprintf(outfile,
+ "max resident set size %16"F_rlim_max"%16"F_rlim_max"\n",
+ rlim.rlim_cur, rlim.rlim_max);
+ }
+#endif
+#ifdef RLIMIT_NPROC /* Linux, not AIX, Cygwin */
+ if (getrlimit(RLIMIT_NPROC, &rlim) < 0) {
+ Warn2("getrlimit(RLIMIT_NPROC, %p): %s", &rlim, strerror(errno));
+ } else {
+ fprintf(outfile,
+ "max user processes %16"F_rlim_max"%16"F_rlim_max"\n",
+ rlim.rlim_cur, rlim.rlim_max);
+ }
+#endif
+#ifdef RLIMIT_NOFILE /* not AIX 4.1 */
+ if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
+ Warn2("getrlimit(RLIMIT_NOFILE, %p): %s", &rlim, strerror(errno));
+ } else {
+ fprintf(outfile,
+ "open files %16"F_rlim_max"%16"F_rlim_max"\n",
+ rlim.rlim_cur, rlim.rlim_max);
+ }
+#endif
+#ifdef RLIMIT_MEMLOCK /* Linux, not AIX, Cygwin */
+ if (getrlimit(RLIMIT_MEMLOCK, &rlim) < 0) {
+ Warn2("getrlimit(RLIMIT_MEMLOCK, %p): %s", &rlim, strerror(errno));
+ } else {
+ fprintf(outfile,
+ "max locked-in-memory address space %16"F_rlim_max"%16"F_rlim_max"\n",
+ rlim.rlim_cur, rlim.rlim_max);
+ }
+#endif
+#ifdef RLIMIT_AS
+ if (getrlimit(RLIMIT_AS, &rlim) < 0) {
+ Warn2("getrlimit(RLIMIT_AS, %p): %s", &rlim, strerror(errno));
+ } else {
+ fprintf(outfile,
+ "virtual memory (kbytes) %16"F_rlim_max"%16"F_rlim_max"\n",
+ rlim.rlim_cur, rlim.rlim_max);
+ }
+#endif
+ }
+
+ /* file descriptors */
+
+ /* what was this for?? */
+ /*Sleep(1);*/
+ return 0;
+}
diff --git a/procan.h b/procan.h
new file mode 100644
index 0000000..0825c54
--- /dev/null
+++ b/procan.h
@@ -0,0 +1,10 @@
+/* $Id: procan.h,v 1.2 2001/06/30 14:02:39 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __procan_h_included
+#define __procan_h_included 1
+
+extern int procan(FILE *outfile);
+
+#endif /* !defined(__procan_h_included) */
diff --git a/procan_main.c b/procan_main.c
new file mode 100644
index 0000000..b368ac1
--- /dev/null
+++ b/procan_main.c
@@ -0,0 +1,94 @@
+/* $Id: procan_main.c,v 1.13 2007/03/06 21:19:18 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+const char copyright[] = "procan by Gerhard Rieger - send bug reports to socat@dest-unreach.org";
+
+#include <stdlib.h> /* strtoul() */
+#include <string.h>
+#include <stdio.h>
+#include "mytypes.h"
+#include "error.h"
+#include "procan.h"
+#include "hostan.h"
+
+
+#define WITH_HELP 1
+
+static void procan_usage(FILE *fd);
+
+
+int main(int argc, const char *argv[]) {
+ const char **arg1;
+#if 0
+ unsigned int n = 1024; /* this is default on my Linux */
+#endif
+
+ diag_set('p', strchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
+
+ arg1 = argv+1; --argc;
+ while (arg1[0] && (arg1[0][0] == '-')) {
+ switch (arg1[0][1]) {
+#if WITH_HELP
+ case '?': case 'h': procan_usage(stdout); exit(0);
+#endif /* WITH_HELP */
+#if LATER
+ case 'V': procan_version(stdout); exit(0);
+ case 'l': diag_set(arg1[0][2], &arg1[0][3]); break;
+ case 'd': diag_set('d', NULL); break;
+#endif
+#if 0
+ case 'n': n = strtoul(&arg1[0][2], NULL, 0); break;
+#endif
+ case '\0': break;
+ default:
+ diag_set_int('e', E_FATAL);
+ Error1("unknown option \"%s\"", arg1[0]);
+#if WITH_HELP
+ procan_usage(stderr);
+#endif
+ exit(1);
+ }
+ if (arg1[0][1] == '\0')
+ break;
+ ++arg1; --argc;
+ }
+ if (argc != 0) {
+ Error1("%d superfluous arguments", argc);
+#if WITH_HELP
+ procan_usage(stderr);
+#endif
+ exit(1);
+ }
+ procan(stdout);
+ hostan(stdout);
+ return 0;
+}
+
+
+#if WITH_HELP
+static void procan_usage(FILE *fd) {
+ fputs(copyright, fd); fputc('\n', fd);
+ fputs("Analyze system parameters of process\n", fd);
+ fputs("Usage:\n", fd);
+ fputs("procan [options]\n", fd);
+ fputs(" options:\n", fd);
+#if LATER
+ fputs(" -V print version information to stdout, and exit\n", fd);
+#endif
+#if WITH_HELP
+ fputs(" -?|-h print a help text describing command line options\n", fd);
+#endif
+#if LATER
+ fputs(" -d increase verbosity (use up to 4 times; 2 are recommended)\n", fd);
+#endif
+#if 0
+ fputs(" -ly[facility] log to syslog, using facility (default is daemon)\n", fd);
+ fputs(" -lf<logfile> log to file\n", fd);
+ fputs(" -ls log to stderr (default if no other log)\n", fd);
+#endif
+#if 0
+ fputs(" -n<fdnum> first file descriptor number not analyzed\n", fd);
+#endif
+}
+#endif /* WITH_HELP */
diff --git a/proxy.sh b/proxy.sh
new file mode 100755
index 0000000..e4da38c
--- /dev/null
+++ b/proxy.sh
@@ -0,0 +1,76 @@
+#! /bin/bash
+# $Id: proxy.sh,v 1.3 2004/07/11 07:55:57 gerhard Exp $
+# Copyright Gerhard Rieger 2003-2004
+# Published under the GNU General Public License V.2, see file COPYING
+
+# perform primitive simulation of a proxy server.
+# accepts and answers correct HTTP CONNECT requests on stdio, and tries to
+# establish the connection to the given server.
+# it is required for socats test.sh
+# for TCP, use this script as:
+# socat tcp-l:8080,reuseaddr,fork exec:"proxy.sh",nofork
+
+if [ -z "$SOCAT" ]; then
+ if type socat >/dev/null 2>&1; then
+ SOCAT=socat
+ else
+ SOCAT="./socat"
+ fi
+fi
+
+if [ $(echo "x\c") = "x" ]; then E=""
+elif [ $(echo -e "x\c") = "x" ]; then E="-e"
+else
+ echo "cannot suppress trailing newline on echo" >&2
+ exit 1
+fi
+ECHO="echo $E"
+CR=$($ECHO "\r")
+#echo "CR=$($ECHO "$CR\c" |od -c)" >&2
+
+case `uname` in
+HP-UX|OSF1)
+ # their cats are too stupid to work with unix domain sockets
+ CAT="$SOCAT -u stdin stdout"
+ ;;
+*)
+ CAT=cat
+ ;;
+esac
+
+SPACES=" "
+while [ -n "$1" ]; do
+ case "$1" in
+ -w) n="$2"; while [ "$n" -gt 0 ]; do SPACES="$SPACES "; n=$((n-1)); done
+ shift ;;
+ #-s) STAT="$2"; shift ;;
+ esac
+ shift
+done
+
+# read and parse HTTP request
+read l
+if echo "$l" |egrep '^CONNECT +[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+ +HTTP/1.[01]' >/dev/null
+then
+ : go on below
+else
+ $ECHO "HTTP/1.0${SPACES}500 Bad Request$CR"
+ $ECHO "$CR"
+ exit
+fi
+
+# extract target server name/address
+s=`echo $l |awk '{print($2);}'`
+
+# read more headers until empty line
+while [ "$l" != "$CR" ]; do
+ read l
+done
+
+# send status
+$ECHO "HTTP/1.0${SPACES}200 OK$CR"
+# send empty line
+$ECHO "$CR"
+
+# perform proxy (relay) function
+exec $SOCAT $SOCAT_OPTS - tcp:$s
diff --git a/proxyecho.sh b/proxyecho.sh
new file mode 100755
index 0000000..545fe68
--- /dev/null
+++ b/proxyecho.sh
@@ -0,0 +1,59 @@
+#! /bin/bash
+# $Id: proxyecho.sh,v 1.5 2004/06/06 17:33:22 gerhard Exp $
+# Copyright Gerhard Rieger 2003
+# Published under the GNU General Public License V.2, see file COPYING
+
+# perform primitive simulation of a proxy server with echo function via stdio.
+# accepts and answers correct HTTP CONNECT requests, but then just echoes data.
+# it is required for test.sh
+# for TCP, use this script as:
+# socat tcp-l:8080,reuseaddr,crlf system:"proxyecho.sh"
+
+if type socat >/dev/null 2>&1; then
+ SOCAT=socat
+else
+ SOCAT=./socat
+fi
+
+case `uname` in
+HP-UX|OSF1)
+ CAT="$SOCAT -u stdin stdout"
+ ;;
+*)
+ CAT=cat
+ ;;
+esac
+
+SPACES=" "
+while [ -n "$1" ]; do
+ case "$1" in
+ -w) n="$2"; while [ "$n" -gt 0 ]; do SPACES="$SPACES "; n=$((n-1)); done
+ shift ;;
+ #-s) STAT="$2"; shift ;;
+ esac
+ shift
+done
+
+# read and parse HTTP request
+read l
+if echo "$l" |egrep '^CONNECT +[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+ +HTTP/1.[01]$' >/dev/null
+then
+ : go on below
+else
+ echo "HTTP/1.0${SPACES}500 Bad Request"
+ echo
+ exit
+fi
+
+# read more headers until empty line
+while [ -n "$l" ]; do
+ read l
+done
+
+# send status
+echo "HTTP/1.0${SPACES}200 OK"
+# send empty line
+echo
+
+# perform echo function
+$CAT
diff --git a/readline-test.sh b/readline-test.sh
new file mode 100755
index 0000000..83c24a2
--- /dev/null
+++ b/readline-test.sh
@@ -0,0 +1,46 @@
+#! /bin/bash
+# $Id: readline-test.sh,v 1.1 2003/12/23 21:28:12 gerhard Exp $
+# Copyright Gerhard Rieger 2003
+# Published under the GNU General Public License V.2, see file COPYING
+
+# script that simulates a simple program with authentication.
+# is just for testing the readline features
+# perform the test with something like:
+# ./socat readline,history=$HOME/.history,noecho='^Password: ' system:./readline-test.sh,pty,setsid,ctty,stderr,sigint,sigquit,echo=0,raw
+
+
+BANNER='readline feature test program'
+USERPROMPT='Authentication required\nUsername: '
+PWDPROMPT='Password: '
+PROMPT='prog> '
+
+# degenerated user database
+CREDUSER="user"
+CREDPASS="password"
+
+if [ $(echo "x\c") = "x" ]; then ECHO="echo"
+elif [ $(echo -e "x\c") = "x" ]; then ECHO="echo -e"
+fi
+
+#trap "$ECHO $0 got SIGINT" INT
+trap "$ECHO $0 got SIGINT" INT
+trap "$ECHO $0 got SIGQUIT" QUIT
+
+# print banner
+$ECHO "$BANNER"
+
+read -r -p "$($ECHO "$USERPROMPT")" USERNAME
+read -rs -p "$PWDPROMPT" PASSWORD
+$ECHO
+
+if [ "$USERNAME" != "$CREDUSER" -o "$PASSWORD" != "$CREDPASS" ]; then
+ $ECHO "Authentication failed" >&2
+ exit -1
+fi
+
+while read -r -p "$PROMPT" COMMAND; do
+ if [ "$COMMAND" = "exit" ]; then
+ break;
+ fi
+ $ECHO "executing $COMMAND"
+done
diff --git a/readline.sh b/readline.sh
new file mode 100755
index 0000000..26cd1df
--- /dev/null
+++ b/readline.sh
@@ -0,0 +1,30 @@
+#! /bin/bash
+# $Id: readline.sh,v 1.3 2004/08/25 15:52:59 gerhard Exp $
+# Copyright Gerhard Rieger 2003-2004
+# Published under the GNU General Public License V.2, see file COPYING
+
+# this is an attempt for a socat based readline wrapper
+# usage: readline.sh <command>
+
+withhistfile=1
+
+while true; do
+ case "X$1" in
+ X-nh|X-nohist*) withhistfile=; shift; continue ;;
+ *) break;;
+ esac
+done
+
+PROGRAM="$@"
+if [ "$withhistfile" ]; then
+ HISTFILE="$HOME/.$1_history"
+ HISTOPT=",history=$HISTFILE"
+else
+ HISTOPT=
+fi
+mkdir -p /tmp/$USER || exit 1
+#
+#
+
+exec socat -d readline"$HISTOPT",noecho='[Pp]assword:' exec:"$PROGRAM",sigint,pty,setsid,ctty,raw,echo=0,stderr 2>/tmp/$USER/stderr2
+
diff --git a/socat.c b/socat.c
new file mode 100644
index 0000000..1231694
--- /dev/null
+++ b/socat.c
@@ -0,0 +1,1370 @@
+/* $Id: socat.c,v 1.111 2007/03/06 21:03:28 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this is the main source, including command line option parsing, general
+ control, and the data shuffler */
+
+#include "config.h"
+#include "xioconfig.h" /* what features are enabled */
+
+#include "sysincludes.h"
+
+#include "mytypes.h"
+#include "compat.h"
+#include "error.h"
+
+#include "sycls.h"
+#include "sysutils.h"
+#include "dalan.h"
+#include "filan.h"
+#include "xio.h"
+#include "xioopts.h"
+#include "xiolockfile.h"
+
+
+/* command line options */
+struct {
+ size_t bufsiz;
+ bool verbose;
+ bool verbhex;
+ struct timeval pollintv; /* with ignoreeof, reread after seconds */
+ struct timeval closwait; /* after close of x, die after seconds */
+ struct timeval total_timeout;/* when nothing happens, die after seconds */
+ bool debug;
+ bool strictopts; /* stop on errors in address options */
+ char logopt; /* y..syslog; s..stderr; f..file; m..mixed */
+ bool lefttoright; /* first addr ro, second addr wo */
+ bool righttoleft; /* first addr wo, second addr ro */
+ xiolock_t lock; /* a lock file */
+} socat_opts = {
+ 8192, /* bufsiz */
+ false, /* verbose */
+ false, /* verbhex */
+ {1,0}, /* pollintv */
+ {0,500000}, /* closwait */
+ {0,0}, /* total_timeout */
+ 0, /* debug */
+ 0, /* strictopts */
+ 's', /* logopt */
+ false, /* lefttoright */
+ false, /* righttoleft */
+ { NULL, 0 }, /* lock */
+};
+
+void socat_usage(FILE *fd);
+void socat_version(FILE *fd);
+int socat(const char *address1, const char *address2);
+int _socat(void);
+int cv_newline(unsigned char **buff, ssize_t *bytes, int lineterm1, int lineterm2);
+void socat_signal(int sig);
+static int socat_sigchild(struct single *file);
+
+void lftocrlf(char **in, ssize_t *len, size_t bufsiz);
+void crlftolf(char **in, ssize_t *len, size_t bufsiz);
+
+static int socat_lock(void);
+static void socat_unlock(void);
+static int socat_newchild(void);
+
+static const char socatversion[] =
+#include "./VERSION"
+ ;
+static const char timestamp[] = __DATE__" "__TIME__;
+
+const char copyright_socat[] = "socat by Gerhard Rieger - see www.dest-unreach.org";
+#if WITH_OPENSSL
+const char copyright_openssl[] = "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)";
+const char copyright_ssleay[] = "This product includes software written by Tim Hudson (tjh@cryptsoft.com)";
+#endif
+
+bool havelock;
+
+
+int main(int argc, const char *argv[]) {
+ const char **arg1, *a;
+ char buff[10];
+ double rto;
+ int i, argc0, result;
+ struct utsname ubuf;
+ int lockrc;
+
+ diag_set('p', strchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
+
+ /* we must init before applying options because env settings have lower
+ priority and are to be overridden by options */
+ if (xioinitialize() != 0) {
+ Exit(1);
+ }
+
+ xiosetopt('p', "!!");
+ xiosetopt('o', ":");
+
+ argc0 = argc; /* save for later use */
+ arg1 = argv+1; --argc;
+ while (arg1[0] && (arg1[0][0] == '-')) {
+ switch (arg1[0][1]) {
+ case 'V': socat_version(stdout); Exit(0);
+#if WITH_HELP
+ case '?':
+ case 'h':
+ socat_usage(stdout);
+ xioopenhelp(stdout, (arg1[0][2]=='?'||arg1[0][2]=='h') ? (arg1[0][3]=='?'||arg1[0][3]=='h') ? 2 : 1 : 0);
+ Exit(0);
+#endif /* WITH_HELP */
+ case 'd': diag_set('d', NULL); break;
+#if WITH_FILAN
+ case 'D': socat_opts.debug = true; break;
+#endif
+ case 'l':
+ switch (arg1[0][2]) {
+ case 'm': /* mixed mode: stderr, then switch to syslog; + facility */
+ diag_set('s', NULL);
+ xiosetopt('l', "m");
+ socat_opts.logopt = arg1[0][2];
+ xiosetopt('y', &arg1[0][3]);
+ break;
+ case 'y': /* syslog + facility */
+ diag_set(arg1[0][2], &arg1[0][3]);
+ break;
+ case 'f': /* to file, +filename */
+ case 'p': /* artificial program name */
+ if (arg1[0][3]) {
+ diag_set(arg1[0][2], &arg1[0][3]);
+ } else if (arg1[1]) {
+ diag_set(arg1[0][2], arg1[1]);
+ ++arg1, --argc;
+ } else {
+ Error1("option -l%c requires an argument; use option \"-h\" for help", arg1[0][2]);
+ }
+ break;
+ case 's': /* stderr */
+ diag_set(arg1[0][2], NULL);
+ break;
+ case 'u':
+ diag_set('u', NULL);
+ break;
+ case 'h':
+ diag_set_int('h', true);
+ break;
+ default:
+ Error1("unknown log option \"%s\"; use option \"-h\" for help", arg1[0]);
+ break;
+ }
+ break;
+ case 'v': socat_opts.verbose = true; break;
+ case 'x': socat_opts.verbhex = true; break;
+ case 'b': if (arg1[0][2]) {
+ a = *arg1+2;
+ } else {
+ ++arg1, --argc;
+ if ((a = *arg1) == NULL) {
+ Error("option -b requires an argument; use option \"-h\" for help");
+ Exit(1);
+ }
+ }
+ socat_opts.bufsiz = strtoul(a, (char **)&a, 0);
+ break;
+ case 's':
+ diag_set_int('e', E_FATAL); break;
+ case 't': if (arg1[0][2]) {
+ a = *arg1+2;
+ } else {
+ ++arg1, --argc;
+ if ((a = *arg1) == NULL) {
+ Error("option -t requires an argument; use option \"-h\" for help");
+ Exit(1);
+ }
+ }
+ rto = strtod(a, (char **)&a);
+ socat_opts.closwait.tv_sec = rto;
+ socat_opts.closwait.tv_usec =
+ (rto-socat_opts.closwait.tv_sec) * 1000000;
+ break;
+ case 'T': if (arg1[0][2]) {
+ a = *arg1+2;
+ } else {
+ ++arg1, --argc;
+ if ((a = *arg1) == NULL) {
+ Error("option -T requires an argument; use option \"-h\" for help");
+ Exit(1);
+ }
+ }
+ rto = strtod(a, (char **)&a);
+ socat_opts.total_timeout.tv_sec = rto;
+ socat_opts.total_timeout.tv_usec =
+ (rto-socat_opts.total_timeout.tv_sec) * 1000000;
+ break;
+ case 'u': socat_opts.lefttoright = true; break;
+ case 'U': socat_opts.righttoleft = true; break;
+ case 'g': xioopts_ignoregroups = true; break;
+ case 'L': if (socat_opts.lock.lockfile)
+ Error("only one -L and -W option allowed");
+ if (arg1[0][2]) {
+ socat_opts.lock.lockfile = *arg1+2;
+ } else {
+ ++arg1, --argc;
+ if ((socat_opts.lock.lockfile = *arg1) == NULL) {
+ Error("option -L requires an argument; use option \"-h\" for help");
+ Exit(1);
+ }
+ }
+ break;
+ case 'W': if (socat_opts.lock.lockfile)
+ Error("only one -L and -W option allowed");
+ if (arg1[0][2]) {
+ socat_opts.lock.lockfile = *arg1+2;
+ } else {
+ ++arg1, --argc;
+ if ((socat_opts.lock.lockfile = *arg1) == NULL) {
+ Error("option -W requires an argument; use option \"-h\" for help");
+ Exit(1);
+ }
+ }
+ socat_opts.lock.waitlock = true;
+ socat_opts.lock.intervall.tv_sec = 1;
+ socat_opts.lock.intervall.tv_nsec = 0;
+ break;
+#if WITH_IP4 || WITH_IP6
+#if WITH_IP4
+ case '4':
+#endif
+#if WITH_IP6
+ case '6':
+#endif
+ xioopts.default_ip = arg1[0][1];
+ xioopts.preferred_ip = arg1[0][1];
+ break;
+#endif /* WITH_IP4 || WITH_IP6 */
+ case '\0':
+ case ',':
+ case ':': break; /* this "-" is a variation of STDIO */
+ default:
+ xioinqopt('p', buff, sizeof(buff));
+ if (arg1[0][1] == buff[0]) {
+ break;
+ }
+ Error1("unknown option \"%s\"; use option \"-h\" for help", arg1[0]);
+ Exit(1);
+ }
+ /* the leading "-" might be a form of the first address */
+ xioinqopt('p', buff, sizeof(buff));
+ if (arg1[0][0] == '-' &&
+ (arg1[0][1] == '\0' || arg1[0][1] == ':' ||
+ arg1[0][1] == ',' || arg1[0][1] == buff[0]))
+ break;
+ ++arg1; --argc;
+ }
+ if (argc != 2) {
+ Error1("exactly 2 addresses required (there are %d); use option \"-h\" for help", argc);
+ Exit(1);
+ }
+ if (socat_opts.lefttoright && socat_opts.righttoleft) {
+ Error("-U and -u must not be combined");
+ }
+
+ Info(copyright_socat);
+#if WITH_OPENSSL
+ Info(copyright_openssl);
+ Info(copyright_ssleay);
+#endif
+ Debug2("socat version %s on %s", socatversion, timestamp);
+ 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);
+
+#if WITH_MSGLEVEL <= E_DEBUG
+ for (i = 0; i < argc0; ++i) {
+ Debug2("argv[%d]: \"%s\"", i, argv[i]);
+ }
+#endif /* WITH_MSGLEVEL <= E_DEBUG */
+
+ /* not sure what signal should print a message */
+ Signal(SIGHUP, socat_signal);
+ Signal(SIGINT, socat_signal);
+ Signal(SIGQUIT, socat_signal);
+ Signal(SIGILL, socat_signal);
+ /* SIGABRT for assert; catching caused endless recursion on assert in libc
+ (tzfile.c:498: __tzfile_compute: Assertion 'num_types == 1' failed.) */
+ /*Signal(SIGABRT, socat_signal);*/
+ Signal(SIGBUS, socat_signal);
+ Signal(SIGFPE, socat_signal);
+ Signal(SIGSEGV, socat_signal);
+ Signal(SIGTERM, socat_signal);
+
+ /* set xio hooks */
+ xiohook_newchild = &socat_newchild;
+
+ if (lockrc = socat_lock()) {
+ /* =0: goon; >0: locked; <0: error, printed in sub */
+ if (lockrc > 0)
+ Error1("could not obtain lock \"%s\"", socat_opts.lock.lockfile);
+ Exit(1);
+ }
+
+ Atexit(socat_unlock);
+
+ result = socat(arg1[0], arg1[1]);
+ Notice1("exiting with status %d", result);
+ Exit(result);
+ return 0; /* not reached, just for gcc -Wall */
+}
+
+
+void socat_usage(FILE *fd) {
+ fputs(copyright_socat, fd); fputc('\n', fd);
+ fputs("Usage:\n", fd);
+ fputs("socat [options] <bi-address> <bi-address>\n", fd);
+ fputs(" options:\n", fd);
+ fputs(" -V print version and feature information to stdout, and exit\n", fd);
+#if WITH_HELP
+ fputs(" -h|-? print a help text describing command line options and addresses\n", fd);
+ fputs(" -hh like -h, plus a list of all common address option names\n", fd);
+ fputs(" -hhh like -hh, plus a list of all available address option names\n", fd);
+#endif /* WITH_HELP */
+ fputs(" -d increase verbosity (use up to 4 times; 2 are recommended)\n", fd);
+#if WITH_FILAN
+ fputs(" -D analyze file descriptors before loop\n", fd);
+#endif
+ fputs(" -ly[facility] log to syslog, using facility (default is daemon)\n", fd);
+ fputs(" -lf<logfile> log to file\n", fd);
+ fputs(" -ls log to stderr (default if no other log)\n", fd);
+ fputs(" -lm[facility] mixed log mode (stderr during initialization, then syslog)\n", fd);
+ fputs(" -lp<progname> set the program name used for logging\n", fd);
+ fputs(" -lu use microseconds for logging timestamps\n", fd);
+ fputs(" -lh add hostname to log messages\n", fd);
+ fputs(" -v verbose data traffic, text\n", fd);
+ fputs(" -x verbose data traffic, hexadecimal\n", fd);
+ fputs(" -b<size_t> set data buffer size (8192)\n", fd);
+ fputs(" -s sloppy (continue on error)\n", fd);
+ fputs(" -t<timeout> wait seconds before closing second channel\n", fd);
+ fputs(" -T<timeout> total inactivity timeout in seconds\n", fd);
+ fputs(" -u unidirectional mode (left to right)\n", fd);
+ fputs(" -U unidirectional mode (right to left)\n", fd);
+ fputs(" -g do not check option groups\n", fd);
+ fputs(" -L <lockfile> try to obtain lock, or fail\n", fd);
+ fputs(" -W <lockfile> try to obtain lock, or wait\n", fd);
+#if WITH_IP4
+ fputs(" -4 prefer IPv4 if version is not explicitly specified\n", fd);
+#endif
+#if WITH_IP6
+ fputs(" -6 prefer IPv6 if version is not explicitly specified\n", fd);
+#endif
+}
+
+
+void socat_version(FILE *fd) {
+ struct utsname ubuf;
+
+ fputs(copyright_socat, fd); fputc('\n', fd);
+ fprintf(fd, "socat version %s on %s\n", socatversion, timestamp);
+ Uname(&ubuf);
+ fprintf(fd, " running on %s version %s, release %s, machine %s\n",
+ ubuf.sysname, ubuf.version, ubuf.release, ubuf.machine);
+ fputs("features:\n", fd);
+#ifdef WITH_STDIO
+ fprintf(fd, " #define WITH_STDIO %d\n", WITH_STDIO);
+#else
+ fputs(" #undef WITH_STDIO\n", fd);
+#endif
+#ifdef WITH_FDNUM
+ fprintf(fd, " #define WITH_FDNUM %d\n", WITH_FDNUM);
+#else
+ fputs(" #undef WITH_FDNUM\n", fd);
+#endif
+#ifdef WITH_FILE
+ fprintf(fd, " #define WITH_FILE %d\n", WITH_FILE);
+#else
+ fputs(" #undef WITH_FILE\n", fd);
+#endif
+#ifdef WITH_CREAT
+ fprintf(fd, " #define WITH_CREAT %d\n", WITH_CREAT);
+#else
+ fputs(" #undef WITH_CREAT\n", fd);
+#endif
+#ifdef WITH_GOPEN
+ fprintf(fd, " #define WITH_GOPEN %d\n", WITH_GOPEN);
+#else
+ fputs(" #undef WITH_GOPEN\n", fd);
+#endif
+#ifdef WITH_TERMIOS
+ fprintf(fd, " #define WITH_TERMIOS %d\n", WITH_TERMIOS);
+#else
+ fputs(" #undef WITH_TERMIOS\n", fd);
+#endif
+#ifdef WITH_PIPE
+ fprintf(fd, " #define WITH_PIPE %d\n", WITH_PIPE);
+#else
+ fputs(" #undef WITH_PIPE\n", fd);
+#endif
+#ifdef WITH_UNIX
+ fprintf(fd, " #define WITH_UNIX %d\n", WITH_UNIX);
+#else
+ fputs(" #undef WITH_UNIX\n", fd);
+#endif /* WITH_UNIX */
+#ifdef WITH_ABSTRACT_UNIXSOCKET
+ fprintf(fd, " #define WITH_ABSTRACT_UNIXSOCKET %d\n", WITH_ABSTRACT_UNIXSOCKET);
+#else
+ fputs(" #undef WITH_ABSTRACT_UNIXSOCKET\n", fd);
+#endif /* WITH_ABSTRACT_UNIXSOCKET */
+#ifdef WITH_IP4
+ fprintf(fd, " #define WITH_IP4 %d\n", WITH_IP4);
+#else
+ fputs(" #undef WITH_IP4\n", fd);
+#endif
+#ifdef WITH_IP6
+ fprintf(fd, " #define WITH_IP6 %d\n", WITH_IP6);
+#else
+ fputs(" #undef WITH_IP6\n", fd);
+#endif
+#ifdef WITH_RAWIP
+ fprintf(fd, " #define WITH_RAWIP %d\n", WITH_RAWIP);
+#else
+ fputs(" #undef WITH_RAWIP\n", fd);
+#endif
+#ifdef WITH_TCP
+ fprintf(fd, " #define WITH_TCP %d\n", WITH_TCP);
+#else
+ fputs(" #undef WITH_TCP\n", fd);
+#endif
+#ifdef WITH_UDP
+ fprintf(fd, " #define WITH_UDP %d\n", WITH_UDP);
+#else
+ fputs(" #undef WITH_UDP\n", fd);
+#endif
+#ifdef WITH_LISTEN
+ fprintf(fd, " #define WITH_LISTEN %d\n", WITH_LISTEN);
+#else
+ fputs(" #undef WITH_LISTEN\n", fd);
+#endif
+#ifdef WITH_SOCKS4
+ fprintf(fd, " #define WITH_SOCKS4 %d\n", WITH_SOCKS4);
+#else
+ fputs(" #undef WITH_SOCKS4\n", fd);
+#endif
+#ifdef WITH_SOCKS4A
+ fprintf(fd, " #define WITH_SOCKS4A %d\n", WITH_SOCKS4A);
+#else
+ fputs(" #undef WITH_SOCKS4A\n", fd);
+#endif
+#ifdef WITH_PROXY
+ fprintf(fd, " #define WITH_PROXY %d\n", WITH_PROXY);
+#else
+ fputs(" #undef WITH_PROXY\n", fd);
+#endif
+#ifdef WITH_SYSTEM
+ fprintf(fd, " #define WITH_SYSTEM %d\n", WITH_SYSTEM);
+#else
+ fputs(" #undef WITH_SYSTEM\n", fd);
+#endif
+#ifdef WITH_EXEC
+ fprintf(fd, " #define WITH_EXEC %d\n", WITH_EXEC);
+#else
+ fputs(" #undef WITH_EXEC\n", fd);
+#endif
+#ifdef WITH_READLINE
+ fprintf(fd, " #define WITH_READLINE %d\n", WITH_READLINE);
+#else
+ fputs(" #undef WITH_READLINE\n", fd);
+#endif
+#ifdef WITH_TUN
+ fprintf(fd, " #define WITH_TUN %d\n", WITH_TUN);
+#else
+ fputs(" #undef WITH_TUN\n", fd);
+#endif
+#ifdef WITH_PTY
+ fprintf(fd, " #define WITH_PTY %d\n", WITH_PTY);
+#else
+ fputs(" #undef WITH_PTY\n", fd);
+#endif
+#ifdef WITH_OPENSSL
+ fprintf(fd, " #define WITH_OPENSSL %d\n", WITH_OPENSSL);
+#else
+ fputs(" #undef WITH_OPENSSL\n", fd);
+#endif
+#ifdef WITH_FIPS
+ fprintf(fd, " #define WITH_FIPS %d\n", WITH_FIPS);
+#else
+ fputs(" #undef WITH_FIPS\n", fd);
+#endif
+#ifdef WITH_LIBWRAP
+ fprintf(fd, " #define WITH_LIBWRAP %d\n", WITH_LIBWRAP);
+#else
+ fputs(" #undef WITH_LIBWRAP\n", fd);
+#endif
+#ifdef WITH_SYCLS
+ fprintf(fd, " #define WITH_SYCLS %d\n", WITH_SYCLS);
+#else
+ fputs(" #undef WITH_SYCLS\n", fd);
+#endif
+#ifdef WITH_FILAN
+ fprintf(fd, " #define WITH_FILAN %d\n", WITH_FILAN);
+#else
+ fputs(" #undef WITH_FILAN\n", fd);
+#endif
+#ifdef WITH_RETRY
+ fprintf(fd, " #define WITH_RETRY %d\n", WITH_RETRY);
+#else
+ fputs(" #undef WITH_RETRY\n", fd);
+#endif
+#ifdef WITH_MSGLEVEL
+ fprintf(fd, " #define WITH_MSGLEVEL %d /*%s*/\n", WITH_MSGLEVEL,
+ &"debug\0\0\0info\0\0\0\0notice\0\0warn\0\0\0\0error\0\0\0fatal\0\0\0"[WITH_MSGLEVEL<<3]);
+#else
+ fputs(" #undef WITH_MSGLEVEL\n", fd);
+#endif
+}
+
+
+xiofile_t *sock1, *sock2;
+int closing = 0; /* 0..no eof yet, 1..first eof just occurred,
+ 2..counting down closing timeout */
+
+/* call this function when the common command line options are parsed, and the
+ addresses are extracted (but not resolved). */
+int socat(const char *address1, const char *address2) {
+ int mayexec;
+
+#if 1
+ if (Signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
+ Warn1("signal(SIGPIPE, SIG_IGN): %s", strerror(errno));
+ }
+#endif
+
+ if (socat_opts.lefttoright) {
+ if ((sock1 = xioopen(address1, XIO_RDONLY|XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYCONVERT)) == NULL) {
+ return -1;
+ }
+ xiosetsigchild(sock1, socat_sigchild);
+ } else if (socat_opts.righttoleft) {
+ if ((sock1 = xioopen(address1, XIO_WRONLY|XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYCONVERT)) == NULL) {
+ return -1;
+ }
+ xiosetsigchild(sock1, socat_sigchild);
+ } else {
+ if ((sock1 = xioopen(address1, XIO_RDWR|XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYCONVERT)) == NULL) {
+ return -1;
+ }
+ xiosetsigchild(sock1, socat_sigchild);
+ }
+#if 1 /*! */
+ if (XIO_READABLE(sock1) &&
+ (XIO_RDSTREAM(sock1)->howtoend == END_KILL ||
+ XIO_RDSTREAM(sock1)->howtoend == END_CLOSE_KILL ||
+ XIO_RDSTREAM(sock1)->howtoend == END_SHUTDOWN_KILL)) {
+ if (XIO_RDSTREAM(sock1)->para.exec.pid == diedunknown1) {
+ /* child has alread died... but it might have put regular data into
+ the communication channel, so continue */
+ Info1("child "F_pid" has already died (diedunknown1)",
+ XIO_RDSTREAM(sock1)->para.exec.pid);
+ diedunknown1 = 0;
+ XIO_RDSTREAM(sock1)->para.exec.pid = 0;
+ /* return STAT_RETRYLATER; */
+ } else if (XIO_RDSTREAM(sock1)->para.exec.pid == diedunknown2) {
+ Info1("child "F_pid" has already died (diedunknown2)",
+ XIO_RDSTREAM(sock1)->para.exec.pid);
+ diedunknown2 = 0;
+ XIO_RDSTREAM(sock1)->para.exec.pid = 0;
+ } else if (XIO_RDSTREAM(sock1)->para.exec.pid == diedunknown3) {
+ Info1("child "F_pid" has already died (diedunknown3)",
+ XIO_RDSTREAM(sock1)->para.exec.pid);
+ diedunknown3 = 0;
+ XIO_RDSTREAM(sock1)->para.exec.pid = 0;
+ } else if (XIO_RDSTREAM(sock1)->para.exec.pid == diedunknown4) {
+ Info1("child "F_pid" has already died (diedunknown4)",
+ XIO_RDSTREAM(sock1)->para.exec.pid);
+ diedunknown4 = 0;
+ XIO_RDSTREAM(sock1)->para.exec.pid = 0;
+ }
+ }
+#endif
+
+ mayexec = (sock1->common.flags&XIO_DOESCONVERT ? 0 : XIO_MAYEXEC);
+ if (XIO_WRITABLE(sock1)) {
+ if (XIO_READABLE(sock1)) {
+ if ((sock2 = xioopen(address2, XIO_RDWR|XIO_MAYFORK|XIO_MAYCHILD|mayexec|XIO_MAYCONVERT)) == NULL) {
+ return -1;
+ }
+ xiosetsigchild(sock2, socat_sigchild);
+ } else {
+ if ((sock2 = xioopen(address2, XIO_RDONLY|XIO_MAYFORK|XIO_MAYCHILD|mayexec|XIO_MAYCONVERT)) == NULL) {
+ return -1;
+ }
+ xiosetsigchild(sock2, socat_sigchild);
+ }
+ } else { /* assuming sock1 is readable */
+ if ((sock2 = xioopen(address2, XIO_WRONLY|XIO_MAYFORK|XIO_MAYCHILD|mayexec|XIO_MAYCONVERT)) == NULL) {
+ return -1;
+ }
+ xiosetsigchild(sock2, socat_sigchild);
+ }
+#if 1 /*! */
+ if (XIO_READABLE(sock2) &&
+ (XIO_RDSTREAM(sock2)->howtoend == END_KILL ||
+ XIO_RDSTREAM(sock2)->howtoend == END_CLOSE_KILL ||
+ XIO_RDSTREAM(sock2)->howtoend == END_SHUTDOWN_KILL)) {
+ if (XIO_RDSTREAM(sock2)->para.exec.pid == diedunknown1) {
+ /* child has alread died... but it might have put regular data into
+ the communication channel, so continue */
+ Info1("child "F_pid" has already died (diedunknown1)",
+ XIO_RDSTREAM(sock2)->para.exec.pid);
+ diedunknown1 = 0;
+ XIO_RDSTREAM(sock2)->para.exec.pid = 0;
+ /* return STAT_RETRYLATER; */
+ } else if (XIO_RDSTREAM(sock2)->para.exec.pid == diedunknown2) {
+ Info1("child "F_pid" has already died (diedunknown2)",
+ XIO_RDSTREAM(sock2)->para.exec.pid);
+ diedunknown2 = 0;
+ XIO_RDSTREAM(sock2)->para.exec.pid = 0;
+ } else if (XIO_RDSTREAM(sock2)->para.exec.pid == diedunknown3) {
+ Info1("child "F_pid" has already died (diedunknown3)",
+ XIO_RDSTREAM(sock2)->para.exec.pid);
+ diedunknown3 = 0;
+ XIO_RDSTREAM(sock2)->para.exec.pid = 0;
+ } else if (XIO_RDSTREAM(sock2)->para.exec.pid == diedunknown4) {
+ Info1("child "F_pid" has already died (diedunknown4)",
+ XIO_RDSTREAM(sock2)->para.exec.pid);
+ diedunknown4 = 0;
+ XIO_RDSTREAM(sock2)->para.exec.pid = 0;
+ }
+ }
+#endif
+
+ Info("resolved and opened all sock addresses");
+ return
+ _socat(); /* nsocks, sockets are visible outside function */
+}
+
+/* checks if this is a connection to a child process, and if so, sees if the
+ child already died, leaving some data for us.
+ returns <0 if an error occurred;
+ returns 0 if no child or not yet died or died without data (sets eof);
+ returns >0 if child died and left data
+*/
+int childleftdata(xiofile_t *xfd) {
+ fd_set in, out, expt;
+ int retval;
+ /* have to check if a child process died before, but left read data */
+ if (XIO_READABLE(xfd) &&
+ (XIO_RDSTREAM(xfd)->howtoend == END_KILL ||
+ XIO_RDSTREAM(xfd)->howtoend == END_CLOSE_KILL ||
+ XIO_RDSTREAM(xfd)->howtoend == END_SHUTDOWN_KILL) &&
+ XIO_RDSTREAM(xfd)->para.exec.pid == 0) {
+ struct timeval time0 = { 0,0 };
+
+ FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt);
+ if (XIO_READABLE(xfd) && !(XIO_RDSTREAM(xfd)->eof >= 2 && !XIO_RDSTREAM(xfd)->ignoreeof)) {
+ FD_SET(XIO_GETRDFD(xfd), &in);
+ /*0 FD_SET(XIO_GETRDFD(xfd), &expt);*/
+ }
+ do {
+ retval = Select(FOPEN_MAX, &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",
+ FOPEN_MAX, 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",
+ FOPEN_MAX, 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;
+}
+
+int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
+ unsigned char **buff, size_t bufsiz, bool righttoleft);
+
+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() */
+
+/* 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(void) {
+ 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 */
+
+#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 */
+
+ fdi = XIO_GETRDFD(sock1);
+ fdo = XIO_GETWRFD(sock1);
+ filan_fd(fdi, stderr);
+ if (fdo != fdi) {
+ filan_fd(fdo, stderr);
+ }
+
+ fdi = XIO_GETRDFD(sock2);
+ fdo = XIO_GETWRFD(sock2);
+ filan_fd(fdi, stderr);
+ if (fdo != fdi) {
+ filan_fd(fdo, stderr);
+ }
+
+ diag_set_int('e', exitlevel); /* restore old exit level */
+ diag_set_int('D', msglevel); /* restore old message level */
+ }
+#endif /* WITH_FILAN */
+
+ /* when converting nl to crnl, size might double */
+ buff = Malloc(2*socat_opts.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) {
+ 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) {
+ if (!mayrd2) {
+ FD_SET(XIO_GETRDFD(sock2), &in);
+ }
+ if (!maywr1) {
+ FD_SET(XIO_GETWRFD(sock1), &out);
+ }
+ }
+ retval = Select(FOPEN_MAX, &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",
+ FOPEN_MAX, 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",
+ FOPEN_MAX, 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, socat_opts.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;
+ }
+ }
+ /* (bytes1 == 0) handled later */
+ } else {
+ bytes1 = -1;
+ }
+
+ if (mayrd2 && maywr1) {
+ mayrd2 = false;
+ if ((bytes2 = xiotransfer(sock2, sock1, &buff, socat_opts.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;
+ }
+ }
+ /* (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)->fd); /*! */
+ 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)->fd);
+ 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;
+}
+
+
+#define MAXTIMESTAMPLEN 128
+/* prints the timestamp to the buffer and terminates it with '\0'. This buffer
+ should be at least MAXTIMESTAMPLEN bytes long.
+ returns 0 on success or -1 if an error occurred */
+int gettimestamp(char *timestamp) {
+ size_t bytes;
+#if HAVE_GETTIMEOFDAY || 1
+ struct timeval now;
+ int result;
+ time_t nowt;
+#else /* !HAVE_GETTIMEOFDAY */
+ time_t now;
+#endif /* !HAVE_GETTIMEOFDAY */
+
+#if HAVE_GETTIMEOFDAY || 1
+ result = gettimeofday(&now, NULL);
+ if (result < 0) {
+ return result;
+ } else {
+ nowt = now.tv_sec;
+#if HAVE_STRFTIME
+ bytes = strftime(timestamp, 20, "%Y/%m/%d %H:%M:%S", localtime(&nowt));
+ bytes += sprintf(timestamp+19, "."F_tv_usec" ", now.tv_usec);
+#else
+ strcpy(timestamp, ctime(&nowt));
+ bytes = strlen(timestamp);
+#endif
+ }
+#else /* !HAVE_GETTIMEOFDAY */
+ now = time(NULL); if (now == (time_t)-1) {
+ return -1;
+ } else {
+#if HAVE_STRFTIME
+ bytes = strftime(timestamp, 21, "%Y/%m/%d %H:%M:%S ", localtime(&now));
+#else
+ strcpy(timestamp, ctime(&now));
+ bytes = strlen(timestamp);
+#endif
+ }
+#endif /* !HAVE_GETTIMEOFDAY */
+ return 0;
+}
+
+static const char *prefixltor = "> ";
+static const char *prefixrtol = "< ";
+static unsigned long numltor;
+static unsigned long numrtol;
+/* print block header (during verbose or hex dump)
+ returns 0 on success or -1 if an error occurred */
+static int
+ xioprintblockheader(FILE *file, size_t bytes, bool righttoleft) {
+ char timestamp[MAXTIMESTAMPLEN];
+ char buff[128+MAXTIMESTAMPLEN];
+ if (gettimestamp(timestamp) < 0) {
+ return -1;
+ }
+ if (righttoleft) {
+ sprintf(buff, "%s%s length="F_Zu" from=%lu to=%lu\n",
+ prefixrtol, timestamp, bytes, numrtol, numrtol+bytes-1);
+ numrtol+=bytes;
+ } else {
+ sprintf(buff, "%s%s length="F_Zu" from=%lu to=%lu\n",
+ prefixltor, timestamp, bytes, numltor, numltor+bytes-1);
+ numltor+=bytes;
+ }
+ fputs(buff, file);
+ return 0;
+}
+
+
+/* inpipe is suspected to have read data available; read at most bufsiz bytes
+ and transfer them to outpipe. Perform required data conversions.
+ buff should be at least twice as large as bufsiz, to allow all standard
+ conversions. Returns the number of bytes written, or 0 on EOF or <0 if an
+ error occurred or when data was read but none written due to conversions
+ (with EAGAIN). EAGAIN also occurs when reading from a nonblocking FD where
+ the file has a mandatory lock.
+ If 0 bytes were read (EOF), it does NOT shutdown or close a channel, and it
+ does NOT write a zero bytes block.
+ */
+/* inpipe, outpipe must be single descriptors (not dual!) */
+int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
+ unsigned char **buff, size_t bufsiz, bool righttoleft) {
+ ssize_t bytes, writt;
+
+ bytes = xioread(inpipe, *buff, socat_opts.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 (socat_opts.verbose && socat_opts.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 (socat_opts.verbhex) {
+ int i;
+ /*! prefix? */
+ for (i = 0; i < bytes; ++i) {
+ fprintf(stderr, " %02x", (*buff)[i]);
+ }
+ fputc('\n', stderr);
+ }
+
+ writt = xiowrite(outpipe, *buff, bytes);
+ if (writt < 0) {
+ /* EAGAIN when nonblocking but a mandatory lock is on file.
+ the problem with EAGAIN is that the read cannot be repeated,
+ so we need to buffer the data and try to write it later
+ again. not yet implemented, sorry. */
+#if 0
+ if (errno == EPIPE) {
+ return 0; /* can no longer write; handle like EOF */
+ }
+#endif
+ return -1;
+ } else {
+ Info3("transferred "F_Zu" bytes from %d to %d",
+ writt, XIO_GETRDFD(inpipe), XIO_GETWRFD(outpipe));
+ }
+ }
+ return writt;
+}
+
+#define CR '\r'
+#define LF '\n'
+
+
+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*socat_opts.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;
+}
+
+void socat_signal(int signum) {
+ switch (signum) {
+ case SIGQUIT:
+ case SIGILL:
+ case SIGABRT:
+ case SIGBUS:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGPIPE:
+ diag_set_int('x', 128+signum); /* in case Error exits for us */
+ Error1("exiting on signal %d", signum);
+ diag_set_int('x', 0); /* in case Error did not exit */
+ break;
+ case SIGTERM:
+ Warn1("exiting on signal %d", signum); break;
+ case SIGHUP:
+ case SIGINT:
+ Notice1("exiting on signal %d", signum); break;
+ }
+ Exit(128+signum);
+}
+
+/* this is the callback when the child of an address died */
+static int socat_sigchild(struct single *file) {
+ if (file->ignoreeof && !closing) {
+ ;
+ } else {
+ file->eof = MAX(file->eof, 1);
+ closing = 1;
+ }
+ return 0;
+}
+
+static int socat_lock(void) {
+ int lockrc;
+
+#if 1
+ if ((lockrc = xiolock(&socat_opts.lock)) < 0) {
+ return -1;
+ }
+ if (lockrc == 0) {
+ havelock = true;
+ }
+ return lockrc;
+#else
+ if (socat_opts.lock.lockfile) {
+ if ((lockrc = xiolock(socat_opts.lock.lockfile)) < 0) {
+ /*Error1("error with lockfile \"%s\"", socat_opts.lock.lockfile);*/
+ return -1;
+ }
+ if (lockrc) {
+ return 1;
+ }
+ havelock = true;
+ /*0 Info1("obtained lock \"%s\"", socat_opts.lock.lockfile);*/
+ }
+
+ if (socat_opts.lock.waitlock) {
+ if (xiowaitlock(socat_opts.lock.waitlock, socat_opts.lock.intervall)) {
+ /*Error1("error with lockfile \"%s\"", socat_opts.lock.lockfile);*/
+ return -1;
+ } else {
+ havelock = true;
+ /*0 Info1("obtained lock \"%s\"", socat_opts.lock.waitlock);*/
+ }
+ }
+ return 0;
+#endif
+}
+
+static void socat_unlock(void) {
+ if (!havelock) return;
+ if (socat_opts.lock.lockfile) {
+ if (Unlink(socat_opts.lock.lockfile) < 0) {
+ Warn2("unlink(\"%s\"): %s",
+ socat_opts.lock.lockfile, strerror(errno));
+ } else {
+ Info1("released lock \"%s\"", socat_opts.lock.lockfile);
+ }
+ }
+}
+
+/* this is a callback function that may be called by the newchild hook of xio
+ */
+static int socat_newchild(void) {
+ havelock = false;
+ return 0;
+}
diff --git a/socat.spec b/socat.spec
new file mode 100644
index 0000000..db6beac
--- /dev/null
+++ b/socat.spec
@@ -0,0 +1,52 @@
+
+%define majorver 1.6
+%define minorver 0.0
+
+Summary: socat - multipurpose relay
+Name: socat
+Version: %{majorver}.%{minorver}
+Release: 1
+Copyright: GPL
+Group: Applications/Communications
+Source0: http://www.dest-unreach.org/socat/download/socat-%{version}.tar.gz
+Requires: readline
+Requires: openssl
+BuildRoot: /var/tmp/%{name}-buildroot
+
+%description
+socat is a relay for bidirectional data transfer between two independent data
+channels. Each of these data channels may be a file, pipe, device (terminal or
+modem etc.), socket (UNIX, IP4, IP6 - raw, UDP, TCP), a file descriptor (stdin
+etc.), a program, or an arbitrary combination of two of these.
+
+%prep
+%setup -n %{name}-%{majorver}
+
+%build
+# the CPPFLAGS setting is required for RedHat Linux
+if [ -d /usr/kerberos/include ]; then
+ CPPFLAGS="-I/usr/kerberos/include" ./configure --prefix=%{_prefix} --mandir=%{_mandir}
+else
+ ./configure --prefix=%{_prefix} --mandir=%{_mandir}
+fi
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+mkdir -p $RPM_BUILD_ROOT%{_bindir}
+mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1
+
+make install DESTDIR=$RPM_BUILD_ROOT
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc README CHANGES EXAMPLES SECURITY xio.help socat.html FAQ BUGREPORTS
+%doc COPYING COPYING.OpenSSL FILES PORTING DEVELOPMENT
+%{_bindir}/socat
+%{_bindir}/procan
+%{_bindir}/filan
+%{_mandir}/man1/socat.1*
diff --git a/socks4a-echo.sh b/socks4a-echo.sh
new file mode 100755
index 0000000..2ab8142
--- /dev/null
+++ b/socks4a-echo.sh
@@ -0,0 +1,114 @@
+#! /bin/bash
+# $Id: socks4a-echo.sh,v 1.2 2004/08/25 16:01:30 gerhard Exp $
+#set -vx
+
+# Copyright Gerhard Rieger 2004
+# Published under the GNU General Public License V.2, see file COPYING
+
+# perform primitive simulation of a socks4a server with echo function via stdio.
+# accepts and answers correct SOCKS4a requests, but then just echoes data.
+# it is required for test.sh
+# for TCP, use this script as:
+# socat tcp-l:1080,reuseaddr,crlf system:"socks4a-echo.sh"
+
+# older bash and ksh do not have -n option to read command; we try dd then
+if echo a |read -n 1 null >/dev/null 2>&1; then
+ HAVE_READ_N=1
+else
+ HAVE_READ_N=
+fi
+
+if type socat >/dev/null 2>&1; then
+ SOCAT=socat
+else
+ SOCAT=./socat
+fi
+
+case `uname` in
+HP-UX|OSF1)
+ CAT="$SOCAT -u stdin stdout"
+ ;;
+*)
+ CAT=cat
+ ;;
+esac
+
+if [ $(echo "x\c") = "x" ]; then E=""
+elif [ $(echo -e "x\c") = "x" ]; then E="-e"
+else
+ echo "cannot suppress trailing newline on echo" >&2
+ exit 1
+fi
+ECHO="echo $E"
+
+if [ $($ECHO "\0101") = "A" ]; then
+ SOCKSREPLY_FAILED="\0\0133\0\0\0\0\0\0\c"
+ SOCKSREPLY_OK="\0\0132\0\0\0\0\0\0\c"
+else
+ SOCKSREPLY_FAILED="\0\133\0\0\0\0\0\0\c"
+ SOCKSREPLY_OK="\0\132\0\0\0\0\0\0\c"
+fi
+
+# read and parse SOCKS4a header
+if [ "$HAVE_READ_N" ]; then
+ read -r -n 1 vn # bash 2.0.3 does not support -n
+else
+ vn=$(dd bs=1 count=1 2>/dev/null)
+fi
+if [ "$vn" != $($ECHO "\04") ]; then
+ $ECHO "$SOCKSREPLY_FAILED"
+ echo "invalid socks version requested" >&2
+ exit
+fi
+
+if [ "$HAVE_READ_N" ]; then
+ read -r -n 1 cd
+else
+ cd=$(dd bs=1 count=1 2>/dev/null)
+fi
+if [ "$cd" != $($ECHO "\01") ]; then
+ $ECHO "$SOCKSREPLY_FAILED"
+ echo "invalid socks operation requested" >&2
+ exit
+fi
+
+a=$(dd bs=1 count=6 2>/dev/null)
+#echo a a a >/dev/tty
+#echo "$a" |od -c >/dev/tty
+#$ECHO "$a" |od -c >/dev/tty
+#echo>/dev/tty
+#echo a a a >/dev/tty
+if [ "$a" != "$($ECHO "}m\0\0\0\01")" ]; then
+ sleep 1
+ $ECHO "$SOCKSREPLY_FAILED"
+ echo "wrong socks address or port requested" >&2
+ exit
+fi
+
+if [ "$HAVE_READ_N" ]; then
+ read -r -n 7 u
+else
+ u=$(dd bs=1 count=7 2>/dev/null)
+fi
+if [ "$u" != "nobody" ]; then
+ $ECHO "$SOCKSREPLY_FAILED"
+ echo "wrong socks user requested" >&2
+ exit
+fi
+
+if [ "$HAVE_READ_N" ]; then
+ read -r -n 10 h
+else
+ h=$(dd bs=1 count=10 2>/dev/null)
+fi
+if [ "$h" != "localhost" ]; then
+ $ECHO "$SOCKSREPLY_FAILED"
+ echo "wrong socks address requested" >&2
+ exit
+fi
+
+# send ok status
+$ECHO "$SOCKSREPLY_OK"
+
+# perform echo function
+$CAT
diff --git a/socks4echo.sh b/socks4echo.sh
new file mode 100755
index 0000000..343d32f
--- /dev/null
+++ b/socks4echo.sh
@@ -0,0 +1,101 @@
+#! /bin/bash
+# $Id: socks4echo.sh,v 1.4 2006/03/21 18:48:53 gerhard Exp $
+
+# Copyright Gerhard Rieger 2004-2006
+# Published under the GNU General Public License V.2, see file COPYING
+
+# perform primitive simulation of a socks4 server with echo function via stdio.
+# accepts and answers correct SOCKS4 requests, but then just echoes data.
+# it is required for test.sh
+# for TCP, use this script as:
+# socat tcp-l:1080,reuseaddr,crlf system:"socks4echo.sh"
+
+# older bash and ksh do not have -n option to read command; we try dd then
+if echo a |read -n 1 null >/dev/null 2>&1; then
+ HAVE_READ_N=1
+else
+ HAVE_READ_N=
+fi
+
+if type socat >/dev/null 2>&1; then
+ SOCAT=socat
+else
+ SOCAT=./socat
+fi
+
+case `uname` in
+HP-UX|OSF1)
+ CAT="$SOCAT -u stdin stdout"
+ ;;
+*)
+ CAT=cat
+ ;;
+esac
+
+if [ $(echo "x\c") = "x" ]; then E=""
+elif [ $(echo -e "x\c") = "x" ]; then E="-e"
+else
+ echo "cannot suppress trailing newline on echo" >&2
+ exit 1
+fi
+ECHO="echo $E"
+
+if [ $($ECHO "\0101") = "A" ]; then
+ SOCKSREPLY_FAILED="\0\0133\0\0\0\0\0\0\c"
+ SOCKSREPLY_OK="\0\0132\0\0\0\0\0\0\c"
+else
+ SOCKSREPLY_FAILED="\0\133\0\0\0\0\0\0\c"
+ SOCKSREPLY_OK="\0\132\0\0\0\0\0\0\c"
+fi
+
+# read and parse SOCKS4 header
+if [ "$HAVE_READ_N" ]; then
+ read -r -n 1 vn # bash 2.0.3 does not support -n
+else
+ vn=$(dd bs=1 count=1 2>/dev/null)
+fi
+if [ "$vn" != $($ECHO "\04") ]; then
+ $ECHO "$SOCKSREPLY_FAILED"
+ echo "invalid socks version requested" >&2
+ exit
+fi
+
+if [ "$HAVE_READ_N" ]; then
+ read -r -n 1 cd
+else
+ cd=$(dd bs=1 count=1 2>/dev/null)
+fi
+if [ "$cd" != $($ECHO "\01") ]; then
+ $ECHO "$SOCKSREPLY_FAILED"
+ echo "invalid socks operation requested" >&2
+ exit
+fi
+
+if [ "$HAVE_READ_N" ]; then
+ read -r -n 6 a
+else
+ a=$(dd bs=1 count=6 2>/dev/null)
+fi
+if [ "$a" != "$($ECHO "}m bL6")" ]; then
+ $ECHO "$SOCKSREPLY_FAILED"
+ echo "$0: wrong socks address or port requested" >&2
+ echo "$0: expected $($ECHO "}m bL6"|od -t x1), received $($ECHO "$a"|od -t x1)" >&2
+ exit
+fi
+
+if [ "$HAVE_READ_N" ]; then
+ read -r -n 7 u
+else
+ u=$(dd bs=1 count=7 2>/dev/null)
+fi
+if [ "$u" != "nobody" ]; then
+ $ECHO "$SOCKSREPLY_FAILED"
+ echo "wrong socks user requested" >&2
+ exit
+fi
+
+# send ok status
+$ECHO "$SOCKSREPLY_OK"
+
+# perform echo function
+$CAT
diff --git a/sslcls.c b/sslcls.c
new file mode 100644
index 0000000..5bea174
--- /dev/null
+++ b/sslcls.c
@@ -0,0 +1,318 @@
+/* $Id: sslcls.c,v 1.8 2007/02/26 21:30:58 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* 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
+ */
+
+#include "config.h"
+#include "xioconfig.h" /* what features are enabled */
+
+#if WITH_SYCLS && WITH_OPENSSL
+
+#include "sysincludes.h"
+
+#include "mytypes.h"
+#include "compat.h"
+#include "errno.h"
+
+#include "error.h"
+#include "filan.h"
+#include "sysutils.h"
+#include "sycls.h"
+
+void sycSSL_load_error_strings(void) {
+ Debug("SSL_load_error_strings()");
+ SSL_load_error_strings();
+ Debug("SSL_load_error_strings() ->");
+}
+
+int sycSSL_library_init(void) {
+ int result;
+ Debug("SSL_library_init()");
+ result = SSL_library_init();
+ Debug1("SSL_library_init() -> %d", result);
+ return result;
+}
+
+SSL_METHOD *sycSSLv2_client_method(void) {
+ SSL_METHOD *result;
+ Debug("SSLv2_client_method()");
+ result = SSLv2_client_method();
+ Debug1("SSLv2_client_method() -> %p", result);
+ return result;
+}
+
+SSL_METHOD *sycSSLv2_server_method(void) {
+ SSL_METHOD *result;
+ Debug("SSLv2_server_method()");
+ result = SSLv2_server_method();
+ Debug1("SSLv2_server_method() -> %p", result);
+ return result;
+}
+
+SSL_METHOD *sycSSLv3_client_method(void) {
+ SSL_METHOD *result;
+ Debug("SSLv3_client_method()");
+ result = SSLv3_client_method();
+ Debug1("SSLv3_client_method() -> %p", result);
+ return result;
+}
+
+SSL_METHOD *sycSSLv3_server_method(void) {
+ SSL_METHOD *result;
+ Debug("SSLv3_server_method()");
+ result = SSLv3_server_method();
+ Debug1("SSLv3_server_method() -> %p", result);
+ return result;
+}
+
+SSL_METHOD *sycSSLv23_client_method(void) {
+ SSL_METHOD *result;
+ Debug("SSLv23_client_method()");
+ result = SSLv23_client_method();
+ Debug1("SSLv23_client_method() -> %p", result);
+ return result;
+}
+
+SSL_METHOD *sycSSLv23_server_method(void) {
+ SSL_METHOD *result;
+ Debug("SSLv23_server_method()");
+ result = SSLv23_server_method();
+ Debug1("SSLv23_server_method() -> %p", result);
+ return result;
+}
+
+SSL_METHOD *sycTLSv1_client_method(void) {
+ SSL_METHOD *result;
+ Debug("TLSv1_client_method()");
+ result = TLSv1_client_method();
+ Debug1("TLSv1_client_method() -> %p", result);
+ return result;
+}
+
+SSL_METHOD *sycTLSv1_server_method(void) {
+ SSL_METHOD *result;
+ Debug("TLSv1_server_method()");
+ result = TLSv1_server_method();
+ Debug1("TLSv1_server_method() -> %p", result);
+ return result;
+}
+
+SSL_CTX *sycSSL_CTX_new(SSL_METHOD *method) {
+ SSL_CTX *result;
+ Debug1("SSL_CTX_new(%p)", method);
+ result = SSL_CTX_new(method);
+ Debug1("SSL_CTX_new() -> %p", result);
+ return result;
+}
+
+SSL *sycSSL_new(SSL_CTX *ctx) {
+ SSL *result;
+ Debug1("SSL_new(%p)", ctx);
+ result = SSL_new(ctx);
+ Debug1("SSL_new() -> %p", result);
+ return result;
+}
+
+int sycSSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
+ const char *CApath) {
+ int result;
+ Debug7("SSL_CTX_load_verify_locations(%p, %s%s%s, %s%s%s)", ctx,
+ CAfile?"\"":"", CAfile?CAfile:NULL, CAfile?"\"":"",
+ CApath?"\"":"", CApath?CApath:NULL, CApath?"\"":"");
+ result = SSL_CTX_load_verify_locations(ctx, CAfile, CApath);
+ Debug1("SSL_CTX_load_verify_locations() -> %d", result);
+ return result;
+}
+
+int sycSSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) {
+ int result;
+ Debug3("SSL_CTX_use_certificate_file(%p, \"%s\", %d)", ctx, file, type);
+ result = SSL_CTX_use_certificate_file(ctx, file, type);
+ Debug1("SSL_CTX_use_certificate_file() -> %d", result);
+ return result;
+}
+
+int sycSSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) {
+ int result;
+ Debug2("SSL_CTX_use_certificate_chain_file(%p, \"%s\")", ctx, file);
+ result = SSL_CTX_use_certificate_chain_file(ctx, file);
+ Debug1("SSL_CTX_use_certificate_chain_file() -> %d", result);
+ return result;
+}
+
+int sycSSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
+ int result;
+ Debug3("SSL_CTX_use_PrivateKey_file(%p, \"%s\", %d)", ctx, file, type);
+ result = SSL_CTX_use_PrivateKey_file(ctx, file, type);
+ Debug1("SSL_CTX_use_PrivateKey_file() -> %d", result);
+ return result;
+}
+
+void sycSSL_CTX_set_verify(SSL_CTX *ctx, int mode,
+ int (*verify_callback)(int, X509_STORE_CTX *)) {
+ Debug3("SSL_CTX_set_verify(%p, %u, %p)", ctx, mode, verify_callback);
+ SSL_CTX_set_verify(ctx, mode, verify_callback);
+ Debug("SSL_CTX_set_verify() -> ");
+}
+
+int sycSSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) {
+ int result;
+ Debug2("SSL_CTX_set_cipher_list(%p, \"%s\")", ctx, str);
+ result = SSL_CTX_set_cipher_list(ctx, str);
+ Debug1("SSL_CTX_set_cipher_list() -> %d", result);
+ return result;
+}
+
+int sycSSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh) {
+ int result;
+ Debug2("SSL_CTX_set_tmp_dh(%p, %p)", ctx, dh);
+ result = SSL_CTX_set_tmp_dh(ctx, dh);
+ Debug1("SSL_CTX_set_tmp_dh() -> %d", result);
+ return result;
+}
+
+int sycSSL_set_cipher_list(SSL *ssl, const char *str) {
+ int result;
+ Debug2("SSL_set_cipher_list(%p, \"%s\")", ssl, str);
+ result = SSL_set_cipher_list(ssl, str);
+ Debug1("SSL_set_cipher_list() -> %d", result);
+ return result;
+}
+
+long sycSSL_get_verify_result(SSL *ssl) {
+ long result;
+ Debug1("SSL_get_verify_result(%p)", ssl);
+ result = SSL_get_verify_result(ssl);
+ Debug1("SSL_get_verify_result() -> %lx", result);
+ return result;
+}
+
+int sycSSL_set_fd(SSL *ssl, int fd) {
+ int result;
+ Debug2("SSL_set_fd(%p, %d)", ssl, fd);
+ result = SSL_set_fd(ssl, fd);
+ Debug1("SSL_set_fd() -> %d", result);
+ return result;
+}
+
+int sycSSL_connect(SSL *ssl) {
+ int result;
+ Debug1("SSL_connect(%p)", ssl);
+ result = SSL_connect(ssl);
+ Debug1("SSL_connect() -> %d", result);
+ return result;
+}
+
+int sycSSL_accept(SSL *ssl) {
+ int result;
+ Debug1("SSL_accept(%p)", ssl);
+ result = SSL_accept(ssl);
+ Debug1("SSL_accept() -> %d", result);
+ return result;
+}
+
+int sycSSL_read(SSL *ssl, void *buf, int num) {
+ int result;
+ Debug3("SSL_read(%p, %p, %d)", ssl, buf, num);
+ result = SSL_read(ssl, buf, num);
+ Debug1("SSL_read() -> %d", result);
+ return result;
+}
+
+int sycSSL_pending(SSL *ssl) {
+ int result;
+ Debug1("SSL_pending(%p)", ssl);
+ result = SSL_pending(ssl);
+ Debug1("SSL_pending() -> %d", result);
+ return result;
+}
+
+int sycSSL_write(SSL *ssl, const void *buf, int num) {
+ int result;
+ Debug3("SSL_write(%p, %p, %d)", ssl, buf, num);
+ result = SSL_write(ssl, buf, num);
+ Debug1("SSL_write() -> %d", result);
+ return result;
+}
+
+X509 *sycSSL_get_peer_certificate(SSL *ssl) {
+ X509 *result;
+ Debug1("SSL_get_peer_certificate(%p)", ssl);
+ result = SSL_get_peer_certificate(ssl);
+ if (result) {
+ Debug1("SSL_get_peer_certificate() -> %p", result);
+ } else {
+ Debug("SSL_get_peer_certificate() -> NULL");
+ }
+ return result;
+}
+
+int sycSSL_shutdown(SSL *ssl) {
+ int result;
+ Debug1("SSL_shutdown(%p)", ssl);
+ result = SSL_shutdown(ssl);
+ Debug1("SSL_shutdown() -> %d", result);
+ return result;
+}
+
+void sycSSL_CTX_free(SSL_CTX *ctx) {
+ Debug1("SSL_CTX_free(%p)", ctx);
+ SSL_CTX_free(ctx);
+ Debug("SSL_CTX_free() -> void");
+ return;
+}
+
+void sycSSL_free(SSL *ssl) {
+ Debug1("SSL_free(%p)", ssl);
+ SSL_free(ssl);
+ Debug("SSL_free() -> void");
+ return;
+}
+
+int sycRAND_egd(const char *path) {
+ int result;
+ Debug1("RAND_egd(\"%s\")", path);
+ result = RAND_egd(path);
+ Debug1("RAND_egd() -> %d", result);
+ return result;
+}
+
+DH *sycPEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u) {
+ DH *result;
+ Debug4("PEM_read_bio_DHparams(%p, %p, %p, %p)",
+ bp, x, cb, u);
+ result = PEM_read_bio_DHparams(bp, x, cb, u);
+ if (result) {
+ /*Debug2("PEM_read_bio_DHparams(, {%p},,) -> %p", *x, result);*/
+ Debug1("PEM_read_bio_DHparams() -> %p", result);
+ } else {
+ Debug("PEM_read_bio_DHparams() -> NULL");
+ }
+ return result;
+}
+
+BIO *sycBIO_new_file(const char *filename, const char *mode) {
+ BIO *result;
+ Debug2("BIO_new_file(\"%s\", \"%s\")", filename, mode);
+ result = BIO_new_file(filename, mode);
+ if (result) {
+ Debug1("BIO_new_file() -> %p", result);
+ } else {
+ Debug("BIO_new_file() -> NULL");
+ }
+ return result;
+}
+
+#if WITH_FIPS
+int sycFIPS_mode_set(int onoff) {
+ int result;
+ Debug1("FIPS_mode_set(%d)", onoff);
+ result = FIPS_mode_set(onoff);
+ Debug1("FIPS_mode_set() -> %d", result);
+ return result;
+}
+#endif /* WITH_FIPS */
+
+#endif /* WITH_SYCLS && WITH_OPENSSL */
diff --git a/sslcls.h b/sslcls.h
new file mode 100644
index 0000000..e3de001
--- /dev/null
+++ b/sslcls.h
@@ -0,0 +1,102 @@
+/* $Id: sslcls.h,v 1.9 2007/02/26 21:30:58 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __sslcls_h_included
+#define __sslcls_h_included 1
+
+#if WITH_SYCLS
+#if WITH_OPENSSL
+
+void sycSSL_load_error_strings(void);
+int sycSSL_library_init(void);
+SSL_METHOD *sycSSLv2_client_method(void);
+SSL_METHOD *sycSSLv2_server_method(void);
+SSL_METHOD *sycSSLv3_client_method(void);
+SSL_METHOD *sycSSLv3_server_method(void);
+SSL_METHOD *sycSSLv23_client_method(void);
+SSL_METHOD *sycSSLv23_server_method(void);
+SSL_METHOD *sycTLSv1_client_method(void);
+SSL_METHOD *sycTLSv1_server_method(void);
+SSL_CTX *sycSSL_CTX_new(SSL_METHOD *method);
+SSL *sycSSL_new(SSL_CTX *ctx);
+int sycSSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
+ const char *CApath);
+int sycSSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
+int sycSSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
+int sycSSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
+void sycSSL_CTX_set_verify(SSL_CTX *ctx, int mode,
+ int (*verify_callback)(int, X509_STORE_CTX *));
+int sycSSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh);
+int sycSSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str);
+int sycSSL_set_cipher_list(SSL *ssl, const char *str);
+long sycSSL_get_verify_result(SSL *ssl);
+int sycSSL_set_fd(SSL *ssl, int fd);
+int sycSSL_connect(SSL *ssl);
+int sycSSL_accept(SSL *ssl);
+int sycSSL_read(SSL *ssl, void *buf, int num);
+int sycSSL_pending(SSL *ssl);
+int sycSSL_write(SSL *ssl, const void *buf, int num);
+X509 *sycSSL_get_peer_certificate(SSL *ssl);
+int sycSSL_shutdown(SSL *ssl);
+void sycSSL_CTX_free(SSL_CTX *ctx);
+void sycSSL_free(SSL *ssl);
+int sycRAND_egd(const char *path);
+
+DH *sycPEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u);
+
+BIO *sycBIO_new_file(const char *filename, const char *mode);
+
+int sycFIPS_mode_set(int onoff);
+
+#endif /* WITH_OPENSSL */
+
+#else /* !WITH_SYCLS */
+
+#if WITH_OPENSSL
+
+#define sycSSL_load_error_strings() SSL_load_error_strings()
+#define sycSSL_library_init() SSL_library_init()
+#define sycSSLv2_client_method() SSLv2_client_method()
+#define sycSSLv2_server_method() SSLv2_server_method()
+#define sycSSLv3_client_method() SSLv3_client_method()
+#define sycSSLv3_server_method() SSLv3_server_method()
+#define sycSSLv23_client_method() SSLv23_client_method()
+#define sycSSLv23_server_method() SSLv23_server_method()
+#define sycTLSv1_client_method() TLSv1_client_method()
+#define sycTLSv1_server_method() TLSv1_server_method()
+#define sycSSL_CTX_new(m) SSL_CTX_new(m)
+#define sycSSL_new(c) SSL_new(c)
+#define sycSSL_CTX_load_verify_locations(c,f,p) SSL_CTX_load_verify_locations(c,f,p)
+#define sycSSL_CTX_use_certificate_file(c,f,t) SSL_CTX_use_certificate_file(c,f,t)
+#define sycSSL_CTX_use_certificate_chain_file(c,f) SSL_CTX_use_certificate_chain_file(c,f)
+#define sycSSL_CTX_use_PrivateKey_file(c,f,t) SSL_CTX_use_PrivateKey_file(c,f,t)
+#define sycSSL_CTX_set_verify(c,m,v) SSL_CTX_set_verify(c,m,v)
+#define sycSSL_CTX_set_tmp_dh(c,d) SSL_CTX_set_tmp_dh(c,d)
+#define sycSSL_CTX_set_cipher_list(c,s) SSL_CTX_set_cipher_list(c,s)
+#define sycSSL_set_cipher_list(s,t) SSL_set_cipher_list(s,t)
+#define sycSSL_get_verify_result(s) SSL_get_verify_result(s)
+#define sycSSL_set_fd(s,f) SSL_set_fd(s,f)
+#define sycSSL_connect(s) SSL_connect(s)
+#define sycSSL_accept(s) SSL_accept(s)
+#define sycSSL_read(s,b,n) SSL_read(s,b,n)
+#define sycSSL_pending(s) SSL_pending(s)
+#define sycSSL_write(s,b,n) SSL_write(s,b,n)
+#define sycSSL_get_peer_certificate(s) SSL_get_peer_certificate(s)
+#define sycSSL_shutdown(s) SSL_shutdown(s)
+#define sycSSL_CTX_free(c) SSL_CTX_free(c)
+#define sycSSL_free(s) SSL_free(s)
+#define sycRAND_egd(p) RAND_egd(p)
+
+#define sycPEM_read_bio_DHparams(b,x,p,u) PEM_read_bio_DHparams(b,x,p,u)
+
+#define sycBIO_new_file(f,m) BIO_new_file(f,m)
+
+#endif /* WITH_OPENSSL */
+
+#define sycFIPS_mode_set(o) FIPS_mode_set(o)
+
+#endif /* !WITH_SYCLS */
+
+#endif /* !defined(__sslcls_h_included) */
+
diff --git a/sycls.c b/sycls.c
new file mode 100644
index 0000000..d30d9b3
--- /dev/null
+++ b/sycls.c
@@ -0,0 +1,1503 @@
+/* $Id: sycls.c,v 1.75 2007/03/06 21:04:12 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* 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
+ */
+
+#include "config.h"
+#include "xioconfig.h" /* what features are enabled */
+
+#if WITH_SYCLS
+
+#include "sysincludes.h"
+
+#include "mytypes.h"
+#include "compat.h"
+#include "errno.h"
+
+#include "error.h"
+#include "filan.h"
+#include "sysutils.h"
+#include "sycls.h"
+
+
+mode_t Umask(mode_t mask) {
+ mode_t result;
+ int _errno;
+ Debug1("umask("F_mode")", mask);
+ result = umask(mask);
+ _errno = errno;
+ Debug1("umask() -> "F_mode, result);
+ errno = _errno;
+ return result;
+}
+
+int Open(const char *pathname, int flags, mode_t mode) {
+ int result, _errno;
+ Debug3("open(\"%s\", 0%o, 0%03o)", pathname, flags, mode);
+ result = open(pathname, flags, mode);
+ _errno = errno;
+ Info4("open(\"%s\", 0%o, 0%03o) -> %d", pathname, flags, mode, result);
+ errno = _errno;
+ return result;
+}
+
+int Creat(const char *pathname, mode_t mode) {
+ int result, _errno;
+ Debug2("creat(\"%s\", 0%03o)", pathname, mode);
+ result = creat(pathname, mode);
+ _errno = errno;
+ Info3("creat(\"%s\", 0%03o) -> %d", pathname, mode, result);
+ errno = _errno;
+ return result;
+}
+
+off_t Lseek(int fildes, off_t offset, int whence) {
+ int _errno;
+ off_t result;
+ Debug3("lseek(%d, "F_off", %d)", fildes, offset, whence);
+ result = lseek(fildes, offset, whence);
+ _errno = errno;
+ Debug1("lseek() -> "F_off, result);
+ errno = _errno;
+ return result;
+}
+
+#if HAVE_LSEEK64
+off64_t Lseek64(int fildes, off64_t offset, int whence) {
+ int _errno;
+ off64_t result;
+ Debug3("lseek64(%d, "F_off64", %d)", fildes, offset, whence);
+ result = lseek64(fildes, offset, whence);
+ _errno = errno;
+ Debug1("lseek64() -> "F_off64, result);
+ errno = _errno;
+ return result;
+}
+#endif /* HAVE_LSEEK64 */
+
+pid_t Getpid(void) {
+ pid_t result;
+ int _errno;
+ Debug("getpid()");
+ result = getpid();
+ _errno = errno;
+ Debug1("getpid() -> "F_pid, result);
+ errno = _errno;
+ return result;
+}
+
+pid_t Getppid(void) {
+ pid_t result;
+ int _errno;
+ Debug("getppid()");
+ result = getppid();
+ _errno = errno;
+ Debug1("getppid() -> "F_pid, result);
+ errno = _errno;
+ return result;
+}
+
+pid_t Getpgrp(void) {
+ pid_t result;
+ int _errno;
+ Debug("getpgrp()");
+ result = getpgrp();
+ _errno = errno;
+ Debug1("getpgrp() -> "F_pid, result);
+ errno = _errno;
+ return result;
+}
+
+#if 0 /* does not compile for FreeBSD */
+/* setpgrp() is not BSD compatible, needs setpgid(..., ...) instead */
+int Setpgrp(void) {
+ int result, _errno;
+ Debug("setpgrp()");
+ result = setpgrp();
+ _errno = errno;
+ Debug1("setpgrp() -> %d", result);
+ errno = _errno;
+ return result;
+}
+#endif
+
+#if HAVE_GETPGID
+int Getpgid(pid_t pid) {
+ pid_t result;
+ int _errno;
+ Debug1("getpgid("F_pid")", pid);
+ result = getpgid(pid);
+ _errno = errno;
+ Debug1("getpgid() -> "F_pid, result);
+ errno = _errno;
+ return result;
+}
+#endif
+
+int Setpgid(pid_t pid, pid_t pgid) {
+ int result, _errno;
+ Debug2("setpgid("F_pid", "F_pid")", pid, pgid);
+ result = setpgid(pid, pgid);
+ _errno = errno;
+ Debug1("setpgid() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+pid_t Tcgetpgrp(int fd) {
+ int result, _errno;
+ Debug1("tcgetpgrp(%d)", fd);
+ result = tcgetpgrp(fd);
+ _errno = errno;
+ Debug1("tcgetpgrp() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+int Tcsetpgrp(int fd, pid_t pgrpid) {
+ int result, _errno;
+ Debug2("tcsetpgrp(%d, "F_pid")", fd, pgrpid);
+ result = tcsetpgrp(fd, pgrpid);
+ _errno = errno;
+ Debug1("tcsetpgrp() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+#if HAVE_GETSID
+pid_t Getsid(pid_t pid) {
+ int result, _errno;
+ Debug1("getsid("F_pid")", pid);
+ result = getsid(pid);
+ _errno = errno;
+ Debug1("getsid() -> "F_pid, result);
+ errno = _errno;
+ return result;
+}
+#endif
+
+pid_t Setsid(void) {
+ int result, _errno;
+ Debug("setsid()");
+ result = setsid();
+ _errno = errno;
+ Debug1("setsid() -> "F_pid, result);
+ errno = _errno;
+ return result;
+}
+
+uid_t Getuid(void) {
+ uid_t result;
+ int _errno;
+ Debug("getuid()");
+ result = getuid();
+ _errno = errno;
+ Debug1("getuid() -> "F_uid, result);
+ errno = _errno;
+ return result;
+}
+
+uid_t Geteuid(void) {
+ uid_t result;
+ int _errno;
+ Debug("geteuid()");
+ result = geteuid();
+ _errno = errno;
+ Debug1("geteuid() -> "F_uid, result);
+ errno = _errno;
+ return result;
+}
+
+int Setuid(uid_t uid) {
+ int result, _errno;
+ Debug1("setuid("F_uid")", uid);
+ result = setuid(uid);
+ _errno = errno;
+ Debug1("setuid() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+gid_t Getgid(void) {
+ gid_t result;
+ int _errno;
+ Debug("getgid()");
+ result = getgid();
+ _errno = errno;
+ Debug1("getgid() -> "F_gid, result);
+ errno = _errno;
+ return result;
+}
+
+gid_t Getegid(void) {
+ gid_t result;
+ int _errno;
+ Debug("getegid()");
+ result = getegid();
+ _errno = errno;
+ Debug1("getegid() -> "F_gid, result);
+ errno = _errno;
+ return result;
+}
+
+int Setgid(gid_t gid) {
+ int result, _errno;
+ Debug1("setgid("F_gid")", gid);
+ result = setgid(gid);
+ _errno = errno;
+ Debug1("setgid() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+int Initgroups(const char *user, gid_t group) {
+ int result, _errno;
+ Debug2("initgroups(\"%s\", "F_gid")", user, group);
+ result = initgroups(user, group);
+ _errno = errno;
+ Debug1("initgroups() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+int Getgroups(int size, gid_t list[]) {
+ int result, _errno;
+ Debug2("getgroups(%d, "F_gid",...)", size, list[0]);
+ result = getgroups(size, list);
+ _errno = errno;
+ Debug1("getgroups() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+#if HAVE_SETGROUPS
+int Setgroups(size_t size, const gid_t *list) {
+ int result, _errno;
+ Debug2("setgroups("F_Zu", "F_gid",...)", size, list[0]);
+ result = setgroups(size, list);
+ _errno = errno;
+ Debug1("setgroups() -> %d", result);
+ errno = _errno;
+ return result;
+}
+#endif
+
+int Chdir(const char *path) {
+ int result, _errno;
+ Debug1("chdir(\"%s\")", path);
+ result = chdir(path);
+ _errno = errno;
+ Debug1("chdir() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+int Chroot(const char *path) {
+ int result, _errno;
+ Debug1("chroot(\"%s\")", path);
+ result = chroot(path);
+ _errno = errno;
+ Debug1("chroot() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+int Gettimeofday(struct timeval *tv, struct timezone *tz) {
+ int result, _errno;
+#if WITH_MSGLEVEL <= E_DEBUG
+ if (tz) {
+ Debug3("gettimeofday(%p, {%d,%d})",
+ tv, tz->tz_minuteswest, tz->tz_dsttime);
+ } else {
+ Debug1("gettimeofday(%p, NULL)", tv);
+ }
+#endif /* WITH_MSGLEVEL <= E_DEBUG */
+ result = gettimeofday(tv, tz);
+ _errno = errno;
+#if WITH_MSGLEVEL <= E_DEBUG
+ if (tz) {
+ Debug5("gettimeofday({%ld,%ld}, {%d,%d}) -> %d",
+ tv->tv_sec, tv->tv_usec, tz->tz_minuteswest, tz->tz_dsttime,
+ result);
+ } else {
+ Debug3("gettimeofday({%ld,%ld},) -> %d",
+ tv->tv_sec, tv->tv_usec, result);
+ }
+#endif /* WITH_MSGLEVEL <= E_DEBUG */
+ errno = _errno;
+ return result;
+}
+
+int Mknod(const char *pathname, mode_t mode, dev_t dev) {
+ int result, _errno;
+ Debug3("mknod(\"%s\", 0%o, %d)", pathname, mode, dev);
+ result = mknod(pathname, mode, dev);
+ _errno = errno;
+ Debug1("mknod() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+int Mkfifo(const char *pathname, mode_t mode) {
+ int result, _errno;
+ Debug2("mkfifo(\"%s\", 0%o)", pathname, mode);
+ result = mkfifo(pathname, mode);
+ _errno = errno;
+ Debug1("mkfifo() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+static void prtstat(const char *func, struct stat *buf, int result) {
+ char txt[256], *t = txt;
+
+ t += sprintf(t, "%s(, {"F_st_dev","F_st_ino","F_mode","F_st_nlink","F_uid","F_gid,
+ func, buf->st_dev, buf->st_ino,
+ buf->st_mode, buf->st_nlink, buf->st_uid, buf->st_gid);
+#if HAVE_ST_RDEV
+ t += sprintf(t, ","F_st_dev, buf->st_rdev);
+#endif
+ t += sprintf(t, ","F_st_size, buf->st_size);
+#if HAVE_ST_BLKSIZE
+ t += sprintf(t, ","F_st_blksize, buf->st_blksize);
+#endif
+#if HAVE_ST_BLOCKS
+ t += sprintf(t, ","F_st_blocks, buf->st_blocks);
+#endif
+ sprintf(t, ",...}) -> %d", result);
+ Debug(txt);
+}
+
+#if defined(HAVE_STAT64) || defined(HAVE_FSTAT64) || defined(HAVE_LSTAT64)
+static void prtstat64(const char *func, struct stat64 *buf, int result) {
+ char txt[256], *t = txt;
+
+ if (result < 0) {
+ sprintf(t, "%s(, {}) -> %d", func, result);
+ } else {
+ t += sprintf(t, "%s(, {"F_st_dev","F_st64_ino","F_mode","F_st_nlink","F_uid","F_gid,
+ func, buf->st_dev, buf->st_ino,
+ buf->st_mode, buf->st_nlink, buf->st_uid, buf->st_gid);
+#if HAVE_ST_RDEV
+ t += sprintf(t, ","F_st_dev, buf->st_rdev);
+#endif
+ t += sprintf(t, ","F_st64_size, buf->st_size);
+#if HAVE_ST_BLKSIZE
+ t += sprintf(t, ","F_st_blksize, buf->st_blksize);
+#endif
+#if HAVE_ST_BLOCKS
+ t += sprintf(t, ","F_st64_blocks, buf->st_blocks);
+#endif
+ sprintf(t, ",...}) -> %d", result);
+ }
+ Debug(txt);
+}
+#endif /* defined(HAVE_STAT64) || defined(HAVE_FSTAT64) || defined(HAVE_LSTAT64) */
+
+int Stat(const char *file_name, struct stat *buf) {
+ int result, _errno;
+ Debug2("stat(%s, %p)", file_name, buf);
+ result = stat(file_name, buf);
+ _errno = errno;
+ prtstat("stat", buf, result);
+ errno = _errno;
+ return result;
+}
+
+#if HAVE_STAT64
+int Stat64(const char *file_name, struct stat64 *buf) {
+ int result, _errno;
+ Debug2("stat64(%s, %p)", file_name, buf);
+ result = stat64(file_name, buf);
+ _errno = errno;
+ prtstat64("stat64", buf, result);
+ errno = _errno;
+ return result;
+}
+#endif /* HAVE_STAT64 */
+
+int Fstat(int filedes, struct stat *buf) {
+ int result, _errno;
+ Debug2("fstat(%d, %p)", filedes, buf);
+ result = fstat(filedes, buf);
+ _errno = errno;
+ prtstat("fstat", buf, result);
+ errno = _errno;
+ return result;
+}
+
+#if HAVE_FSTAT64
+int Fstat64(int filedes, struct stat64 *buf) {
+ int result, _errno;
+ Debug2("fstat64(%d, %p)", filedes, buf);
+ result = fstat64(filedes, buf);
+ _errno = errno;
+ prtstat64("fstat64", buf, result);
+ errno = _errno;
+ return result;
+}
+#endif /* HAVE_FSTAT64 */
+
+int Lstat(const char *file_name, struct stat *buf) {
+ int result, _errno;
+ Debug2("lstat(%s, %p)", file_name, buf);
+ result = lstat(file_name, buf);
+ _errno = errno;
+ prtstat("lstat", buf, result);
+ errno = _errno;
+ return result;
+}
+
+#if HAVE_LSTAT64
+int Lstat64(const char *file_name, struct stat64 *buf) {
+ int result, _errno;
+ Debug2("lstat64(%s, %p)", file_name, buf);
+ result = lstat64(file_name, buf);
+ _errno = errno;
+ prtstat64("lstat64", buf, result);
+ errno = _errno;
+ return result;
+}
+#endif /* HAVE_LSTAT64 */
+
+int Dup(int oldfd) {
+ int newfd, _errno;
+ Debug1("dup(%d)", oldfd);
+ newfd = dup(oldfd);
+ _errno = errno;
+ Info2("dup(%d) -> %d", oldfd, newfd);
+ errno = _errno;
+ return newfd;
+}
+
+int Dup2(int oldfd, int newfd) {
+ int result, _errno;
+ Debug2("dup2(%d, %d)", oldfd, newfd);
+ result = dup2(oldfd, newfd);
+ _errno = errno;
+ Info3("dup2(%d, %d) -> %d", oldfd, newfd, result);
+ errno = _errno;
+ return result;
+}
+
+int Pipe(int filedes[2]) {
+ int result, _errno;
+ Debug1("pipe(%p)", filedes);
+ result = pipe(filedes);
+ _errno = errno;
+ Info3("pipe({%d,%d}) -> %d", filedes[0], filedes[1], result);
+ errno = _errno;
+ return result;
+}
+
+ssize_t Read(int fd, void *buf, size_t count) {
+ ssize_t result;
+ int _errno;
+ Debug3("read(%d, %p, "F_Zu")", fd, buf, count);
+ result = read(fd, buf, count);
+ _errno = errno;
+ Debug1("read -> "F_Zd, result);
+ errno = _errno;
+ return result;
+}
+
+ssize_t Write(int fd, const void *buf, size_t count) {
+ ssize_t result;
+ int _errno;
+ Debug3("write(%d, %p, "F_Zu")", fd, buf, count);
+ result = write(fd, buf, count);
+ _errno = errno;
+ Debug1("write -> "F_Zd, result);
+ errno = _errno;
+ return result;
+}
+
+int Fcntl(int fd, int cmd) {
+ int result, _errno;
+ Debug2("fcntl(%d, %d)", fd, cmd);
+ result = fcntl(fd, cmd);
+ _errno = errno;
+ Debug1("fcntl() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+int Fcntl_l(int fd, int cmd, long arg) {
+ int result, _errno;
+ Debug3("fcntl(%d, %d, %ld)", fd, cmd, arg);
+ result = fcntl(fd, cmd, arg);
+ _errno = errno;
+ Debug1("fcntl() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+int Fcntl_lock(int fd, int cmd, struct flock *l) {
+ int result, _errno;
+ Debug7("fcntl(%d, %d, {type=%hd,whence=%hd,start="F_off",len="F_off",pid="F_pid"})",
+ fd, cmd, l->l_type, l->l_whence, l->l_start, l->l_len, l->l_pid);
+ result = fcntl(fd, cmd, l);
+ _errno = errno;
+ Debug1("fcntl() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+int Ftruncate(int fd, off_t length) {
+ int retval, _errno;
+ Debug2("ftruncate(%d, "F_off")", fd, length);
+ retval = ftruncate(fd, length);
+ _errno = errno;
+ Debug1("ftruncate() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+#if HAVE_FTRUNCATE64
+int Ftruncate64(int fd, off64_t length) {
+ int retval, _errno;
+ Debug2("ftruncate64(%d, "F_off64")", fd, length);
+ retval = ftruncate64(fd, length);
+ _errno = errno;
+ Debug1("ftruncate64() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+#endif /* HAVE_FTRUNCATE64 */
+
+#if HAVE_FLOCK
+int Flock(int fd, int operation) {
+ int retval, _errno;
+ Debug2("flock(%d, %d)", fd, operation);
+ retval = flock(fd, operation);
+ _errno = errno;
+ Debug1("flock() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+#endif /* HAVE_FLOCK */
+
+int Ioctl(int d, int request, void *argp) {
+ int retval, _errno;
+ if (argp > (void *)0x10000) { /* fuzzy...*/
+ Debug4("ioctl(%d, 0x%x, %p{%lu})", d, request, argp, *(unsigned long *)argp);
+ } else {
+ Debug3("ioctl(%d, 0x%x, 0x%p)", d, request, argp);
+ }
+ retval = ioctl(d, request, argp);
+ _errno = errno;
+ Debug1("ioctl() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+int Close(int fd) {
+ int retval, _errno;
+ Info1("close(%d)", fd);
+ retval = close(fd);
+ _errno = errno;
+ Debug1("close() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+int Fchown(int fd, uid_t owner, gid_t group) {
+ int retval, _errno;
+ Debug3("fchown(%d, "F_uid", "F_gid")", fd, owner, group);
+ retval = fchown(fd, owner, group);
+ _errno = errno;
+ Debug1("fchown() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+int Fchmod(int fd, mode_t mode) {
+ int retval, _errno;
+ Debug2("fchmod(%d, 0%o)", fd, mode);
+ retval = fchmod(fd, mode);
+ _errno = errno;
+ Debug1("fchmod() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+int Unlink(const char *pathname) {
+ int retval, _errno;
+ Debug1("unlink(\"%s\")", pathname);
+ retval = unlink(pathname);
+ _errno = errno;
+ Debug1("unlink() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+int Symlink(const char *oldpath, const char *newpath) {
+ int retval, _errno;
+ Debug2("symlink(\"%s\", \"%s\")", oldpath, newpath);
+ retval = symlink(oldpath, newpath);
+ _errno = errno;
+ Debug1("symlink() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+int Readlink(const char *path, char *buf, size_t bufsiz) {
+ int retval, _errno;
+ Debug3("readlink(\"%s\", %p, "F_Zu")", path, buf, bufsiz);
+ retval = readlink(path, buf, bufsiz);
+ _errno = errno;
+ Debug1("readlink() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+int Chown(const char *path, uid_t owner, gid_t group) {
+ int retval, _errno;
+ Debug3("chown(\"%s\", "F_uid", "F_gid")", path, owner, group);
+ retval = chown(path, owner, group);
+ _errno = errno;
+ Debug1("chown() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+int Chmod(const char *path, mode_t mode) {
+ int retval, _errno;
+ Debug2("chmod(\"%s\", 0%o)", path, mode);
+ retval = chmod(path, mode);
+ _errno = errno;
+ Debug1("chmod() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+#if HAVE_POLL
+/* 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);
+ result = poll(ufds, nfds, timeout);
+ Debug2("poll(, {,, 0x%02hx}) -> %d", ufds[0].revents, result);
+ return result;
+}
+#endif /* HAVE_POLL */
+
+/* we only show the first word of the fd_set's; hope this is enough for most
+ cases. */
+int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ struct timeval *timeout) {
+ int result, _errno;
+#if HAVE_FDS_BITS
+ Debug7("select(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu."F_tv_usec")",
+ n, readfds->fds_bits[0], writefds->fds_bits[0],
+ exceptfds->fds_bits[0],
+ timeout?"&":"NULL/", timeout?timeout->tv_sec:0,
+ timeout?timeout->tv_usec:0);
+#else
+ Debug7("select(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu.%06u)",
+ n, readfds->__fds_bits[0], writefds->__fds_bits[0],
+ exceptfds->__fds_bits[0],
+ timeout?"&":"NULL/", timeout?timeout->tv_sec:0,
+ timeout?timeout->tv_usec:0);
+#endif
+ result = select(n, readfds, writefds, exceptfds, timeout);
+ _errno = errno;
+#if HAVE_FDS_BITS
+ Debug7("select -> (, 0x%lx, 0x%lx, 0x%lx, %s%lu."F_tv_usec"), %d",
+ readfds->fds_bits[0], writefds->fds_bits[0], exceptfds->fds_bits[0],
+ timeout?"&":"NULL/", timeout?timeout->tv_sec:0,
+ timeout?timeout->tv_usec:0, result);
+#else
+ Debug7("select -> (, 0x%lx, 0x%lx, 0x%lx, %s%lu.%06u), %d",
+ readfds->__fds_bits[0], writefds->__fds_bits[0],
+ exceptfds->__fds_bits[0],
+ timeout?"&":"NULL/", timeout?timeout->tv_sec:0,
+ timeout?timeout->tv_usec:0, result);
+#endif
+ errno = _errno;
+ return result;
+}
+
+pid_t Fork(void) {
+ pid_t pid;
+ int _errno;
+ Debug("fork()");
+ pid = fork();
+ _errno = errno;
+ Debug1("fork() -> %d", pid); /* attention: called twice! */
+ errno = _errno;
+ return pid;
+}
+
+pid_t Waitpid(pid_t pid, int *status, int options) {
+ int _errno;
+ pid_t retval;
+ Debug3("waitpid("F_pid", %p, %d)", pid, status, options);
+ retval = waitpid(pid, status, options);
+ _errno = errno;
+ Debug2("waitpid(, {%d}, ) -> "F_pid, *status, retval);
+ errno = _errno;
+ return retval;
+}
+
+sighandler_t Signal(int signum, sighandler_t handler) {
+ int _errno;
+ sighandler_t retval;
+ Debug2("signal(%d, %p)", signum, handler);
+ retval = signal(signum, handler);
+ _errno = errno;
+ Debug1("signal() -> %p", retval);
+ errno = _errno;
+ return retval;
+}
+
+#if HAVE_SIGACTION
+int Sigaction(int signum, const struct sigaction *act,
+ struct sigaction *oldact) {
+ int retval;
+ Debug3("sigaction(%d, %p, %p)", signum, act, oldact);
+ retval = sigaction(signum, act, oldact);
+ Debug1("sigaction() -> %d", retval);
+ return retval;
+}
+#endif /* HAVE_SIGACTION */
+
+int Sigprocmask(int how, const sigset_t *set, sigset_t *oset) {
+ int retval;
+ Debug3("sigprocmask(%d, %p, %p)", how, set, oset);
+ retval = sigprocmask(how, set, oset);
+ Debug1("sigprocmask() -> %d", retval);
+ return retval;
+}
+
+unsigned int Alarm(unsigned int seconds) {
+ unsigned int retval;
+ Debug1("alarm(%u)", seconds);
+ retval = alarm(seconds);
+ Debug1("alarm() -> %u", retval);
+ return retval;
+}
+
+int Kill(pid_t pid, int sig) {
+ int retval, _errno;
+ Debug2("kill("F_pid", %d)", pid, sig);
+ retval = kill(pid, sig);
+ _errno = errno;
+ Debug1("kill() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+int Link(const char *oldpath, const char *newpath) {
+ int retval, _errno;
+ Debug2("link(\"%s\", \"%s\")", oldpath, newpath);
+ retval = link(oldpath, newpath);
+ _errno = errno;
+ Debug1("link() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+int Execvp(const char *file, char *const argv[]) {
+ int result, _errno;
+ if (argv[1] == NULL)
+ Debug2("execvp(\"%s\", \"%s\")", file, argv[0]);
+ else if (argv[2] == NULL)
+ Debug3("execvp(\"%s\", \"%s\" \"%s\")", file, argv[0], argv[1]);
+ else if (argv[3] == NULL)
+ Debug4("execvp(\"%s\", \"%s\" \"%s\" \"%s\")", file, argv[0], argv[1], argv[2]);
+ else if (argv[4] == NULL)
+ Debug5("execvp(\"%s\", \"%s\" \"%s\" \"%s\" \"%s\")", file, argv[0], argv[1], argv[2], argv[3]);
+ else if (argv[5] == NULL)
+ Debug6("execvp(\"%s\", \"%s\" \"%s\" \"%s\" \"%s\" \"%s\")", file, argv[0], argv[1], argv[2], argv[3], argv[4]);
+ else
+ Debug6("execvp(\"%s\", \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" ...)", file, argv[0], argv[1], argv[2], argv[3], argv[4]);
+
+ result = execvp(file, argv);
+ _errno = errno;
+ Debug1("execvp() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+int System(const char *string) {
+ int result, _errno;
+ Debug1("system(\"%s\")", string);
+ result = system(string);
+ _errno = errno;
+ Debug1("system() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+int Socketpair(int d, int type, int protocol, int sv[2]) {
+ int result, _errno;
+ Debug4("socketpair(%d, %d, %d, %p)", d, type, protocol, sv);
+ result = socketpair(d, type, protocol, sv);
+ _errno = errno;
+ Info6("socketpair(%d, %d, %d, {%d,%d}) -> %d", d, type, protocol, sv[0], sv[1], result);
+ errno = _errno;
+ return result;
+}
+
+#if _WITH_SOCKET
+int Socket(int domain, int type, int protocol) {
+ int result, _errno;
+ Debug3("socket(%d, %d, %d)", domain, type, protocol);
+ result = socket(domain, type, protocol);
+ _errno = errno;
+ Info4("socket(%d, %d, %d) -> %d", domain, type, protocol, result);
+ errno = _errno;
+ return result;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Bind(int sockfd, struct sockaddr *my_addr, int addrlen) {
+ int result, _errno;
+ char infobuff[256];
+
+ sockaddr_info(my_addr, addrlen, infobuff, sizeof(infobuff));
+ Debug3("bind(%d, %s, "F_Zd")", sockfd, infobuff, addrlen);
+ result = bind(sockfd, my_addr, addrlen);
+ _errno = errno;
+ Debug1("bind() -> %d", result);
+ errno = _errno;
+ return result;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Connect(int sockfd, const struct sockaddr *serv_addr, int addrlen) {
+ int result, _errno;
+ char infobuff[256];
+
+ /*sockaddr_info(serv_addr, infobuff, sizeof(infobuff));
+ Debug3("connect(%d, %s, "F_Zd")", sockfd, infobuff, addrlen);*/
+#if 0
+ Debug18("connect(%d,{0x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x}, "F_Zd")",
+ sockfd,
+ ((unsigned char *)serv_addr)[0], ((unsigned char *)serv_addr)[1],
+ ((unsigned char *)serv_addr)[2], ((unsigned char *)serv_addr)[3],
+ ((unsigned char *)serv_addr)[4], ((unsigned char *)serv_addr)[5],
+ ((unsigned char *)serv_addr)[6], ((unsigned char *)serv_addr)[7],
+ ((unsigned char *)serv_addr)[8], ((unsigned char *)serv_addr)[9],
+ ((unsigned char *)serv_addr)[10], ((unsigned char *)serv_addr)[11],
+ ((unsigned char *)serv_addr)[12], ((unsigned char *)serv_addr)[13],
+ ((unsigned char *)serv_addr)[14], ((unsigned char *)serv_addr)[15],
+ addrlen);
+#else
+ Debug4("connect(%d, {%d,%s}, "F_Zd")",
+ sockfd, serv_addr->sa_family,
+ sockaddr_info(serv_addr, addrlen, infobuff, sizeof(infobuff)),
+ addrlen);
+#endif
+ result = connect(sockfd, serv_addr, addrlen);
+ _errno = errno;
+ Debug1("connect() -> %d", result);
+ errno = _errno;
+ return result;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Listen(int s, int backlog) {
+ int result, _errno;
+ Debug2("listen(%d, %d)", s, backlog);
+ result = listen(s, backlog);
+ _errno = errno;
+ Debug1("listen() -> %d", result);
+ errno = _errno;
+ return result;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+/* don't forget to handle EINTR when using Accept() ! */
+int Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
+ int result, _errno;
+
+ Debug3("accept(%d, %p, %p)", s, addr, addrlen);
+ result = accept(s, addr, addrlen);
+ _errno = errno;
+ if (result >= 0) {
+ char infobuff[256];
+ sockaddr_info(addr, *addrlen, infobuff, sizeof(infobuff));
+ Info5("accept(%d, {%d, %s}, "F_Zd") -> %d", s,
+ addr->sa_family,
+ sockaddr_info(addr, *addrlen, infobuff, sizeof(infobuff)),
+ *addrlen, result);
+ } else {
+ Debug1("accept(,,) -> %d", result);
+ }
+ errno = _errno;
+ return result;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Getsockname(int s, struct sockaddr *name, socklen_t *namelen) {
+ int result, _errno;
+ char infobuff[256];
+
+ Debug4("getsockname(%d, %p, %p{"F_socklen"})", s, name, namelen, *namelen);
+ result = getsockname(s, name, namelen);
+ _errno = errno;
+ /*Debug2("getsockname(,, {"F_socklen"}) -> %d",
+ *namelen, result);*/
+ Debug3("getsockname(, {%s}, {"F_socklen"}) -> %d",
+ sockaddr_info(name, *namelen, infobuff, sizeof(infobuff)),
+ *namelen, result);
+ errno = _errno;
+ return result;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Getpeername(int s, struct sockaddr *name, socklen_t *namelen) {
+ int result, _errno;
+ char infobuff[256];
+
+ Debug4("getpeername(%d, %p, %p{"F_socklen"})", s, name, namelen, *namelen);
+ result = getpeername(s, name, namelen);
+ _errno = errno;
+ sockaddr_info(name, *namelen, infobuff, sizeof(infobuff));
+ Debug3("getpeername(, {%s}, {"F_socklen"}) -> %d",
+ infobuff, *namelen, result);
+ errno = _errno;
+ return result;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) {
+ int result, _errno;
+ Debug5("getsockopt(%d, %d, %d, %p, {"F_Zd"})",
+ s, level, optname, optval, *optlen);
+ result = getsockopt(s, level, optname, optval, optlen);
+ _errno = errno;
+ Debug3("getsockopt() -> (,,, 0x%08x, %d), %d",
+ *(int *)optval, *optlen, result);
+ errno = _errno;
+ return result;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Setsockopt(int s, int level, int optname, const void *optval, int optlen) {
+ int result, _errno;
+ if (optlen <= sizeof(int)) {
+ Debug5("setsockopt(%d, %d, %d, {0x%x}, %d)",
+ s, level, optname, *(unsigned int *)optval, optlen);
+ } else {
+ Debug6("setsockopt(%d, %d, %d, {0x%08x,%08x}, %d)",
+ s, level, optname,
+ ((unsigned int *)optval)[0], ((unsigned int *)optval)[1],
+ optlen);
+ }
+ result = setsockopt(s, level, optname, optval, optlen);
+ _errno = errno;
+ Debug1("setsockopt() -> %d", result);
+ errno = _errno;
+ return result;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Recv(int s, void *buf, size_t len, int flags) {
+ int retval, _errno;
+ Debug4("recv(%d, %p, "F_Zu", %d)", s, buf, len, flags);
+ retval = recv(s, buf, len, flags);
+ _errno = errno;
+ Debug1("recv() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from,
+ socklen_t *fromlen) {
+ int retval, _errno;
+ char infobuff[256];
+ Debug6("recvfrom(%d, %p, "F_Zu", %d, %p, "F_Zu")",
+ s, buf, len, flags, from, *fromlen);
+ retval = recvfrom(s, buf, len, flags, from, fromlen);
+ _errno = errno;
+ if (from) {
+ Debug4("recvfrom(,,,, {%d,%s}, "F_Zd") -> %d",
+ from->sa_family,
+ sockaddr_info(from, *fromlen, infobuff, sizeof(infobuff)),
+ *fromlen, retval);
+ } else {
+ Debug1("recvfrom(,,,, NULL, NULL) -> %d", retval);
+ }
+ errno = _errno;
+ return retval;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Recvmsg(int s, struct msghdr *msgh, int flags) {
+ int retval, _errno;
+ char infobuff[256];
+ Debug3("recvmsg(%d, %p, %d)", s, msgh, flags);
+ retval = recvmsg(s, msgh, flags);
+ _errno = errno;
+ Debug2("recvmsg(, {%s}, ) -> %d",
+ msgh->msg_name?sockaddr_info(msgh->msg_name, msgh->msg_namelen, infobuff, sizeof(infobuff)):"NULL",
+ retval);
+ errno = _errno;
+ return retval;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Send(int s, const void *mesg, size_t len, int flags) {
+ int retval, _errno;
+ Debug5("send(%d, %p[%08x...], "F_Zu", %d)",
+ s, mesg, ntohl(*(unsigned long *)mesg), len, flags);
+ retval = send(s, mesg, len, flags);
+ _errno = errno;
+ Debug1("send() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Sendto(int s, const void *mesg, size_t len, int flags,
+ const struct sockaddr *to, socklen_t tolen) {
+ int retval, _errno;
+ char infobuff[256];
+
+ sockaddr_info(to, tolen, infobuff, sizeof(infobuff));
+ Debug7("sendto(%d, %p[%08x...], "F_Zu", %d, {%s}, %d)",
+ s, mesg, htonl(*(unsigned long *)mesg), len, flags, infobuff, tolen);
+ retval = sendto(s, mesg, len, flags, to, tolen);
+ _errno = errno;
+ Debug1("sendto() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+int Shutdown(int fd, int how) {
+ int retval, _errno;
+ Info2("shutdown(%d, %d)", fd, how);
+ retval = shutdown(fd, how);
+ _errno = errno;
+ Debug1("shutdown() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+#endif /* _WITH_SOCKET */
+
+unsigned int Sleep(unsigned int seconds) {
+ unsigned int retval;
+ Debug1("sleep(%u)", seconds);
+ retval = sleep(seconds);
+ Debug1("sleep() -> %u", retval);
+ return retval;
+}
+
+void Usleep(unsigned long usec) {
+ Debug1("usleep(%lu)", usec);
+ usleep(usec);
+ Debug("usleep() ->");
+ return;
+}
+
+#if HAVE_NANOSLEEP
+unsigned int Nanosleep(const struct timespec *req, struct timespec *rem) {
+ int retval, _errno;
+ Debug3("nanosleep({"F_time",%ld},%p)", req->tv_sec, req->tv_nsec, rem);
+ retval = nanosleep(req, rem);
+ _errno = errno;
+ if (rem) {
+ Debug3("nanosleep(,{"F_time",%ld}) -> %d",
+ rem->tv_sec, rem->tv_nsec, retval);
+ } else {
+ Debug1("nanosleep() -> %d", retval);
+ }
+ errno = _errno;
+ return retval;
+}
+#endif /* HAVE_NANOSLEEP */
+
+int Pause(void) {
+ int retval, _errno;
+ Debug("pause()");
+ retval = pause();
+ _errno = errno;
+ Debug1("pause() -> %d", retval);
+ errno = _errno;
+ return retval;
+}
+
+#if WITH_IP4 || WITH_IP6
+struct hostent *Gethostbyname(const char *name) {
+ struct hostent *hent;
+ Debug1("gethostbyname(\"%s\")", name);
+ hent = gethostbyname(name);
+ if (hent == NULL) {
+ Debug("gethostbyname() -> NULL");
+ } else {
+ Debug4("gethostbyname() -> %d.%d.%d.%d",
+ ((unsigned char *)hent->h_addr_list[0])[0],
+ ((unsigned char *)hent->h_addr_list[0])[1],
+ ((unsigned char *)hent->h_addr_list[0])[2],
+ ((unsigned char *)hent->h_addr_list[0])[3]);
+ }
+ return hent;
+}
+#endif /* WITH_IP4 || WITH_IP6 */
+
+#if (_WITH_IP4 || _WITH_IP6) && HAVE_GETADDRINFO
+int Getaddrinfo(const char *node, const char *service,
+ const struct addrinfo *hints, struct addrinfo **res) {
+ int result;
+ Debug15("getaddrinfo(%s%s%s, %s%s%s, {%d,%d,%d,%d,"F_Zu",%p,%p,%p}, %p)",
+ node?"\"":"", node?node:"NULL", node?"\"":"",
+ service?"\"":"", service?service:"NULL", service?"\"":"",
+ hints->ai_flags, hints->ai_family, hints->ai_socktype,
+ hints->ai_protocol, hints->ai_addrlen, hints->ai_addr,
+ hints->ai_canonname, hints->ai_next, res);
+ result = getaddrinfo(node, service, hints, res);
+ if (result == 0) {
+ char sockbuff[256];
+ sockaddr_info((*res)->ai_addr, hints->ai_addrlen, sockbuff, sizeof(sockbuff));
+ Debug2("getaddrinfo(,,,{{%s, %s}) -> 0",
+ sockbuff,
+ (*res)->ai_canonname?(*res)->ai_canonname:"");
+ } else {
+ Debug2("getaddrinfo(,,,{%p}) -> %d", *res, result);
+ }
+ return result;
+}
+#endif /* (_WITH_IP4 || _WITH_IP6) && HAVE_GETADDRINFO */
+
+#if (WITH_IP4 || WITH_IP6) && HAVE_GETIPNODEBYNAME
+struct hostent *Getipnodebyname(const char *name, int af, int flags,
+ int *error_num) {
+ struct hostent *result;
+ Debug4("getipnodebyname(\"%s\", %d, %d, %p)", name, af, flags, error_num);
+ result = getipnodebyname(name, af, flags, error_num);
+ if (result == NULL) {
+ Debug1("getipnodebyname(,,, {%d}) -> NULL", *error_num);
+ } else {
+ Debug4("getipnodebyname() -> {\"%s\", %p, %d, %d, ???}",
+ result->h_name, result->h_aliases, result->h_addrtype,
+ result->h_length);
+ }
+ return result;
+}
+#endif /* (WITH_IP4 || WITH_IP6) && HAVE_GETIPNODEBYNAME */
+
+void *Malloc(size_t size) {
+ void *result;
+ Debug1("malloc("F_Zd")", size);
+ result = malloc(size);
+ Debug1("malloc() -> %p", result);
+ if (result == NULL) {
+ Error1("malloc("F_Zd"): out of memory", size);
+ return NULL;
+ }
+ return result;
+}
+
+void *Calloc(size_t nmemb, size_t size) {
+ void *result;
+ Debug2("calloc("F_Zd", "F_Zd")", nmemb, size);
+ result = calloc(nmemb, size);
+ Debug1("calloc() -> %p", result);
+ if (result == NULL) {
+ Error2("calloc("F_Zd", "F_Zd"): out of memory", nmemb, size);
+ return NULL;
+ }
+ return result;
+}
+
+void *Realloc(void *ptr, size_t size) {
+ void *result;
+ Debug2("realloc(%p, "F_Zd")", ptr, size);
+ result = realloc(ptr, size);
+ Debug1("realloc() -> %p", result);
+ if (result == NULL) {
+ Error2("realloc(%p, "F_Zd"): out of memory", ptr, size);
+ return NULL;
+ }
+ return result;
+}
+
+int Tcgetattr(int fd, struct termios *termios_p) {
+ int i, result, _errno;
+ char chars[5*NCCS], *cp = chars;
+
+ Debug2("tcgetattr(%d, %p)", fd, termios_p);
+ result = tcgetattr(fd, termios_p);
+ _errno = errno;
+
+ for (i = 0; i < NCCS-1; ++i) {
+ cp += sprintf(cp, "%02x,", termios_p->c_cc[i]);
+ }
+ sprintf(cp, "%02x", termios_p->c_cc[i]);
+ Debug6("tcgetattr(, {%08x,%08x,%08x,%08x,%s}) -> %d",
+ termios_p->c_iflag, termios_p->c_oflag,
+ termios_p->c_cflag, termios_p->c_lflag,
+ chars, result);
+ errno = _errno;
+ return result;
+}
+
+int Tcsetattr(int fd, int optional_actions, struct termios *termios_p) {
+ int i, result, _errno;
+ char chars[5*NCCS], *cp = chars;
+
+ for (i = 0; i < NCCS-1; ++i) {
+ cp += sprintf(cp, "%02x,", termios_p->c_cc[i]);
+ }
+ sprintf(cp, "%02x", termios_p->c_cc[i]);
+ Debug7("tcsetattr(%d, %d, {%08x,%08x,%08x,%08x,%s})", fd, optional_actions,
+ termios_p->c_iflag, termios_p->c_oflag,
+ termios_p->c_cflag, termios_p->c_lflag, chars);
+ result = tcsetattr(fd, optional_actions, termios_p);
+ _errno = errno;
+ Debug1("tcsetattr() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+char *Ttyname(int fd) {
+ char *result;
+ int _errno;
+ Debug1("ttyname(%d)", fd);
+ result = ttyname(fd);
+ _errno = errno;
+ if (result)
+ Debug1("ttyname() -> %s", result);
+ else
+ Debug("ttyname() -> NULL");
+ errno = _errno;
+ return result;
+}
+
+int Isatty(int fd) {
+ int result, _errno;
+ Debug1("isatty(%d)", fd);
+ result = isatty(fd);
+ _errno = errno;
+ Debug1("isatty() -> %d", result);
+ errno = _errno;
+ return result;
+}
+
+#if HAVE_OPENPTY
+int Openpty(int *ptyfd, int *ttyfd, char *ptyname, struct termios *termp,
+ struct winsize *winp) {
+ int result, _errno;
+ Debug5("openpty(%p, %p, %p, %p, %p)", ptyfd, ttyfd, ptyname, termp, winp);
+ result = openpty(ptyfd, ttyfd, ptyname, termp, winp);
+ _errno = errno;
+ Info4("openpty({%d}, {%d}, {\"%s\"},,) -> %d", *ptyfd, *ttyfd, ptyname,
+ result);
+ errno = _errno;
+ return result;
+}
+#endif /* HAVE_OPENPTY */
+
+#if HAVE_GRANTPT
+int Grantpt(int fd) {
+ int result, _errno;
+ Debug1("grantpt(%d)", fd);
+ result = grantpt(fd);
+ _errno = errno;
+ Debug1("grantpt() -> %d", result);
+ errno = _errno;
+ return result;
+}
+#endif /* HAVE_GRANTPT */
+
+#if HAVE_UNLOCKPT
+int Unlockpt(int fd) {
+ int result, _errno;
+ Debug1("unlockpt(%d)", fd);
+ result = unlockpt(fd);
+ _errno = errno;
+ Debug1("unlockpt() -> %d", result);
+ errno = _errno;
+ return result;
+}
+#endif /* HAVE_UNLOCKPT */
+
+#if HAVE_PTSNAME /* AIX, not Linux */
+char *Ptsname(int fd) {
+ char *result;
+ int _errno;
+ Debug1("ptsname(%d)", fd);
+ result = ptsname(fd);
+ _errno = errno;
+ if (result)
+ Debug1("ptsname() -> %s", result);
+ else
+ Debug("ptsname() -> NULL");
+ errno = _errno;
+ return result;
+}
+#endif /* HAVE_PTSNAME */
+
+int Uname(struct utsname *buf) {
+ int result, _errno;
+ Debug1("uname(%p)", buf);
+ result = uname(buf);
+ _errno = errno;
+#if UNAME_DOMAINNAME
+ Debug6("uname({%s, %s, %s, %s, %s, %s})",
+ buf->sysname, buf->nodename, buf->release,
+ buf->version, buf->machine, buf->domainname);
+#else
+ Debug5("uname({%s, %s, %s, %s, %s})",
+ buf->sysname, buf->nodename, buf->release,
+ buf->version, buf->machine);
+#endif
+ errno = _errno;
+ return result;
+}
+
+int Gethostname(char *name, size_t len) {
+ int result, _errno;
+ Debug2("gethostname(%p, "F_Zu")", name, len);
+ result = gethostname(name, len);
+ _errno = errno;
+ Debug2("gethostname(\"%s\", ) -> %d", name, result);
+ errno = _errno;
+ return result;
+}
+
+/* due to Linux docu, it does not set errno */
+int Atexit(void (*func)(void)) {
+ int result;
+ Debug1("atexit(%p)", func);
+ result = atexit(func);
+ Debug1("atexit() -> %d", result);
+ return result;
+}
+
+
+void Exit(int status) {
+ Debug1("exit(%d)", status);
+ exit(status);
+}
+
+void Abort(void) {
+ Debug("abort()");
+ abort();
+}
+
+int Mkstemp(char *template) {
+ int result, _errno;
+ Debug1("mkstemp(\"%s\")", template);
+ result = mkstemp(template);
+ _errno = errno;
+ Info2("mkstemp({%s}) -> %d", template, result);
+ errno = _errno;
+ return result;
+}
+
+#if WITH_READLINE
+
+char *Readline(const char *prompt) {
+ char *result;
+
+ if (prompt) {
+ Debug1("readline(\"%s\")", prompt);
+ } else {
+ Debug("readline(NULL)");
+ }
+ result = readline(prompt);
+ if (result) {
+ Debug("readline() -> \"...\"");
+ } else {
+ Debug("readline() -> NULL");
+ }
+ return result;
+}
+
+void Using_history(void) {
+ Debug("using_history()");
+ using_history();
+ Debug("using_history() ->");
+}
+
+int Read_history(const char *filename) {
+ int result;
+
+ if (filename) {
+ Debug1("read_history(\"%s\")", filename);
+ } else {
+ Debug("read_history(NULL)");
+ }
+ result = read_history(filename);
+ if (result) {
+ Debug1("read_history() -> %d", result);
+ } else {
+ Debug("read_history() -> 0");
+ }
+ return result;
+}
+
+int Write_history(const char *filename) {
+ int result;
+
+ if (filename) {
+ Debug1("write_history(\"%s\")", filename);
+ } else {
+ Debug("write_history(NULL)");
+ }
+ result = write_history(filename);
+ if (result) {
+ Debug1("write_history() -> %d", result);
+ } else {
+ Debug("write_history() -> 0");
+ }
+ return result;
+}
+
+int Append_history(int nelements, const char *filename) {
+ int result;
+
+ if (filename) {
+ Debug2("append_history(%d, \"%s\")", nelements, filename);
+ } else {
+ Debug1("append_history(%d, NULL)", nelements);
+ }
+ result = append_history(nelements, filename);
+ if (result) {
+ Debug1("append_history() -> %d", result);
+ } else {
+ Debug("append_history() -> 0");
+ }
+ return result;
+}
+
+int Where_history(void) {
+ int result;
+
+ Debug("where_history()");
+ result = where_history();
+ Debug1("where_history() -> %d", result);
+ return result;
+}
+
+void Add_history(const char *string) {
+ Debug1("add_history(\"%s\")", string);
+ add_history(string);
+ Debug("add_history() ->");
+}
+
+#endif /* WITH_READLINE */
+
+#endif /* WITH_SYCLS */
diff --git a/sycls.h b/sycls.h
new file mode 100644
index 0000000..ffe49db
--- /dev/null
+++ b/sycls.h
@@ -0,0 +1,270 @@
+/* $Id: sycls.h,v 1.50 2007/03/06 21:04:26 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __sycls_h_included
+#define __sycls_h_included 1
+
+#if WITH_SYCLS
+struct termios; /* prevent gcc from spitting silly warning */
+struct utsname;
+struct flock;
+struct addrinfo;
+
+mode_t Umask(mode_t mask);
+int Open(const char *pathname, int flags, mode_t mode);
+int Creat(const char *pathname, mode_t mode);
+off_t Lseek(int fildes, off_t offset, int whence);
+#if HAVE_LSEEK64
+off64_t Lseek64(int fildes, off64_t offset, int whence);
+#endif
+pid_t Getpid(void);
+pid_t Getppid(void);
+pid_t Getpgrp(void);
+int Getpgid(pid_t pid);
+int Setpgid(pid_t pid, pid_t pgid);
+int Setpgrp(void);
+pid_t Tcgetpgrp(int fd);
+int Tcsetpgrp(int fd, pid_t pgrpid);
+pid_t Getsid(pid_t pid);
+pid_t Setsid(void);
+uid_t Getuid(void);
+uid_t Geteuid(void);
+int Setuid(uid_t uid);
+gid_t Getgid(void);
+gid_t Getegid(void);
+int Setgid(gid_t gid);
+int Initgroups(const char *user, gid_t group);
+int Getgroups(int size, gid_t list[]);
+int Setgroups(size_t size, const gid_t *list);
+int Chdir(const char *path);
+int Chroot(const char *path);
+int Gettimeofday(struct timeval *tv, struct timezone *tz);
+int Mknod(const char *pathname, mode_t mode, dev_t dev);
+int Mkfifo(const char *pathname, mode_t mode);
+int Stat(const char *file_name, struct stat *buf);
+int Fstat(int filedes, struct stat *buf);
+int Lstat(const char *file_name, struct stat *buf);
+#if HAVE_STAT64
+int Stat64(const char *file_name, struct stat64 *buf);
+int Fstat64(int filedes, struct stat64 *buf);
+int Lstat64(const char *file_name, struct stat64 *buf);
+#endif /* HAVE_STAT64 */
+int Dup(int oldfd);
+int Dup2(int oldfd, int newfd);
+int Pipe(int filedes[2]);
+ssize_t Read(int fd, void *buf, size_t count);
+ssize_t Write(int fd, const void *buf, size_t count);
+int Fcntl(int fd, int cmd);
+int Fcntl_l(int fd, int cmd, long arg);
+int Fcntl_lock(int fd, int cmd, struct flock *l);
+int Ftruncate(int fd, off_t length);
+#if HAVE_FTRUNCATE64
+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 Close(int fd);
+int Fchown(int fd, uid_t owner, gid_t group);
+int Fchmod(int fd, mode_t mode);
+int Unlink(const char *pathname);
+int Symlink(const char *oldpath, const char *newpath);
+int Readlink(const char *path, char *buf, size_t bufsiz);
+int Chown(const char *path, uid_t owner, gid_t group);
+int Chmod(const char *path, mode_t mode);
+int Poll(struct pollfd *ufds, unsigned int nfds, int timeout);
+int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ struct timeval *timeout);
+pid_t Fork(void);
+pid_t Waitpid(pid_t pid, int *status, int options);
+#ifndef HAVE_TYPE_SIGHANDLER
+typedef RETSIGTYPE (*sighandler_t)(int);
+#endif
+sighandler_t Signal(int signum, sighandler_t handler);
+int Sigaction(int signum, const struct sigaction *act,
+ struct sigaction *oldact);
+int Sigprocmask(int how, const sigset_t *set, sigset_t *oset);
+unsigned int Alarm(unsigned int seconds);
+int Kill(pid_t pid, int sig);
+int Link(const char *oldpath, const char *newpath);
+int Execvp(const char *file, char *const argv[]);
+int System(const char *string);
+int Socketpair(int d, int type, int protocol, int sv[2]);
+#if _WITH_SOCKET
+int Socket(int domain, int type, int protocol);
+int Bind(int sockfd, struct sockaddr *my_addr, int addrlen);
+int Connect(int sockfd, const struct sockaddr *serv_addr, int addrlen);
+int Listen(int s, int backlog);
+int Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int Getsockname(int s, struct sockaddr *name, socklen_t *namelen);
+int Getpeername(int s, struct sockaddr *name, socklen_t *namelen);
+int Getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
+int Setsockopt(int s, int level, int optname, const void *optval, int optlen);
+int Recv(int s, void *buf, size_t len, int flags);
+int Recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from,
+ socklen_t *fromlen);
+int Recvmsg(int s, struct msghdr *msg, int flags);
+int Send(int s, const void *mesg, size_t len, int flags);
+int Sendto(int s, const void *msg, size_t len, int flags,
+ const struct sockaddr *to, socklen_t tolen);
+int Shutdown(int fd, int how);
+#endif /* _WITH_SOCKET */
+unsigned int Sleep(unsigned int seconds);
+void Usleep(unsigned long usec);
+unsigned int Nanosleep(const struct timespec *req, struct timespec *rem);
+int Pause(void);
+struct hostent *Gethostbyname(const char *name);
+int Getaddrinfo(const char *node, const char *service,
+ const struct addrinfo *hints, struct addrinfo **res);
+struct hostent *Getipnodebyname(const char *name, int af, int flags,
+ int *error_num);
+void *Malloc(size_t size);
+void *Calloc(size_t nmemb, size_t size);
+void *Realloc(void *ptr, size_t size);
+int Tcgetattr(int fd, struct termios *termios_p);
+int Tcsetattr(int fd, int optional_actions, struct termios *termios_p);
+char *Ttyname(int fd);
+int Isatty(int fd);
+struct winsize; /* avoid warnings */
+int Openpty(int *ptyfd, int *ttyfd, char *ptyname, struct termios *termp,
+ struct winsize *winp);
+char *Ptsname(int fd);
+int Grantpt(int fd);
+int Unlockpt(int fd);
+int Gethostname(char *name, size_t len);
+int Uname(struct utsname *buf);
+int Atexit(void (*func)(void));
+void Exit(int status);
+void Abort(void);
+int Mkstemp(char *template);
+
+char *Readline(const char *prompt);
+void Using_history(void);
+int Read_history(const char *filename);
+int Write_history(const char *filename);
+int Append_history(int nelements, const char *filename);
+int Read_history(const char *filename);
+void Add_history(const char *string);
+
+#else /* !WITH_SYCLS */
+
+#define Umask(m) umask(m)
+#define Open(p,f,m) open(p,f,m)
+#define Creat(p,m) creat(p,m)
+#define Lseek(f,o,w) lseek(f,o,w)
+#define Lseek64(f,o,w) lseek64(f,o,w)
+#define Getpid() getpid()
+#define Getppid() getppid()
+#define Getpgrp() getpgrp()
+#define Getpgid(p) getpgid(p)
+#define Setpgid(p,g) setpgid(p,g)
+#define Setpgrp() setpgrp()
+#define Tcgetpgrp(f) tcgetpgrp(f)
+#define Tcsetpgrp(f,p) tcsetpgrp(f,p)
+#define Getsid(p) getsid(p)
+#define Setsid() setsid()
+#define Getuid() getuid()
+#define Geteuid() geteuid()
+#define Setuid(u) setuid(u)
+#define Getgid() getgid()
+#define Getegid() getegid()
+#define Setgid(g) setgid(g)
+#define Initgroups(u,g) initgroups(u,g)
+#define Getgroups(s,l) getgroups(s,l)
+#define Setgroups(s,l) setgroups(s,l)
+#define Chdir(p) chdir(p)
+#define Chroot(p) chroot(p)
+#define Gettimeofday(tv,tz) gettimeofday(tv,tz)
+#define Mknod(p,m,d) mknod(p,m,d)
+#define Mkfifo(p,m) mkfifo(p,m)
+#define Stat(f,b) stat(f,b)
+#define Stat64(f,b) stat64(f,b)
+#define Fstat(f,b) fstat(f,b)
+#define Fstat64(f,b) fstat64(f,b)
+#define Lstat(f,b) lstat(f,b)
+#define Lstat64(f,b) lstat64(f,b)
+#define Dup(o) dup(o)
+#define Dup2(o,n) dup2(o,n)
+#define Pipe(f) pipe(f)
+#define Read(f,b,c) read(f,b,c)
+#define Write(f,b,c) write(f,b,c)
+#define Fcntl(f,c) fcntl(f,c)
+#define Fcntl_l(f,c,a) fcntl(f,c,a)
+#define Fcntl_lock(f,c,l) fcntl(f,c,l)
+#define Ftruncate(f,l) ftruncate(f,l)
+#define Ftruncate64(f,l) ftruncate64(f,l)
+#define Flock(f,o) flock(f,o)
+#define Ioctl(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)
+#define Unlink(p) unlink(p)
+#define Symlink(op,np) symlink(op,np)
+#define Readlink(p,b,s) readlink(p,b,s)
+#define Chown(p,o,g) chown(p,o,g)
+#define Chmod(p,m) chmod(p,m)
+#define Poll(u, n, t) poll(u, n, t)
+#define Select(n,r,w,e,t) select(n,r,w,e,t)
+#define Fork() fork()
+#define Waitpid(p,s,o) waitpid(p,s,o)
+#define Signal(s,h) signal(s,h)
+#define Sigaction(s,a,o) sigaction(s,a,o)
+#define Sigprocmask(h,s,o) sigprocmask(h,s,o)
+#define Alarm(s) alarm(s)
+#define Kill(p,s) kill(p,s)
+#define Link(o,n) link(o,n)
+#define Execvp(f,a) execvp(f,a)
+#define System(s) system(s)
+#define Socketpair(d,t,p,s) socketpair(d,t,p,s)
+#define Socket(d,t,p) socket(d,t,p)
+#define Bind(s,m,a) bind(s,m,a)
+#define Connect(s,a,l) connect(s,a,l)
+#define Listen(s,b) listen(s,b)
+#define Accept(s,a,l) accept(s,a,l)
+#define Getsockname(s,n,l) getsockname(s,n,l)
+#define Getpeername(s,n,l) getpeername(s,n,l)
+#define Getsockopt(s,d,n,v,l) getsockopt(s,d,n,v,l)
+#define Setsockopt(s,d,n,v,l) setsockopt(s,d,n,v,l)
+#define Recv(s,b,l,f) recv(s,b,l,f)
+#define Recvfrom(s,b,bl,f,fr,fl) recvfrom(s,b,bl,f,fr,fl)
+#define Recvmsg(s,m,f) recvmsg(s,m,f)
+#define Send(s,m,l,f) send(s,m,l,f)
+#define Sendto(s,b,bl,f,t,tl) sendto(s,b,bl,f,t,tl)
+#define Shutdown(f,h) shutdown(f,h)
+#define Sleep(s) sleep(s)
+#define Usleep(u) usleep(u)
+#define Nanosleep(req,rem) nanosleep(req,rem)
+#define Pause() pause()
+#define Gethostbyname(n) gethostbyname(n)
+#define Getaddrinfo(n,s,h,r) getaddrinfo(n,s,h,r)
+#define Getipnodebyname(n,a,f,e) getipnodebyname(n,a,f,e)
+#define Malloc(s) malloc(s)
+#define Calloc(n,s) calloc(n,s)
+#define Realloc(p,s) realloc(p,s)
+#define Tcgetattr(f,t) tcgetattr(f,t)
+#define Tcsetattr(f,o,t) tcsetattr(f,o,t)
+#define Ttyname(f) ttyname(f)
+#define Isatty(f) isatty(f)
+#define Openpty(p,t,n,i,f) openpty(p,t,n,i,f)
+#define Ptsname(f) ptsname(f)
+#define Grantpt(f) grantpt(f)
+#define Unlockpt(f) unlockpt(f)
+#define Getpgid(p) getpgid(p)
+#define Gethostname(n,l) gethostname(n,l)
+#define Uname(b) uname(b)
+#define Atexit(f) atexit(f)
+#define Exit(s) exit(s)
+#define Abort() abort()
+#define Mkstemp(t) mkstemp(t)
+
+#define Readline(p) readline(p)
+#define Using_history() using_history()
+#define Read_history(f) read_history(f)
+#define Write_history(f) write_history(f)
+#define Append_history(n,f) append_history(n,f)
+#define Read_history(f) read_history(f)
+#define Add_history(s) add_history(s)
+
+#endif /* !WITH_SYCLS */
+
+#endif /* !defined(__sycls_h_included) */
diff --git a/sysincludes.h b/sysincludes.h
new file mode 100644
index 0000000..a2b9f8a
--- /dev/null
+++ b/sysincludes.h
@@ -0,0 +1,161 @@
+/* $Id: sysincludes.h,v 1.23 2007/03/06 21:04:58 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __sysincludes_h_included
+#define __sysincludes_h_included 1
+
+#if HAVE_LIMITS_H
+#include <limits.h> /* USHRT_MAX */
+#endif
+#include <math.h> /* HUGE_VAL */
+#include <assert.h>
+#include <stdarg.h> /* for msg() */
+#include <string.h> /* strerror(), strchr() */
+#if HAVE_STRINGS_H
+#include <strings.h> /* strcasecmp(), bzero() for FD_ZERO */
+#endif
+#include <stdlib.h> /* malloc(), free() */
+#include <ctype.h> /* isdigit() */
+#include <stdio.h> /* FILE */
+#include <errno.h> /* errno */
+#if HAVE_SYSLOG_H
+#include <syslog.h> /* openlog(), syslog(), closelog() */
+#endif
+#include <signal.h> /* signal(), SIGPIPE, SIG_IGN */
+#include <time.h> /* struct timeval, strftime() */
+#include <sys/timeb.h> /* struct timeb */
+#if HAVE_UNISTD_H
+#include <unistd.h> /* select(), read(), write(), stat(), fork() */
+#endif
+#if HAVE_PWD_H
+#include <pwd.h> /* getpwnam() */
+#endif
+#if HAVE_GRP_H
+#include <grp.h> /* getgrnam() */
+#endif
+#if HAVE_PTY_H
+#include <pty.h>
+#endif
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h> /* Linux 2.4 NGROUPS */
+#endif
+#if HAVE_SYS_TIME_H
+#include <sys/time.h> /* select(); OpenBSD: struct timespec */
+#endif
+#if HAVE_STDINT_H
+#include <stdint.h> /* uint8_t */
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h> /* pid_t, select(), socket(), connect(), open(), u_short */
+#endif
+#if HAVE_SYS_POLL_H
+#include <sys/poll.h> /* poll() */
+#endif
+#if HAVE_SYS_SOCKET_H
+#include <sys/socket.h> /* struct sockaddr, struct linger, socket(), connect() */
+#endif
+#if HAVE_SYS_UIO_H
+#include <sys/uio.h> /* struct iovec */
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h> /* struct stat, stat(), open() */
+#endif
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h> /* WNOHANG */
+#endif
+#if HAVE_FCNTL_H
+#include <fcntl.h> /* open(), O_RDWR */
+#endif
+#if HAVE_NETDB_H && (_WITH_IP4 || _WITH_IP6)
+#include <netdb.h> /* struct hostent, gethostbyname() */
+#endif
+#if HAVE_SYS_UN_H && WITH_UNIX
+#include <sys/un.h> /* struct sockaddr_un, unix domain sockets */
+#endif
+#if HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h> /* ioctl() */
+#endif
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h> /* select(), fdset on AIX 4.1 */
+#endif
+#if HAVE_SYS_FILE_H
+#include <sys/file.h> /* LOCK_EX, on AIX directly included */
+#endif
+#if _WITH_SOCKET
+# if HAVE_NETINET_IN_H
+#include <netinet/in.h> /* struct sockaddr_in, htonl() */
+# endif
+#endif /* _WITH_SOCKET */
+#if _WITH_SOCKET && (_WITH_IP4 || _WITH_IP6)
+# if HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h> /* Solaris, FreeBSD: n_long */
+# endif
+# if HAVE_NETINET_IP_H
+#include <netinet/ip.h> /* struct ip - past netinet/in.h on AIX! */
+# endif
+# if HAVE_NETINET_TCP_H
+#include <netinet/tcp.h> /* TCP_RFC1323 */
+# endif
+# if HAVE_NETINET_IP6_H && _WITH_IP6
+#include <netinet/ip6.h>
+# endif
+# if HAVE_NETINET6_IN6_H && _WITH_IP6
+#include <netinet6/in6.h>
+# endif
+#include <arpa/inet.h> /* Linux: inet_aton() */
+#if HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h> /* req for resolv.h (esp. on MacOSX) */
+#endif
+#include <net/if.h>
+#if HAVE_RESOLV_H
+#include <resolv.h> /* _res */
+#endif
+#endif /* _WITH_IP4 || _WITH_IP6 */
+/*#include <linux/sockios.h>*/
+#if HAVE_NET_IF_H
+#include <net/if.h>
+#endif /* HAVE_NET_IF_H */
+#if HAVE_LINUX_IF_TUN_H
+#include <linux/if_tun.h>
+#endif
+
+#if HAVE_TERMIOS_H && WITH_TERMIOS
+#include <termios.h>
+#endif
+#if HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h> /* uname(), struct utsname */
+#endif
+#if HAVE_UTIL_H
+#include <util.h> /* NetBSD, OpenBSD openpty() */
+#endif
+#if HAVE_LIBUTIL_H
+#include <libutil.h> /* FreeBSD openpty() */
+#endif
+#if HAVE_SYS_STROPTS_H
+#include <sys/stropts.h> /* SunOS I_PUSH ... */
+#endif
+#if HAVE_REGEX_H
+#include <regex.h>
+#endif
+#if HAVE_LINUX_FS_H
+#include <linux/fs.h> /* somewhere required for ext2_fs.h */
+#endif
+#if HAVE_LINUX_EXT2_FS_H
+#include <linux/ext2_fs.h> /* Linux ext2 filesystem definitions */
+#endif
+#if WITH_READLINE
+# if HAVE_READLINE_READLINE_H
+#include <readline/readline.h>
+# endif
+# if HAVE_READLINE_HISTORY_H
+#include <readline/history.h>
+# endif
+#endif /* WITH_READLINE */
+#if WITH_OPENSSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#endif
+
+#endif /* !defined(__sysincludes_h_included) */
diff --git a/sysutils.c b/sysutils.c
new file mode 100644
index 0000000..c10e2ea
--- /dev/null
+++ b/sysutils.c
@@ -0,0 +1,495 @@
+/* $Id: sysutils.c,v 1.44 2007/03/06 21:05:11 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* translate socket addresses into human readable form */
+
+#include "config.h"
+#include "xioconfig.h"
+
+#include "sysincludes.h"
+
+#include "compat.h" /* socklen_t */
+#include "mytypes.h"
+#include "error.h"
+#include "sycls.h"
+#include "utils.h"
+#include "sysutils.h"
+
+
+#if WITH_UNIX
+void socket_un_init(struct sockaddr_un *sa) {
+#if HAVE_STRUCT_SOCKADDR_SALEN
+ sa->sun_len = sizeof(struct sockaddr_un);
+#endif
+ sa->sun_family = AF_UNIX;
+ memset(sa->sun_path, '\0', sizeof(sa->sun_path));
+}
+#endif /* WITH_UNIX */
+
+#if WITH_IP4
+void socket_in_init(struct sockaddr_in *sa) {
+#if HAVE_STRUCT_SOCKADDR_SALEN
+ sa->sin_len = sizeof(struct sockaddr_in);
+#endif
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ sa->sin_addr.s_addr = 0;
+ sa->sin_zero[0] = 0;
+ sa->sin_zero[1] = 0;
+ sa->sin_zero[2] = 0;
+ sa->sin_zero[3] = 0;
+ sa->sin_zero[4] = 0;
+ sa->sin_zero[5] = 0;
+ sa->sin_zero[6] = 0;
+ sa->sin_zero[7] = 0;
+}
+#endif /* WITH_IP4 */
+
+#if WITH_IP6
+void socket_in6_init(struct sockaddr_in6 *sa) {
+#if HAVE_STRUCT_SOCKADDR_SALEN
+ sa->sin6_len = sizeof(struct sockaddr_in6);
+#endif
+ sa->sin6_family = AF_INET6;
+ sa->sin6_port = 0;
+ sa->sin6_flowinfo = 0;
+#if HAVE_IP6_SOCKADDR==0
+ sa->sin6_addr.s6_addr[0] = 0;
+ sa->sin6_addr.s6_addr[1] = 0;
+ sa->sin6_addr.s6_addr[2] = 0;
+ sa->sin6_addr.s6_addr[3] = 0;
+ sa->sin6_addr.s6_addr[4] = 0;
+ sa->sin6_addr.s6_addr[5] = 0;
+ sa->sin6_addr.s6_addr[6] = 0;
+ sa->sin6_addr.s6_addr[7] = 0;
+ sa->sin6_addr.s6_addr[8] = 0;
+ sa->sin6_addr.s6_addr[9] = 0;
+ sa->sin6_addr.s6_addr[10] = 0;
+ sa->sin6_addr.s6_addr[11] = 0;
+ sa->sin6_addr.s6_addr[12] = 0;
+ sa->sin6_addr.s6_addr[13] = 0;
+ sa->sin6_addr.s6_addr[14] = 0;
+ sa->sin6_addr.s6_addr[15] = 0;
+#elif HAVE_IP6_SOCKADDR==1
+ sa->sin6_addr.u6_addr.u6_addr32[0] = 0;
+ sa->sin6_addr.u6_addr.u6_addr32[1] = 0;
+ sa->sin6_addr.u6_addr.u6_addr32[2] = 0;
+ sa->sin6_addr.u6_addr.u6_addr32[3] = 0;
+#elif HAVE_IP6_SOCKADDR==2
+ sa->sin6_addr.u6_addr32[0] = 0;
+ sa->sin6_addr.u6_addr32[1] = 0;
+ sa->sin6_addr.u6_addr32[2] = 0;
+ sa->sin6_addr.u6_addr32[3] = 0;
+#elif HAVE_IP6_SOCKADDR==3
+ sa->sin6_addr.in6_u.u6_addr32[0] = 0;
+ sa->sin6_addr.in6_u.u6_addr32[1] = 0;
+ sa->sin6_addr.in6_u.u6_addr32[2] = 0;
+ sa->sin6_addr.in6_u.u6_addr32[3] = 0;
+#elif HAVE_IP6_SOCKADDR==4
+ sa->sin6_addr._S6_un._S6_u32[0] = 0;
+ sa->sin6_addr._S6_un._S6_u32[1] = 0;
+ sa->sin6_addr._S6_un._S6_u32[2] = 0;
+ sa->sin6_addr._S6_un._S6_u32[3] = 0;
+#elif HAVE_IP6_SOCKADDR==5
+ sa->sin6_addr.__u6_addr.__u6_addr32[0] = 0;
+ sa->sin6_addr.__u6_addr.__u6_addr32[1] = 0;
+ sa->sin6_addr.__u6_addr.__u6_addr32[2] = 0;
+ sa->sin6_addr.__u6_addr.__u6_addr32[3] = 0;
+#endif
+}
+#endif /* WITH_IP6 */
+
+
+#if _WITH_SOCKET
+/* initializes the socket address of the specified address family. Returns the
+ length of the specific socket address, or 0 on error. */
+socklen_t socket_init(int af, union sockaddr_union *sa) {
+ switch (af) {
+#if WITH_UNIX
+ case AF_UNIX: socket_un_init(&sa->un); return sizeof(sa->un);
+#endif
+#if WITH_IP4
+ case AF_INET: socket_in_init(&sa->ip4); return sizeof(sa->ip4);
+#endif
+#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);
+ memset(sa, 0, sizeof(union sockaddr_union));
+ sa->soa.sa_family = af;
+ return 0;
+ }
+}
+#endif /* _WITH_SOCKET */
+
+#if WITH_UNIX
+#define XIOUNIXSOCKOVERHEAD (sizeof(struct sockaddr_un)-sizeof(((struct sockaddr_un*)0)->sun_path))
+#endif
+
+#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];
+ char *lbuff = buff;
+ char *cp = lbuff;
+ int n;
+
+ 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;
+
+ switch (sa->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);
+ }
+ break;
+#endif
+#if WITH_IP4
+ case AF_INET: sockaddr_inet4_info((struct sockaddr_in *)sa, cp, blen);
+ break;
+#endif
+#if WITH_IP6
+ case AF_INET6: sockaddr_inet6_info((struct sockaddr_in6 *)sa, cp, blen);
+ break;
+#endif
+ default:
+ 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) {
+ Warn("sockaddr_info(): buffer too short");
+ *buff = '\0';
+ return buff;
+ }
+ }
+ return lbuff;
+}
+#endif /* _WITH_SOCKET */
+
+
+#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';
+ }
+ return buff;
+}
+#endif /* WITH_UNIX */
+
+#if WITH_IP4
+/* addr in host byte order! */
+char *inet4addr_info(uint32_t addr, char *buff, size_t blen) {
+ if (snprintf(buff, blen, "%u.%u.%u.%u",
+ (unsigned int)(addr >> 24), (unsigned int)((addr >> 16) & 0xff),
+ (unsigned int)((addr >> 8) & 0xff), (unsigned int)(addr & 0xff)) < 0) {
+ Warn("inet4addr_info(): buffer too short");
+ buff[blen-1] = '\0';
+ }
+ return buff;
+}
+#endif /* WITH_IP4 */
+
+#if WITH_IP4
+char *sockaddr_inet4_info(const struct sockaddr_in *sa, char *buff, size_t blen) {
+ if (snprintf(buff, blen, "%u.%u.%u.%u:%hu",
+ ((unsigned char *)&sa->sin_addr.s_addr)[0],
+ ((unsigned char *)&sa->sin_addr.s_addr)[1],
+ ((unsigned char *)&sa->sin_addr.s_addr)[2],
+ ((unsigned char *)&sa->sin_addr.s_addr)[3],
+ htons(sa->sin_port)) < 0) {
+ Warn("sockaddr_inet4_info(): buffer too short");
+ buff[blen-1] = '\0';
+ }
+ return buff;
+}
+#endif /* WITH_IP4 */
+
+#if !HAVE_INET_NTOP
+/* http://www.opengroup.org/onlinepubs/000095399/functions/inet_ntop.html */
+const char *inet_ntop(int pf, const void *binaddr,
+ char *addrtext, socklen_t textlen) {
+ size_t retlen;
+ switch (pf) {
+ case PF_INET:
+ if ((retlen =
+ snprintf(addrtext, textlen, "%u.%u.%u.%u",
+ ((unsigned char *)binaddr)[0],
+ ((unsigned char *)binaddr)[1],
+ ((unsigned char *)binaddr)[2],
+ ((unsigned char *)binaddr)[3]))
+ < 0) {
+ return NULL; /* errno is valid */
+ }
+ break;
+ case PF_INET6:
+ if ((retlen =
+ snprintf(addrtext, textlen, "%x:%x:%x:%x:%x:%x:%x:%x",
+ ntohs(((uint16_t *)binaddr)[0]),
+ ntohs(((uint16_t *)binaddr)[1]),
+ ntohs(((uint16_t *)binaddr)[2]),
+ ntohs(((uint16_t *)binaddr)[3]),
+ ntohs(((uint16_t *)binaddr)[4]),
+ ntohs(((uint16_t *)binaddr)[5]),
+ ntohs(((uint16_t *)binaddr)[6]),
+ ntohs(((uint16_t *)binaddr)[7])
+ ))
+ < 0) {
+ return NULL; /* errno is valid */
+ }
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+ addrtext[retlen] = '\0';
+ return addrtext;
+}
+#endif /* !HAVE_INET_NTOP */
+
+#if WITH_IP6
+/* convert the IP6 socket address to human readable form. buff should be at
+ least 50 chars long */
+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
+ (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],
+#elif HAVE_IP6_SOCKADDR==1
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[0]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[1]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[2]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[3]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[4]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[5]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[6]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr.u6_addr16)[7]),
+#elif HAVE_IP6_SOCKADDR==2
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[0]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[1]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[2]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[3]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[4]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[5]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[6]),
+ ntohs(((unsigned short *)&sa->sin6_addr.u6_addr16)[7]),
+#elif HAVE_IP6_SOCKADDR==3
+ ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[0]),
+ ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[1]),
+ ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[2]),
+ ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[3]),
+ ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[4]),
+ ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[5]),
+ ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[6]),
+ ntohs(((unsigned short *)&sa->sin6_addr.in6_u.u6_addr16)[7]),
+#elif HAVE_IP6_SOCKADDR==4
+ (sa->sin6_addr._S6_un._S6_u8[0]<<8)|(sa->sin6_addr._S6_un._S6_u8[1]&0xff),
+ (sa->sin6_addr._S6_un._S6_u8[2]<<8)|(sa->sin6_addr._S6_un._S6_u8[3]&0xff),
+ (sa->sin6_addr._S6_un._S6_u8[4]<<8)|(sa->sin6_addr._S6_un._S6_u8[5]&0xff),
+ (sa->sin6_addr._S6_un._S6_u8[6]<<8)|(sa->sin6_addr._S6_un._S6_u8[7]&0xff),
+ (sa->sin6_addr._S6_un._S6_u8[8]<<8)|(sa->sin6_addr._S6_un._S6_u8[9]&0xff),
+ (sa->sin6_addr._S6_un._S6_u8[10]<<8)|(sa->sin6_addr._S6_un._S6_u8[11]&0xff),
+ (sa->sin6_addr._S6_un._S6_u8[12]<<8)|(sa->sin6_addr._S6_un._S6_u8[13]&0xff),
+ (sa->sin6_addr._S6_un._S6_u8[14]<<8)|(sa->sin6_addr._S6_un._S6_u8[15]&0xff),
+#elif HAVE_IP6_SOCKADDR==5
+ ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[0]),
+ ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[1]),
+ ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[2]),
+ ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[3]),
+ ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[4]),
+ ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[5]),
+ ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[6]),
+ ntohs(((unsigned short *)&sa->sin6_addr.__u6_addr.__u6_addr16)[7]),
+#endif
+ ntohs(sa->sin6_port)) < 0) {
+ Warn("sockaddr_inet6_info(): buffer too short");
+ buff[blen-1] = '\0';
+ }
+ return buff;
+}
+#endif /* WITH_IP6 */
+
+/* fill the list with the supplementary group ids of user.
+ caller passes size of list in ngroups, function returns number of groups in
+ ngroups.
+ function returns 0 if 0 or more groups were found, or 1 if the list is too
+ short. */
+int getusergroups(const char *user, gid_t *list, size_t *ngroups) {
+ struct group *grp;
+ size_t i = 0;
+
+ setgrent();
+ while (grp = getgrent()) {
+ char **gusr = grp->gr_mem;
+ while (*gusr) {
+ if (!strcmp(*gusr, user)) {
+ if (i == *ngroups)
+ return 1;
+ list[i++] = grp->gr_gid;
+ break;
+ }
+ ++gusr;
+ }
+ }
+ endgrent();
+ *ngroups = i;
+ return 0;
+}
+
+#if !HAVE_HSTRERROR
+const char *hstrerror(int err) {
+ static const char *h_messages[] = {
+ "success",
+ "authoritative answer not found",
+ "non-authoritative, host not found, or serverfail",
+ "Host name lookup failure", /* "non recoverable error" */
+ "valid name, no data record of requested type" };
+
+ assert(HOST_NOT_FOUND==1);
+ assert(TRY_AGAIN==2);
+ assert(NO_RECOVERY==3);
+ assert(NO_DATA==4);
+ if ((err < 0) || err > sizeof(h_messages)/sizeof(const char *)) {
+ return "";
+ }
+ return h_messages[err];
+}
+#endif /* !HAVE_HSTRERROR */
+
+
+#if WITH_TCP || WITH_UDP
+/* returns port in network byte order */
+int parseport(const char *portname, int ipproto) {
+ struct servent *se;
+ char *extra;
+ int result;
+
+ if (isdigit(portname[0]&0xff)) {
+ result = htons(strtoul(portname, &extra, 0));
+ if (*extra != '\0') {
+ Error3("parseport(\"%s\", %d): extra trailing data \"%s\"",
+ portname, ipproto, extra);
+ }
+ return result;
+ }
+
+ if ((se = getservbyname(portname, ipproto==IPPROTO_TCP?"tcp":"udp")) == NULL) {
+ Error2("cannot resolve service \"%s/%d\"", portname, ipproto);
+ return 0;
+ }
+
+ return se->s_port;
+}
+#endif /* WITH_TCP || WITH_UDP */
+
+#if WITH_IP4 || WITH_IP6
+/* 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) {
+ /* Linux: man 7 netdevice */
+ /* FreeBSD: man 4 networking */
+ /* Solaris: man 7 if_tcp */
+
+#if defined(HAVE_STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX)
+ /* currently we support Linux, FreeBSD; not Solaris */
+
+#define IFBUFSIZ 1024
+ int s;
+ struct ifreq ifr;
+
+ if (ifname[0] == '\0') {
+ return -1;
+ }
+ 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",
+ s, ifr.ifr_name, strerror(errno));
+ return -1;
+ }
+ Close(s);
+#if HAVE_STRUCT_IFREQ_IFR_INDEX
+ return ifr.ifr_index;
+#elif HAVE_STRUCT_IFREQ_IFR_IFINDEX
+ return ifr.ifr_ifindex;
+#endif /* HAVE_STRUCT_IFREQ_IFR_IFINDEX */
+
+#else /* !defined(HAVE_ STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX) */
+ return -1;
+#endif /* !defined(HAVE_ STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX) */
+}
+
+
+/* like ifindexbyname(), but allows an index number as input.
+ writes the resulting index to *ifindex and returns 0,
+ or returns -1 on error */
+int ifindex(const char *ifname, unsigned int *ifindex) {
+ char *endptr;
+ long int val;
+
+ if (ifname[0] == '\0') {
+ return -1;
+ }
+ val = strtol(ifname, &endptr, 0);
+ if (endptr[0] == '\0') {
+ *ifindex = val;
+ return 0;
+ }
+
+ if ((val = ifindexbyname(ifname)) < 0) {
+ return -1;
+ }
+ *ifindex = val;
+ return 0;
+}
+#endif /* WITH_IP4 || WITH_IP6 */
diff --git a/sysutils.h b/sysutils.h
new file mode 100644
index 0000000..7e326b8
--- /dev/null
+++ b/sysutils.h
@@ -0,0 +1,98 @@
+/* $Id: sysutils.h,v 1.23 2007/03/06 21:05:37 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __sysutils_h_included
+#define __sysutils_h_included 1
+
+#if WITH_IP6
+/* not all OSes provide in6_addr that allows splitting to 16 or 32 bit junks of
+ the host address part of sockaddr_in6; here we help ourselves */
+union xioin6_u {
+ uint8_t u6_addr8[16];
+ uint16_t u6_addr16[8];
+ uint32_t u6_addr32[4];
+} ;
+#endif /* WITH_IP6 */
+
+union sockaddr_union {
+ struct sockaddr soa;
+#if WITH_UNIX
+ struct sockaddr_un un;
+#endif /* WITH_UNIX */
+#if WITH_IP4
+ struct sockaddr_in ip4;
+#endif /* WITH_IP4 */
+#if WITH_IP6
+ 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 */
+
+#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 */
+} ;
+#endif /* _WITH_SOCKET */
+
+#if _WITH_SOCKET
+extern socklen_t socket_init(int af, union sockaddr_union *sa);
+#endif
+#if WITH_UNIX
+extern void socket_un_init(struct sockaddr_un *sa);
+#endif /* WITH_UNIX */
+#if _WITH_IP4
+extern void socket_in_init(struct sockaddr_in *sa);
+#endif /* _WITH_IP4 */
+#if _WITH_IP6
+extern void socket_in6_init(struct sockaddr_in6 *sa);
+#endif /* _WITH_IP4 */
+
+#if _WITH_SOCKET
+extern char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size_t blen);
+#endif
+#if WITH_UNIX
+extern char *sockaddr_unix_info(const struct sockaddr_un *sa, socklen_t salen, char *buff, size_t blen);
+#endif /* WITH_UNIX */
+#if WITH_IP4
+extern char *inet4addr_info(uint32_t addr, char *buff, size_t blen);
+extern char *sockaddr_inet4_info(const struct sockaddr_in *sa, char *buff, size_t blen);
+#endif /* WITH_IP4 */
+#if WITH_IP6
+extern char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen);
+#endif /* WITH_IP6 */
+#if !HAVE_INET_NTOP
+extern const char *inet_ntop(int pf, const void *binaddr,
+ char *addrtext, socklen_t textlen);
+#endif
+
+extern int getusergroups(const char *user, gid_t *list, size_t *ngroups);
+
+#if !HAVE_HSTRERROR
+extern const char *hstrerror(int err);
+#endif
+
+extern int parseport(const char *portname, int proto);
+
+extern int ifindexbyname(const char *ifname);
+extern int ifindex(const char *ifname, unsigned int *ifindex);
+
+#endif /* !defined(__sysutils_h_included) */
diff --git a/test.sh b/test.sh
new file mode 100755
index 0000000..c1e6e5c
--- /dev/null
+++ b/test.sh
Binary files differ
diff --git a/testcert.conf b/testcert.conf
new file mode 100644
index 0000000..64b06cd
--- /dev/null
+++ b/testcert.conf
@@ -0,0 +1,9 @@
+prompt=no
+
+[ req ]
+default_bits = 768
+distinguished_name=Test
+
+[ Test ]
+countryName = XY
+
diff --git a/utils.c b/utils.c
new file mode 100644
index 0000000..e2d6824
--- /dev/null
+++ b/utils.c
@@ -0,0 +1,147 @@
+/* $Id: utils.c,v 1.17 2007/02/08 18:36:16 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* useful additions to C library */
+
+#include "config.h"
+
+#include "sysincludes.h"
+
+#include "compat.h" /* socklen_t */
+#include "mytypes.h"
+#include "sycls.h"
+#include "utils.h"
+
+
+#if !HAVE_MEMRCHR
+/* GNU extension, available since glibc 2.1.91 */
+void *memrchr(const void *s, int c, size_t n) {
+ const unsigned char *t = ((unsigned char *)s)+n;
+ while (--t >= (unsigned char *)s) {
+ if (*t == c) break;
+ }
+ if (t < (unsigned char *)s)
+ return NULL;
+ return (void *)t;
+}
+#endif /* !HAVE_MEMRCHR */
+
+void *memdup(const void *src, size_t n) {
+ void *dest;
+
+ if ((dest = Malloc(n)) == NULL) {
+ return NULL;
+ }
+
+ memcpy(dest, src, n);
+ return dest;
+}
+
+/* search the keyword-table for a match of the leading part of name. */
+/* returns the pointer to the matching field of the keyword or NULL if no
+ keyword was found. */
+const struct wordent *keyw(const struct wordent *keywds, const char *name, unsigned int nkeys) {
+ unsigned int lower, upper, mid;
+ int r;
+
+ lower = 0;
+ upper = nkeys;
+
+ while (upper - lower > 1)
+ {
+ mid = (upper + lower) >> 1;
+ if (!(r = strcasecmp(keywds[mid].name, name)))
+ {
+ return &keywds[mid];
+ }
+ if (r < 0)
+ lower = mid;
+ else
+ upper = mid;
+ }
+ if (nkeys > 0 && !(strcasecmp(keywds[lower].name, name)))
+ {
+ return &keywds[lower];
+ }
+ return NULL;
+}
+
+/* Linux: setenv(), AIX: putenv() */
+#if !HAVE_SETENV
+int setenv(const char *name, const char *value, int overwrite) {
+ int result;
+ char *env;
+ if (!overwrite) {
+ if (getenv(name)) return 0; /* already exists */
+ }
+ if ((env = Malloc(strlen(name)+strlen(value)+2)) != NULL) {
+ return -1;
+ }
+ sprintf(env, "%s=%s", name, value);
+ if ((result = putenv(env)) != 0) { /* AIX docu says "... nonzero ..." */
+ free(env);
+ result = -1;
+ }
+ /* linux "man putenv" says: ...this string becomes part of the environment*/
+ return result;
+}
+#endif /* !HAVE_SETENV */
+
+
+
+/* sanitize an "untrusted" character. output buffer must provide at least 5
+ characters space.
+ Does not append null. returns length out output (currently: max 4) */
+static size_t sanitize_char(char c, char *o, int style) {
+ int hn; /* high nibble */
+ int ln; /* low nibble */
+ int n; /* written chars */
+ if (isprint(c)) {
+ *o = c;
+ return 1;
+ }
+ *o++ = '\\';
+ n = 2;
+ switch (c) {
+ case '\0': *o++ = '0'; break;
+ case '\a': *o++ = 'a'; break;
+ case '\b': *o++ = 'b'; break;
+ case '\t': *o++ = 't'; break;
+ case '\n': *o++ = 'n'; break;
+ case '\v': *o++ = 'v'; break;
+ case '\f': *o++ = 'f'; break;
+ case '\r': *o++ = 'r'; break;
+ case '\'': *o++ = '\''; break;
+ case '\"': *o++ = '"'; break;
+ case '\\': *o++ = '\\'; break;
+ default:
+ *o++ = 'x';
+ hn = (c>>4)&0x0f;
+ ln = c&0x0f;
+ *o++ = (hn>=10 ? (('A'-1)+(hn-10)) : ('0'+hn));
+ *o++ = (ln>=10 ? (('A'-1)+(ln-10)) : ('0'+ln));
+ n = 4;
+ }
+ return n;
+}
+
+/* sanitize "untrusted" text, replacing special control characters with the C
+ string version ("\x"), and replacing unprintable chars with ".".
+ text can grow to four times of input, so keep output buffer long enough!
+ returns a pointer to the first untouched byte of the output buffer.
+*/
+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
+ ) {
+ int c;
+
+ while (bytes > 0) {
+ c = *(unsigned char *)data++;
+ coded += sanitize_char(c, coded, style);
+ --bytes;
+ }
+ return coded;
+}
diff --git a/utils.h b/utils.h
new file mode 100644
index 0000000..c974a41
--- /dev/null
+++ b/utils.h
@@ -0,0 +1,68 @@
+/* $Id: utils.h,v 1.7 2007/02/08 18:36:16 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __utils_h_included
+#define __utils_h_included 1
+
+/* a generic name table entry */
+struct wordent {
+ const char *name;
+ void *desc;
+} ;
+
+#if !HAVE_MEMRCHR
+extern void *memrchr(const void *s, int c, size_t n);
+#endif
+extern void *memdup(const void *src, size_t n);
+#if !HAVE_SETENV
+extern int setenv(const char *name, const char *value, int overwrite);
+#endif /* !HAVE_SETENV */
+
+extern const struct wordent *keyw(const struct wordent *keywds, const char *name, unsigned int nkeys);
+
+
+#define XIOSAN_ZERO_MASK 0x000f
+#define XIOSAN_ZERO_DEFAULT 0x0000
+#define XIOSAN_ZERO_DOT 0x0001
+#define XIOSAN_ZERO_BACKSLASH_OCT_3 0x0002
+#define XIOSAN_ZERO_BACKSLASH_OCT_4 0x0003
+#define XIOSAN_ZERO_BACKSLASHX_HEX_UP 0x0004
+#define XIOSAN_ZERO_BACKSLASHX_HEX_LOW 0x0005
+#define XIOSAN_ZERO_PERCENT_HEX_UP 0x0006
+#define XIOSAN_ZERO_PERCENT_HEX_LOW 0x0007
+#define XIOSAN_CONTROL_MASK 0x00f0
+#define XIOSAN_CONTROL_DEFAULT 0x0000
+#define XIOSAN_CONTROL_DOT 0x0010
+#define XIOSAN_CONTROL_BACKSLASH_OCT_3 0x0020
+#define XIOSAN_CONTROL_BACKSLASH_OCT_4 0x0030
+#define XIOSAN_CONTROL_BACKSLASHX_HEX_UP 0x0040
+#define XIOSAN_CONTROL_BACKSLASHX_HEX_LOW 0x0050
+#define XIOSAN_CONTROL_PERCENT_HEX_UP 0x0060
+#define XIOSAN_CONTROL_PERCENT_HEX_LOW 0x0070
+#define XIOSAN_UNPRINT_MASK 0x0f00
+#define XIOSAN_UNPRINT_DEFAULT 0x0000
+#define XIOSAN_UNPRINT_DOT 0x0100
+#define XIOSAN_UNPRINT_BACKSLASH_OCT_3 0x0200
+#define XIOSAN_UNPRINT_BACKSLASH_OCT_4 0x0300
+#define XIOSAN_UNPRINT_BACKSLASHX_HEX_UP 0x0400
+#define XIOSAN_UNPRINT_BACKSLASHX_HEX_LOW 0x0500
+#define XIOSAN_UNPRINT_PERCENT_HEX_UP 0x0600
+#define XIOSAN_UNPRINT_PERCENT_HEX_LOW 0x0700
+#define XIOSAN_DEFAULT_MASK 0xf000
+#define XIOSAN_DEFAULT_BACKSLASH_DOT 0x1000
+#define XIOSAN_DEFAULT_BACKSLASH_OCT_3 0x2000
+#define XIOSAN_DEFAULT_BACKSLASH_OCT_4 0x3000
+#define XIOSAN_DEFAULT_BACKSLASHX_HEX_UP 0x4000
+#define XIOSAN_DEFAULT_BACKSLASHX_HEX_LOW 0x5000
+#define XIOSAN_DEFAULT_PERCENT_HEX_UP 0x6000
+#define XIOSAN_DEFAULT_PERCENT_HEX_LOW 0x7000
+
+extern
+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);
+
+#endif /* !defined(__utils_h_included) */
+
diff --git a/xio-ascii.c b/xio-ascii.c
new file mode 100644
index 0000000..4ebe0d2
--- /dev/null
+++ b/xio-ascii.c
@@ -0,0 +1,107 @@
+/* $Id: xio-ascii.c,v 1.5 2006/07/23 07:30:46 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2002-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains functions for text encoding, decoding, and conversions */
+
+
+#include <stddef.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include "xio-ascii.h"
+
+/* for each 6 bit pattern we have an ASCII character in the arry */
+const static int base64chars[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/',
+} ;
+
+#define CHAR64(c) (base64chars[c])
+
+char *
+ xiob64encodeline(const char *data, /* input data */
+ size_t bytes, /* length of input data, >=0 */
+ char *coded /* output buffer, must be long enough */
+ ) {
+ int c1, c2, c3;
+
+ while (bytes > 0) {
+ c1 = *data++;
+ *coded++ = CHAR64(c1>>2);
+ if (--bytes == 0) {
+ *coded++ = CHAR64((c1&0x03)<<4);
+ *coded++ = '=';
+ *coded++ = '=';
+ } else {
+ c2 = *data++;
+ *coded++ = CHAR64(((c1&0x03)<<4)|(c2>>4));
+ if (--bytes == 0) {
+ *coded++ = CHAR64((c2&0x0f)<<2);
+ *coded++ = '=';
+ } else {
+ c3 = *data++; --bytes;
+ *coded++ = CHAR64(((c2&0x0f)<<2)|(c3>>6));
+ *coded++ = CHAR64(c3&0x3f);
+ }
+ }
+ }
+ return coded;
+}
+
+
+
+/* sanitize "untrusted" text, replacing special control characters with the C
+ string version ("\x"), and replacing unprintable chars with ".".
+ text can grow to double size, so keep output buffer long enough!
+ returns a pointer to the first untouched byte of the output buffer.
+*/
+char *xiosanitize(const char *data, /* input data */
+ size_t bytes, /* length of input data, >=0 */
+ char *coded /* output buffer, must be long enough */
+ ) {
+ int c;
+
+ while (bytes > 0) {
+ c = *(unsigned char *)data++;
+ switch (c) {
+ case '\0' : *coded++ = '\\'; *coded++ = '0'; break;
+ case '\a' : *coded++ = '\\'; *coded++ = 'a'; break;
+ case '\b' : *coded++ = '\\'; *coded++ = 'b'; break;
+ case '\t' : *coded++ = '\\'; *coded++ = 't'; break;
+ case '\n' : *coded++ = '\\'; *coded++ = 'n'; break;
+ case '\v' : *coded++ = '\\'; *coded++ = 'v'; break;
+ case '\f' : *coded++ = '\\'; *coded++ = 'f'; break;
+ case '\r' : *coded++ = '\\'; *coded++ = 'r'; break;
+ case '\'' : *coded++ = '\\'; *coded++ = '\''; break;
+ case '\"' : *coded++ = '\\'; *coded++ = '"'; break;
+ case '\\' : *coded++ = '\\'; *coded++ = '\\'; break;
+ default:
+ if (!isprint(c))
+ c = '.';
+ *coded++ = c;
+ break;
+ }
+ --bytes;
+ }
+ return coded;
+}
+
+
+/* print the bytes in hex */
+char *
+ xiohexdump(const unsigned char *data, size_t bytes, char *coded) {
+ int space = 0;
+ while (bytes-- > 0) {
+ if (space) { *coded++ = ' '; }
+ coded += sprintf(coded, "%02x", *data++);
+ space = 1;
+ }
+ return coded;
+}
diff --git a/xio-ascii.h b/xio-ascii.h
new file mode 100644
index 0000000..bc4735d
--- /dev/null
+++ b/xio-ascii.h
@@ -0,0 +1,20 @@
+/* $Id: xio-ascii.h,v 1.4 2006/07/23 07:30:49 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2002-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_ascii_h_included
+#define __xio_ascii_h_included 1
+
+extern char *
+ xiob64encodeline(const char *data, /* input data */
+ size_t bytes, /* length of input data, >=0 */
+ char *coded /* output buffer, must be long enough */
+ );
+extern char *xiosanitize(const char *data, /* input data */
+ size_t bytes, /* length of input data, >=0 */
+ char *coded /* output buffer, must be long enough */
+ );
+extern char *
+ xiohexdump(const unsigned char *data, size_t bytes, char *coded);
+
+#endif /* !defined(__xio_ascii_h_included) */
diff --git a/xio-creat.c b/xio-creat.c
new file mode 100644
index 0000000..edc490a
--- /dev/null
+++ b/xio-creat.c
@@ -0,0 +1,79 @@
+/* $Id: xio-creat.c,v 1.16 2006/07/13 06:39:01 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of create type */
+
+#include "xiosysincludes.h"
+
+#if WITH_CREAT
+
+#include "xioopen.h"
+#include "xio-named.h"
+#include "xio-creat.h"
+
+
+static int xioopen_creat(int arg, const char *argv[], struct opt *opts, int rw, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
+
+
+/*! within stream model, this is a write-only address - use 2 instead of 3 */
+const struct addrdesc addr_creat = { "create", 3, xioopen_creat, GROUP_FD|GROUP_NAMED|GROUP_FILE, 0, 0, 0 HELP(":<filename>") };
+
+
+/* retrieve the mode option and perform the creat() call.
+ returns the file descriptor or a negative value. */
+static int _xioopen_creat(const char *path, int rw, struct opt *opts) {
+ mode_t mode = 0666;
+ int fd;
+
+ retropt_modet(opts, OPT_PERM, &mode);
+
+ if ((fd = Creat(path, mode)) < 0) {
+ Error3("creat(\"%s\", 0%03o): %s",
+ path, mode, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ return fd;
+}
+
+
+static int xioopen_creat(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
+ const char *filename = argv[1];
+ int rw = (xioflags&XIO_ACCMODE);
+ bool exists;
+ bool opt_unlink_close = false;
+ int result;
+
+ /* remove old file, or set user/permissions on old file; parse options */
+ if ((result = _xioopen_named_early(argc, argv, fd, groups, &exists, opts)) < 0) {
+ return result;
+ }
+
+ 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;
+ }
+
+ Notice2("creating regular file \"%s\" for %s", filename, ddirection[rw]);
+ if ((result = _xioopen_creat(filename, rw, opts)) < 0)
+ return result;
+ fd->stream.fd = result;
+
+ applyopts_named(filename, opts, PH_PASTOPEN);
+ if ((result = applyopts2(fd->stream.fd, opts, PH_PASTOPEN, PH_LATE2)) < 0)
+ return result;
+
+ applyopts_cloexec(fd->stream.fd, opts);
+
+ applyopts_fchown(fd->stream.fd, opts);
+
+ if ((result = _xio_openlate(&fd->stream, opts)) < 0)
+ return result;
+
+ return 0;
+}
+
+#endif /* WITH_CREAT */
diff --git a/xio-creat.h b/xio-creat.h
new file mode 100644
index 0000000..afe8073
--- /dev/null
+++ b/xio-creat.h
@@ -0,0 +1,10 @@
+/* $Id: xio-creat.h,v 1.4 2001/11/04 17:19:20 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_creat_h_included
+#define __xio_creat_h_included 1
+
+extern const struct addrdesc addr_creat;
+
+#endif /* !defined(__xio_creat_h_included) */
diff --git a/xio-exec.c b/xio-exec.c
new file mode 100644
index 0000000..2b2c3cd
--- /dev/null
+++ b/xio-exec.c
@@ -0,0 +1,137 @@
+/* $Id: xio-exec.c,v 1.19 2006/07/12 21:59:28 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of exec type */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+#include "nestlex.h"
+
+#include "xio-progcall.h"
+#include "xio-exec.h"
+
+#if WITH_EXEC
+
+static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
+ int xioflags, /* XIO_RDONLY etc. */
+ xiofile_t *fd,
+ unsigned groups,
+ int dummy1, int dummy2, int dummy3
+ );
+
+const struct addrdesc addr_exec = { "exec", 3, xioopen_exec, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, 0, 0, 0 HELP(":<command-line>") };
+
+const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREEXEC, TYPE_BOOL, OFUNC_SPEC };
+
+static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
+ int xioflags, /* XIO_RDONLY, XIO_MAYCHILD etc. */
+ xiofile_t *fd,
+ unsigned groups,
+ int dummy1, int dummy2, int dummy3
+ ) {
+ int status;
+ bool dash = false;
+
+ if (argc != 2) {
+ Error3("\"%s:%s\": wrong number of parameters (%d instead of 1)", argv[0], argv[1], argc-1);
+ }
+
+ retropt_bool(opts, OPT_DASH, &dash);
+
+ status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts);
+ if (status < 0) return status;
+ if (status == 0) { /* child */
+ const char *ends[] = { " ", NULL };
+ const char *hquotes[] = { "'", NULL };
+ const char *squotes[] = { "\"", NULL };
+ const char *nests[] = {
+ "'", "'",
+ "(", ")",
+ "[", "]",
+ "{", "}",
+ NULL
+ } ;
+ char **pargv = NULL;
+ int pargc, i;
+ size_t len;
+ const char *strp;
+ char *token; /*! */
+ char *tokp;
+ char *path = NULL;
+ char *tmp;
+ int numleft;
+ int result;
+
+ /*! Close(something) */
+ /* parse command line */
+ Debug1("child: args = \"%s\"", argv[1]);
+ pargv = Malloc(8*sizeof(char *));
+ if (pargv == NULL) return STAT_RETRYLATER;
+ i = 0;
+ len = strlen(argv[1])+1;
+ strp = argv[1];
+ token = Malloc(len); /*! */
+ tokp = token;
+ if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests,
+ true, true, false) < 0) {
+ Error("internal: miscalculated string lengths");
+ }
+ *tokp++ = '\0';
+ pargv[0] = strrchr(tokp-1, '/');
+ if (pargv[0] == NULL) pargv[0] = token; else ++pargv[0];
+ pargc = 1;
+ 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,
+ true, true, false) < 0) {
+ Error("internal: miscalculated string lengths");
+ }
+ *tokp++ = '\0';
+ }
+ pargv[pargc] = NULL;
+
+ if ((tmp = Malloc(strlen(pargv[0])+2)) == NULL) {
+ return STAT_RETRYLATER;
+ }
+ if (dash) {
+ tmp[0] = '-';
+ strcpy(tmp+1, pargv[0]);
+ } else {
+ strcpy(tmp, pargv[0]);
+ }
+ pargv[0] = tmp;
+
+ if (setopt_path(opts, &path) < 0) {
+ /* this could be dangerous, so let us abort this child... */
+ Exit(1);
+ }
+
+ if ((numleft = leftopts(opts)) > 0) {
+ Error1("%d option(s) could not be used", numleft);
+ showleft(opts);
+ return STAT_NORETRY;
+ }
+
+ Notice1("execvp'ing \"%s\"", token);
+ result = Execvp(token, pargv);
+ /* here we come only if execvp() failed */
+ switch (pargc) {
+ case 1: Error3("execvp(\"%s\", \"%s\"): %s", token, pargv[0], strerror(errno)); break;
+ case 2: Error4("execvp(\"%s\", \"%s\", \"%s\"): %s", token, pargv[0], pargv[1], strerror(errno)); break;
+ case 3:
+ default:
+ Error5("execvp(\"%s\", \"%s\", \"%s\", \"%s\", ...): %s", token, pargv[0], pargv[1], pargv[2], strerror(errno)); break;
+ }
+ Exit(1); /* this child process */
+ }
+
+ /* parent */
+ return 0;
+}
+#endif /* WITH_EXEC */
diff --git a/xio-exec.h b/xio-exec.h
new file mode 100644
index 0000000..ab84aed
--- /dev/null
+++ b/xio-exec.h
@@ -0,0 +1,12 @@
+/* $Id: xio-exec.h,v 1.6 2002/05/19 08:05:36 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001, 2002 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_exec_h_included
+#define __xio_exec_h_included 1
+
+extern const struct addrdesc addr_exec;
+
+extern const struct optdesc opt_dash;
+
+#endif /* !defined(__xio_exec_h_included) */
diff --git a/xio-ext2.c b/xio-ext2.c
new file mode 100644
index 0000000..6082190
--- /dev/null
+++ b/xio-ext2.c
@@ -0,0 +1,91 @@
+/* $Id: xio-ext2.c,v 1.1 2006/05/07 17:06:53 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2005-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for handling Linux ext2fs options
+ they can also be set with chattr(1) and viewed with lsattr(1) */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-ext2.h"
+
+
+#if WITH_EXT2
+
+/****** FD options ******/
+
+#ifdef EXT2_SECRM_FL
+/* secure deletion, chattr 's' */
+const struct optdesc opt_ext2_secrm = { "ext2-secrm", "secrm", OPT_EXT2_SECRM, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_SECRM_FL };
+#endif /* EXT2_SECRM_FL */
+
+#ifdef EXT2_UNRM_FL
+/* undelete, chattr 'u' */
+const struct optdesc opt_ext2_unrm = { "ext2-unrm", "unrm", OPT_EXT2_UNRM, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_UNRM_FL };
+#endif /* EXT2_UNRM_FL */
+
+#ifdef EXT2_COMPR_FL
+/* compress file, chattr 'c' */
+const struct optdesc opt_ext2_compr = { "ext2-compr", "compr", OPT_EXT2_COMPR, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_COMPR_FL };
+#endif /* EXT2_COMPR_FL */
+
+#ifdef EXT2_SYNC_FL
+/* synchronous update, chattr 'S' */
+const struct optdesc opt_ext2_sync = { "ext2-sync", "sync", OPT_EXT2_SYNC, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_SYNC_FL };
+#endif /* EXT2_SYNC_FL */
+
+#ifdef EXT2_IMMUTABLE_FL
+/* immutable file, chattr 'i' */
+const struct optdesc opt_ext2_immutable = { "ext2-immutable", "immutable", OPT_EXT2_IMMUTABLE, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_IMMUTABLE_FL };
+#endif /* EXT2_IMMUTABLE_FL */
+
+#ifdef EXT2_APPEND_FL
+/* writes to file may only append, chattr 'a' */
+const struct optdesc opt_ext2_append = { "ext2-append", "append", OPT_EXT2_APPEND, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_APPEND_FL };
+#endif /* EXT2_APPEND_FL */
+
+#ifdef EXT2_NODUMP_FL
+/* do not dump file, chattr 'd' */
+const struct optdesc opt_ext2_nodump = { "ext2-nodump", "nodump", OPT_EXT2_NODUMP, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_NODUMP_FL };
+#endif /* EXT2_NODUMP_FL */
+
+#ifdef EXT2_NOATIME_FL
+/* do not update atime, chattr 'A' */
+const struct optdesc opt_ext2_noatime = { "ext2-noatime", "noatime", OPT_EXT2_NOATIME, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_NOATIME_FL };
+#endif /* EXT2_NOATIME_FL */
+
+/* EXT2_DIRTY_FL ??? */
+/* EXT2_COMPRBLK_FL one ore more compress clusters */
+/* EXT2_NOCOMPR_FL access raw compressed data */
+/* EXT2_ECOMPR_FL compression error */
+/* EXT2_BTREE_FL btree format dir */
+/* EXT2_INDEX_FL hash indexed directory */
+/* EXT2_IMAGIC ??? */
+
+#ifdef EXT2_JOURNAL_DATA_FL
+/* file data should be journaled, chattr 'j' */
+const struct optdesc opt_ext2_journal_data = { "ext2-journal-data", "journal-data", OPT_EXT2_JOURNAL_DATA, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_JOURNAL_DATA_FL };
+#endif /* EXT2_JOURNAL_DATA_FL */
+
+#ifdef EXT2_NOTAIL_FL
+/* file tail should not be merged, chattr 't' */
+const struct optdesc opt_ext2_notail = { "ext2-notail", "notail", OPT_EXT2_NOTAIL, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_NOTAIL_FL };
+#endif /* EXT2_NOTAIL_FL */
+
+#ifdef EXT2_DIRSYNC_FL
+/* synchronous directory modifications, chattr 'D' */
+const struct optdesc opt_ext2_dirsync = { "ext2-dirsync", "dirsync", OPT_EXT2_DIRSYNC, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_DIRSYNC_FL };
+#endif /* EXT2_DIRSYNC_FL */
+
+#ifdef EXT2_TOPDIR_FL
+/* top of directory hierarchies, chattr 'T' */
+const struct optdesc opt_ext2_topdir = { "ext2-topdir", "topdir", OPT_EXT2_TOPDIR, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, EXT2_IOC_GETFLAGS, EXT2_IOC_SETFLAGS, EXT2_TOPDIR_FL };
+#endif /* EXT2_TOPDIR_FL */
+
+/* EXTENTS inode uses extents */
+
+
+#endif /* WITH_EXT2 */
+
+
diff --git a/xio-ext2.h b/xio-ext2.h
new file mode 100644
index 0000000..a7571c4
--- /dev/null
+++ b/xio-ext2.h
@@ -0,0 +1,21 @@
+/* $Id: xio-ext2.h,v 1.2 2006/05/31 19:28:24 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_ext2_h_included
+#define __xio_ext2_h_included 1
+
+extern const struct optdesc opt_ext2_secrm;
+extern const struct optdesc opt_ext2_unrm;
+extern const struct optdesc opt_ext2_compr;
+extern const struct optdesc opt_ext2_sync;
+extern const struct optdesc opt_ext2_immutable;
+extern const struct optdesc opt_ext2_append;
+extern const struct optdesc opt_ext2_nodump;
+extern const struct optdesc opt_ext2_noatime;
+extern const struct optdesc opt_ext2_journal_data;
+extern const struct optdesc opt_ext2_notail;
+extern const struct optdesc opt_ext2_dirsync;
+extern const struct optdesc opt_ext2_topdir;
+
+#endif /* !defined(__xio_ext2_h_included) */
diff --git a/xio-fd.c b/xio-fd.c
new file mode 100644
index 0000000..e9c29b9
--- /dev/null
+++ b/xio-fd.c
@@ -0,0 +1,77 @@
+/* $Id: xio-fd.c,v 1.26 2006/12/28 07:35:50 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains common file descriptor related option definitions */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-fd.h"
+
+/****** for ALL addresses - with open() or fcntl(F_SETFL) ******/
+const struct optdesc opt_append = { "append", NULL, OPT_O_APPEND, GROUP_OPEN|GROUP_FD, PH_LATE, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_APPEND };
+const struct optdesc opt_nonblock = { "o-nonblock", "nonblock", OPT_O_NONBLOCK, GROUP_OPEN|GROUP_FD, PH_FD, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_NONBLOCK };
+#if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
+const struct optdesc opt_o_ndelay = { "o-ndelay", NULL, OPT_O_NDELAY, GROUP_OPEN|GROUP_FD, PH_LATE, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_NDELAY };
+#endif
+#ifdef O_ASYNC
+const struct optdesc opt_async = { "async", NULL, OPT_O_ASYNC, GROUP_OPEN|GROUP_FD, PH_LATE, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_ASYNC };
+#endif
+#ifdef O_BINARY
+const struct optdesc opt_o_binary = { "o-binary", "binary", OPT_O_BINARY, GROUP_OPEN|GROUP_FD, PH_OPEN, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_BINARY };
+#endif
+#ifdef O_TEXT
+const struct optdesc opt_o_text = { "o-text", "text", OPT_O_TEXT, GROUP_OPEN|GROUP_FD, PH_OPEN, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_TEXT };
+#endif
+#ifdef O_NOINHERIT
+const struct optdesc opt_o_noinherit = { "o-noinherit", "noinherit", OPT_O_NOINHERIT, GROUP_OPEN|GROUP_FD, PH_OPEN, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_NOINHERIT };
+#endif
+#ifdef O_NOATIME
+const struct optdesc opt_o_noatime = { "o-noatime", "noatime", OPT_O_NOATIME, GROUP_OPEN|GROUP_FD, PH_FD, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_NOATIME };
+#endif
+/****** for ALL addresses - with fcntl(F_SETFD) ******/
+const struct optdesc opt_cloexec = { "cloexec", NULL, OPT_CLOEXEC, GROUP_FD, PH_LATE, TYPE_BOOL, OFUNC_FCNTL, F_SETFD, FD_CLOEXEC };
+/****** ftruncate() ******/
+/* this record is good for ftruncate() or ftruncate64() if available */
+#if HAVE_FTRUNCATE64
+const struct optdesc opt_ftruncate32 = { "ftruncate32", NULL, OPT_FTRUNCATE32, GROUP_REG, PH_LATE, TYPE_OFF32, OFUNC_SPEC };
+const struct optdesc opt_ftruncate64 = { "ftruncate64", "truncate", OPT_FTRUNCATE64, GROUP_REG, PH_LATE, TYPE_OFF64, OFUNC_SPEC };
+#else
+const struct optdesc opt_ftruncate32 = { "ftruncate32", "truncate", OPT_FTRUNCATE32, GROUP_REG, PH_LATE, TYPE_OFF32, OFUNC_SPEC };
+#endif /* !HAVE_FTRUNCATE64 */
+/****** for ALL addresses - permissions, ownership, and positioning ******/
+const struct optdesc opt_group = { "group", "gid", OPT_GROUP, GROUP_FD|GROUP_NAMED,PH_FD,TYPE_GIDT,OFUNC_SPEC };
+const struct optdesc opt_group_late= { "group-late","gid-l", OPT_GROUP_LATE,GROUP_FD, PH_LATE, TYPE_GIDT, OFUNC_SPEC };
+const struct optdesc opt_perm = { "perm", "mode", OPT_PERM, GROUP_FD|GROUP_NAMED, PH_FD, TYPE_MODET,OFUNC_SPEC };
+const struct optdesc opt_perm_late = { "perm-late", NULL, OPT_PERM_LATE, GROUP_FD, PH_LATE, TYPE_MODET,OFUNC_SPEC };
+const struct optdesc opt_user = { "user", "uid", OPT_USER, GROUP_FD|GROUP_NAMED, PH_FD, TYPE_UIDT, OFUNC_SPEC };
+const struct optdesc opt_user_late = { "user-late", "uid-l", OPT_USER_LATE, GROUP_FD, PH_LATE, TYPE_UIDT, OFUNC_SPEC };
+/* for something like random access files */
+#if HAVE_LSEEK64
+const struct optdesc opt_lseek32_cur = { "lseek32-cur", NULL, OPT_SEEK32_CUR, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_CUR };
+const struct optdesc opt_lseek32_end = { "lseek32-end", NULL, OPT_SEEK32_END, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_END };
+const struct optdesc opt_lseek32_set = { "lseek32-set", NULL, OPT_SEEK32_SET, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_SET };
+const struct optdesc opt_lseek64_cur = { "lseek64-cur", "seek-cur", OPT_SEEK64_CUR, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF64, OFUNC_SEEK64, SEEK_CUR };
+const struct optdesc opt_lseek64_end = { "lseek64-end", "seek-end", OPT_SEEK64_END, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF64, OFUNC_SEEK64, SEEK_END };
+const struct optdesc opt_lseek64_set = { "lseek64-set", "seek", OPT_SEEK64_SET, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF64, OFUNC_SEEK64, SEEK_SET };
+#else
+const struct optdesc opt_lseek32_cur = { "lseek32-cur", "seek-cur", OPT_SEEK32_CUR, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_CUR };
+const struct optdesc opt_lseek32_end = { "lseek32-end", "seek-end", OPT_SEEK32_END, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_END };
+const struct optdesc opt_lseek32_set = { "lseek32-set", "seek", OPT_SEEK32_SET, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_SET };
+#endif /* !HAVE_LSEEK64 */
+/* for all addresses (?) */
+const struct optdesc opt_f_setlk_rd = { "f-setlk-rd", "setlk-rd", OPT_F_SETLK_RD, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_SPEC, F_SETLK, F_RDLCK };
+const struct optdesc opt_f_setlkw_rd = { "f-setlkw-rd", "setlkw-rd",OPT_F_SETLKW_RD, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_SPEC, F_SETLKW, F_RDLCK };
+const struct optdesc opt_f_setlk_wr = { "f-setlk-wr", "setlk", OPT_F_SETLK_WR, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_SPEC, F_SETLK, F_WRLCK };
+const struct optdesc opt_f_setlkw_wr = { "f-setlkw-wr", "setlkw", OPT_F_SETLKW_WR, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_SPEC, F_SETLKW, F_WRLCK };
+#if HAVE_FLOCK
+const struct optdesc opt_flock_sh = { "flock-sh", NULL, OPT_FLOCK_SH, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_FLOCK, LOCK_SH };
+const struct optdesc opt_flock_sh_nb = { "flock-sh-nb", NULL, OPT_FLOCK_SH_NB, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_FLOCK, LOCK_SH|LOCK_NB };
+const struct optdesc opt_flock_ex = { "flock-ex", "flock", OPT_FLOCK_EX, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_FLOCK, LOCK_EX };
+const struct optdesc opt_flock_ex_nb = { "flock-ex-nb", "flock-nb", OPT_FLOCK_EX_NB, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_FLOCK, LOCK_EX|LOCK_NB };
+#endif /* HAVE_FLOCK */
+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", "close", OPT_END_CLOSE, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoend, END_CLOSE };
diff --git a/xio-fd.h b/xio-fd.h
new file mode 100644
index 0000000..6e3ed7d
--- /dev/null
+++ b/xio-fd.h
@@ -0,0 +1,41 @@
+/* $Id: xio-fd.h,v 1.12 2006/12/28 07:35:50 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* 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_append;
+extern const struct optdesc opt_nonblock;
+extern const struct optdesc opt_o_ndelay;
+extern const struct optdesc opt_async;
+extern const struct optdesc opt_o_binary;
+extern const struct optdesc opt_o_text;
+extern const struct optdesc opt_o_noinherit;
+extern const struct optdesc opt_cloexec;
+extern const struct optdesc opt_ftruncate32;
+extern const struct optdesc opt_ftruncate64;
+extern const struct optdesc opt_group;
+extern const struct optdesc opt_group_late;
+extern const struct optdesc opt_perm;
+extern const struct optdesc opt_perm_late;
+extern const struct optdesc opt_user;
+extern const struct optdesc opt_user_late;
+extern const struct optdesc opt_lseek32_cur;
+extern const struct optdesc opt_lseek32_end;
+extern const struct optdesc opt_lseek32_set;
+extern const struct optdesc opt_lseek64_cur;
+extern const struct optdesc opt_lseek64_end;
+extern const struct optdesc opt_lseek64_set;
+extern const struct optdesc opt_flock_sh;
+extern const struct optdesc opt_flock_sh_nb;
+extern const struct optdesc opt_flock_ex;
+extern const struct optdesc opt_flock_ex_nb;
+extern const struct optdesc opt_f_setlk_rd;
+extern const struct optdesc opt_f_setlkw_rd;
+extern const struct optdesc opt_f_setlk_wr;
+extern const struct optdesc opt_f_setlkw_wr;
+extern const struct optdesc opt_cool_write;
+extern const struct optdesc opt_end_close;
+
+#endif /* !defined(__xio_fd_h_included) */
diff --git a/xio-fdnum.c b/xio-fdnum.c
new file mode 100644
index 0000000..859a816
--- /dev/null
+++ b/xio-fdnum.c
@@ -0,0 +1,78 @@
+/* $Id: xio-fdnum.c,v 1.13 2006/07/08 10:03:14 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of fdnum type */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-fdnum.h"
+
+
+#if WITH_FDNUM
+
+static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
+
+
+const struct addrdesc addr_fd = { "fd", 3, xioopen_fdnum, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(":<num>") };
+
+
+/* use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
+static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xfd, unsigned groups,
+ int dummy1, int dummy2, int dummy3) {
+ char *a1;
+ int rw = (xioflags&XIO_ACCMODE);
+ int numfd;
+ int result;
+
+ if (argc != 2) {
+ Error3("%s:%s: wrong number of parameters (%d instead of 1)", argv[0], argv[1], argc-1);
+ }
+
+ numfd = strtoul(argv[1], &a1, 0);
+ if (*a1 != '\0') {
+ Error1("error in FD number \"%s\"", argv[1]);
+ }
+ /* we dont want to see these fds in child processes */
+ if (Fcntl_l(numfd, F_SETFD, FD_CLOEXEC) < 0) {
+ Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd, strerror(errno));
+ }
+ Notice2("using file descriptor %d for %s", numfd, ddirection[rw]);
+ if ((result = xioopen_fd(opts, rw, &xfd->stream, numfd, dummy2, dummy3)) < 0) {
+ return result;
+ }
+ return 0;
+}
+
+#endif /* WITH_FDNUM */
+
+#if WITH_FD
+
+/* retrieve and apply options to a standard file descriptor.
+ Do not set FD_CLOEXEC flag. */
+int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd, int dummy2, int dummy3) {
+
+ xfd->fd = numfd;
+ xfd->howtoend = END_NONE;
+
+#if WITH_TERMIOS
+ if (Isatty(xfd->fd)) {
+ if (Tcgetattr(xfd->fd, &xfd->savetty) < 0) {
+ Warn2("cannot query current terminal settings on fd %d: %s",
+ xfd->fd, strerror(errno));
+ } else {
+ xfd->ttyvalid = true;
+ }
+ }
+#endif /* WITH_TERMIOS */
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ applyopts2(xfd->fd, opts, PH_INIT, PH_FD);
+
+ return _xio_openlate(xfd, opts);
+}
+
+#endif /* WITH_FD */
diff --git a/xio-fdnum.h b/xio-fdnum.h
new file mode 100644
index 0000000..f9acf03
--- /dev/null
+++ b/xio-fdnum.h
@@ -0,0 +1,12 @@
+/* $Id: xio-fdnum.h,v 1.6 2006/03/21 20:48:31 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_fdnum_h_included
+#define __xio_fdnum_h_included 1
+
+extern const struct addrdesc addr_fd;
+
+extern int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd, int dummy2, int dummy3);
+
+#endif /* !defined(__xio_fdnum_h_included) */
diff --git a/xio-file.c b/xio-file.c
new file mode 100644
index 0000000..2156913
--- /dev/null
+++ b/xio-file.c
@@ -0,0 +1,124 @@
+/* $Id: xio-file.c,v 1.21 2007/03/06 21:07:25 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of open type */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-named.h"
+#include "xio-file.h"
+
+
+static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
+
+
+#if WITH_OPEN
+
+/****** OPEN addresses ******/
+const struct optdesc opt_o_rdonly = { "o-rdonly", "rdonly", OPT_O_RDONLY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG_PATTERN, O_RDONLY, O_ACCMODE };
+const struct optdesc opt_o_wronly = { "o-wronly", "wronly", OPT_O_WRONLY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG_PATTERN, O_WRONLY, O_ACCMODE };
+const struct optdesc opt_o_rdwr = { "o-rdwr", "rdwr", OPT_O_RDWR, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG_PATTERN, O_RDWR, O_ACCMODE };
+const struct optdesc opt_o_create = { "o-create", "creat", OPT_O_CREATE, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_CREAT };
+const struct optdesc opt_o_excl = { "o-excl", "excl", OPT_O_EXCL, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_EXCL };
+const struct optdesc opt_o_noctty = { "o-noctty", "noctty", OPT_O_NOCTTY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_NOCTTY };
+#ifdef O_SYNC
+const struct optdesc opt_o_sync = { "o-sync", "sync", OPT_O_SYNC, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_SYNC };
+#endif
+#ifdef O_NOFOLLOW
+const struct optdesc opt_o_nofollow = { "o-nofollow", "nofollow",OPT_O_NOFOLLOW, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_NOFOLLOW };
+#endif
+#ifdef O_DIRECTORY
+const struct optdesc opt_o_directory = { "o-directory", "directory",OPT_O_DIRECTORY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_DIRECTORY };
+#endif
+#ifdef O_LARGEFILE
+const struct optdesc opt_o_largefile = { "o-largefile", "largefile",OPT_O_LARGEFILE, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_LARGEFILE };
+#endif
+#ifdef O_NSHARE
+const struct optdesc opt_o_nshare = { "o-nshare", "nshare", OPT_O_NSHARE, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_NSHARE };
+#endif
+#ifdef O_RSHARE
+const struct optdesc opt_o_rshare = { "o-rshare", "rshare", OPT_O_RSHARE, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_RSHARE };
+#endif
+#ifdef O_DEFER
+const struct optdesc opt_o_defer = { "o-defer", "defer", OPT_O_DEFER, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_DEFER };
+#endif
+#ifdef O_DIRECT
+const struct optdesc opt_o_direct = { "o-direct", "direct", OPT_O_DIRECT, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_DIRECT };
+#endif
+#ifdef O_DSYNC
+const struct optdesc opt_o_dsync = { "o-dsync", "dsync", OPT_O_DSYNC, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_DSYNC };
+#endif
+#ifdef O_RSYNC
+const struct optdesc opt_o_rsync = { "o-rsync", "rsync", OPT_O_RSYNC, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_RSYNC };
+#endif
+#ifdef O_DELAY
+const struct optdesc opt_o_delay = { "o-delay", "delay", OPT_O_DELAY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_DELAY };
+#endif
+#ifdef O_PRIV
+const struct optdesc opt_o_priv = { "o-priv", "priv", OPT_O_PRIV, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_PRIV };
+#endif
+const struct optdesc opt_o_trunc = { "o-trunc", "trunc", OPT_O_TRUNC, GROUP_OPEN, PH_LATE, TYPE_BOOL, OFUNC_FLAG, O_TRUNC };
+
+#endif /* WITH_OPEN */
+
+
+#if _WITH_FILE /*! inconsistent name FILE vs. OPEN */
+
+const struct addrdesc addr_open = { "open", 3, xioopen_open, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS, 0, 0, 0 HELP(":<filename>") };
+
+/* open for writing:
+ if the filesystem entry already exists, the data is appended
+ if it does not exist, a file is created and the data is appended
+*/
+static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
+ const char *filename = argv[1];
+ int rw = (xioflags & XIO_ACCMODE);
+ bool exists;
+ bool opt_unlink_close = false;
+ int result;
+
+ /* remove old file, or set user/permissions on old file; parse options */
+ if ((result = _xioopen_named_early(argc, argv, fd, groups, &exists, opts)) < 0) {
+ return result;
+ }
+
+ 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;
+ }
+
+ Notice3("opening %s \"%s\" for %s",
+ filetypenames[(result&S_IFMT)>>12], filename, ddirection[rw]);
+ if ((result = _xioopen_open(filename, rw, opts)) < 0)
+ return result;
+ fd->stream.fd = result;
+
+#if WITH_TERMIOS
+ if (Isatty(fd->stream.fd)) {
+ if (Tcgetattr(fd->stream.fd, &fd->stream.savetty) < 0) {
+ Warn2("cannot query current terminal settings on fd %d: %s",
+ fd->stream.fd, strerror(errno));
+ } else {
+ fd->stream.ttyvalid = true;
+ }
+ }
+#endif /* WITH_TERMIOS */
+
+ applyopts_named(filename, opts, PH_FD);
+ applyopts(fd->stream.fd, opts, PH_FD);
+ applyopts_cloexec(fd->stream.fd, opts);
+
+ applyopts_fchown(fd->stream.fd, opts);
+
+ if ((result = _xio_openlate(&fd->stream, opts)) < 0)
+ return result;
+
+ return 0;
+}
+
+#endif /* _WITH_FILE */
diff --git a/xio-file.h b/xio-file.h
new file mode 100644
index 0000000..03d16c9
--- /dev/null
+++ b/xio-file.h
@@ -0,0 +1,31 @@
+/* $Id: xio-file.h,v 1.8 2006/07/13 21:19:15 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_file_h_included
+#define __xio_file_h_included 1
+
+extern const struct optdesc opt_o_rdonly;
+extern const struct optdesc opt_o_wronly;
+extern const struct optdesc opt_o_rdwr;
+extern const struct optdesc opt_o_create;
+extern const struct optdesc opt_o_excl;
+extern const struct optdesc opt_o_noctty;
+extern const struct optdesc opt_o_sync;
+extern const struct optdesc opt_o_nofollow;
+extern const struct optdesc opt_o_directory;
+extern const struct optdesc opt_o_largefile;
+extern const struct optdesc opt_o_nshare;
+extern const struct optdesc opt_o_rshare;
+extern const struct optdesc opt_o_defer;
+extern const struct optdesc opt_o_direct;
+extern const struct optdesc opt_o_dsync;
+extern const struct optdesc opt_o_rsync;
+extern const struct optdesc opt_o_delay;
+extern const struct optdesc opt_o_priv;
+extern const struct optdesc opt_o_trunc;
+extern const struct optdesc opt_o_noatime;
+
+extern const struct addrdesc addr_open;
+
+#endif /* !defined(__xio_file_h_included) */
diff --git a/xio-gopen.c b/xio-gopen.c
new file mode 100644
index 0000000..3108da8
--- /dev/null
+++ b/xio-gopen.c
@@ -0,0 +1,218 @@
+/* $Id: xio-gopen.c,v 1.32 2007/02/08 18:36:44 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of generic open type */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-named.h"
+#include "xio-unix.h"
+#include "xio-gopen.h"
+
+
+#if WITH_GOPEN
+
+static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
+
+
+const struct addrdesc addr_gopen = { "gopen", 3, xioopen_gopen, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS|GROUP_SOCKET|GROUP_SOCK_UNIX, 0, 0, 0 HELP(":<filename>") };
+
+static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
+ const char *filename = argv[1];
+ flags_t openflags = (xioflags & XIO_ACCMODE);
+ mode_t st_mode;
+ bool exists;
+ bool opt_unlink_close = false;
+ int result;
+
+ if ((result =
+ _xioopen_named_early(argc, argv, fd, GROUP_NAMED|groups, &exists, opts)) < 0) {
+ return result;
+ }
+ st_mode = result;
+
+ if (exists) {
+ /* file (or at least named entry) exists */
+ if ((xioflags&XIO_ACCMODE) != XIO_RDONLY) {
+ openflags |= O_APPEND;
+ }
+ } else {
+ openflags |= O_CREAT;
+ }
+
+ /* 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;
+ 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;
+ }
+
+ 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.fd = Socket(PF_UNIX, socktype, 0)) < 0) {
+ Error2("socket(PF_UNIX, %d, 0): %s", socktype, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ /*0 Info2("socket(PF_UNIX, %d, 0) -> %d", socktype, fd->stream.fd);*/
+ applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
+ applyopts(fd->stream.fd, opts, PH_FD);
+
+ applyopts_cloexec(fd->stream.fd, opts);
+
+ sa.sun_family = AF_UNIX;
+ salen = xiosetunix(&sa, filename, false, false);
+
+#if 0
+ applyopts(fd->stream.fd, opts, PH_PREBIND);
+ applyopts(fd->stream.fd, opts, PH_BIND);
+ if (us) {
+ if (Bind(fd->stream.fd, 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.fd, opts, PH_PASTBIND);
+#endif /* 0 */
+
+ applyopts(fd->stream.fd, opts, PH_CONNECT);
+ if ((result = Connect(fd->stream.fd, (struct sockaddr *)&sa, salen)) < 0) {
+ if (errno == EINPROGRESS) {
+ Warn4("connect(%d, %s, "F_Zd"): %s",
+ fd->stream.fd, 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.fd, sockaddr_unix_info(&sa, salen, infobuff, sizeof(infobuff)),
+ sizeof(sa), strerror(errno));
+ Info("assuming datagram socket");
+ Close(fd->stream.fd);
+
+ opts = opts2;
+ if ((fd->stream.fd = 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.fd);*/
+
+ applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
+ applyopts(fd->stream.fd, opts, PH_FD);
+
+ applyopts_cloexec(fd->stream.fd, 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.fd, sockaddr_unix_info(&sa, fd->stream.salen, infobuff, sizeof(infobuff)),
+ sizeof(sa), strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ }
+ if (fd->stream.howtoend == END_UNSPEC) {
+ fd->stream.howtoend = END_SHUTDOWN;
+ }
+
+ applyopts_fchown(fd->stream.fd, opts);
+ applyopts(fd->stream.fd, opts, PH_CONNECTED);
+ applyopts(fd->stream.fd, opts, PH_LATE);
+ applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */
+
+ if (Getsockname(fd->stream.fd, (struct sockaddr *)&us, &uslen) < 0) {
+ Warn4("getsockname(%d, %p, {%d}): %s",
+ fd->stream.fd, &us, uslen, strerror(errno));
+ } else {
+ Notice1("successfully connected via %s",
+ sockaddr_unix_info(&us, uslen, infobuff, sizeof(infobuff)));
+ }
+#else
+ Error("\"%s\" is a socket, but UNIX socket support is not compiled in");
+ return -1;
+#endif /* WITH_UNIX */
+
+ } else {
+ /* a file name */
+
+ Info1("\"%s\" is not a socket, open()'ing it", filename);
+
+ 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;
+ }
+
+ Notice3("opening %s \"%s\" for %s",
+ filetypenames[(st_mode&S_IFMT)>>12], filename, ddirection[(xioflags&XIO_ACCMODE)]);
+ if ((result = _xioopen_open(filename, openflags, opts)) < 0)
+ return result;
+#ifdef I_PUSH
+ if (S_ISCHR(st_mode)) {
+ Ioctl(result, I_PUSH, "ptem");
+ Ioctl(result, I_PUSH, "ldterm");
+ Ioctl(result, I_PUSH, "ttcompat");
+ }
+#endif
+ fd->stream.fd = result;
+
+#if WITH_TERMIOS
+ if (Isatty(fd->stream.fd)) {
+ if (Tcgetattr(fd->stream.fd, &fd->stream.savetty) < 0) {
+ Warn2("cannot query current terminal settings on fd %d: %s",
+ fd->stream.fd, strerror(errno));
+ } else {
+ fd->stream.ttyvalid = true;
+ }
+ }
+#endif /* WITH_TERMIOS */
+ applyopts_named(filename, opts, PH_FD);
+ applyopts(fd->stream.fd, opts, PH_FD);
+ applyopts_cloexec(fd->stream.fd, opts);
+ }
+
+ if ((result = applyopts2(fd->stream.fd, opts, PH_PASTSOCKET, PH_CONNECTED)) < 0)
+ return result;
+
+ if ((result = _xio_openlate(&fd->stream, opts)) < 0)
+ return result;
+ return 0;
+}
+
+#endif /* WITH_GOPEN */
diff --git a/xio-gopen.h b/xio-gopen.h
new file mode 100644
index 0000000..dff3084
--- /dev/null
+++ b/xio-gopen.h
@@ -0,0 +1,10 @@
+/* $Id: xio-gopen.h,v 1.4 2001/11/04 17:19:20 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_gopen_h_included
+#define __xio_gopen_h_included 1
+
+extern const struct addrdesc addr_gopen;
+
+#endif /* !defined(__xio_gopen_h_included) */
diff --git a/xio-ip.c b/xio-ip.c
new file mode 100644
index 0000000..cb065dc
--- /dev/null
+++ b/xio-ip.c
@@ -0,0 +1,510 @@
+/* $Id: xio-ip.c,v 1.31 2007/03/06 21:08:02 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for IP related functions */
+
+#include "xiosysincludes.h"
+
+#if _WITH_IP4 || _WITH_IP6
+
+#include "xioopen.h"
+#include "xio-socket.h"
+#include "xio-ip.h"
+#include "xio-ip6.h"
+
+
+#if WITH_IP4 || WITH_IP6
+
+#ifdef IP_OPTIONS
+const struct optdesc opt_ip_options = { "ip-options", "ipoptions", OPT_IP_OPTIONS, GROUP_SOCK_IP, PH_PASTSOCKET,TYPE_BIN, OFUNC_SOCKOPT_APPEND, SOL_IP, IP_OPTIONS };
+#endif
+#ifdef IP_PKTINFO
+const struct optdesc opt_ip_pktinfo = { "ip-pktinfo", "pktinfo", OPT_IP_PKTINFO, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_PKTINFO };
+#endif
+#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
+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
+const struct optdesc opt_ip_recvopts= { "ip-recvopts","recvopts", OPT_IP_RECVOPTS,GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_RECVOPTS };
+#endif
+#ifdef IP_RETOPTS
+const struct optdesc opt_ip_retopts = { "ip-retopts", "retopts", OPT_IP_RETOPTS, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_RETOPTS };
+#endif
+const struct optdesc opt_ip_tos = { "ip-tos", "tos", OPT_IP_TOS, GROUP_SOCK_IP, PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_TOS };
+const struct optdesc opt_ip_ttl = { "ip-ttl", "ttl", OPT_IP_TTL, GROUP_SOCK_IP, PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_TTL };
+#ifdef IP_HDRINCL
+const struct optdesc opt_ip_hdrincl = { "ip-hdrincl", "hdrincl", OPT_IP_HDRINCL, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_HDRINCL };
+#endif
+#ifdef IP_RECVERR
+const struct optdesc opt_ip_recverr = { "ip-recverr", "recverr", OPT_IP_RECVERR, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_RECVERR };
+#endif
+#ifdef IP_MTU_DISCOVER
+const struct optdesc opt_ip_mtu_discover={"ip-mtu-discover","mtudiscover",OPT_IP_MTU_DISCOVER,GROUP_SOCK_IP,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_IP,IP_MTU_DISCOVER };
+#endif
+#ifdef IP_MTU
+const struct optdesc opt_ip_mtu = { "ip-mtu", "mtu", OPT_IP_MTU, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_MTU };
+#endif
+#ifdef IP_FREEBIND
+const struct optdesc opt_ip_freebind= { "ip-freebind","freebind", OPT_IP_FREEBIND,GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_FREEBIND };
+#endif
+#ifdef IP_ROUTER_ALERT
+const struct optdesc opt_ip_router_alert={"ip-router-alert","routeralert",OPT_IP_ROUTER_ALERT,GROUP_SOCK_IP,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_IP,IP_ROUTER_ALERT};
+#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};
+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 };
+#endif
+#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
+
+#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 };
+const struct optdesc opt_res_aaonly = { "res-aaonly", "aaonly", OPT_RES_AAONLY, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, (size_t)&((xiosingle_t *)0)->para.socket.ip.res_opts, sizeof(unsigned long), RES_AAONLY };
+const struct optdesc opt_res_usevc = { "res-usevc", "usevc", OPT_RES_USEVC, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, (size_t)&((xiosingle_t *)0)->para.socket.ip.res_opts, sizeof(unsigned long), RES_USEVC };
+const struct optdesc opt_res_primary = { "res-primary", "primary", OPT_RES_PRIMARY, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, (size_t)&((xiosingle_t *)0)->para.socket.ip.res_opts, sizeof(unsigned long), RES_PRIMARY };
+const struct optdesc opt_res_igntc = { "res-igntc", "igntc", OPT_RES_IGNTC, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, (size_t)&((xiosingle_t *)0)->para.socket.ip.res_opts, sizeof(unsigned long), RES_IGNTC };
+const struct optdesc opt_res_recurse = { "res-recurse", "recurse", OPT_RES_RECURSE, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, (size_t)&((xiosingle_t *)0)->para.socket.ip.res_opts, sizeof(unsigned long), RES_RECURSE };
+const struct optdesc opt_res_defnames = { "res-defnames", "defnames", OPT_RES_DEFNAMES, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, (size_t)&((xiosingle_t *)0)->para.socket.ip.res_opts, sizeof(unsigned long), RES_DEFNAMES };
+const struct optdesc opt_res_stayopen = { "res-stayopen", "stayopen", OPT_RES_STAYOPEN, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, (size_t)&((xiosingle_t *)0)->para.socket.ip.res_opts, sizeof(unsigned long), RES_STAYOPEN };
+const struct optdesc opt_res_dnsrch = { "res-dnsrch", "dnsrch", OPT_RES_DNSRCH, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, (size_t)&((xiosingle_t *)0)->para.socket.ip.res_opts, sizeof(unsigned long), RES_DNSRCH };
+#endif /* HAVE_RESOLV_H */
+
+#endif /* WITH_IP4 || WITH_IP6 */
+
+
+#if HAVE_RESOLV_H
+int Res_init(void) {
+ int result;
+ Debug("res_init()");
+ result = res_init();
+ Debug1("res_init() -> %d", result);
+ return result;
+}
+#endif /* HAVE_RESOLV_H */
+
+#if HAVE_RESOLV_H
+unsigned long res_opts() {
+ return _res.options;
+}
+#endif /* HAVE_RESOLV_H */
+
+/* the ultimate(?) socat resolver function
+ node: the address to be resolved; supported forms:
+ 1.2.3.4 (IPv4 address)
+ [::2] (IPv6 address)
+ hostname (hostname resolving to IPv4 or IPv6 address)
+ hostname.domain (fq hostname resolving to IPv4 or IPv6 address)
+ service: the port specification; may be numeric or symbolic
+ family: PF_INET, PF_INET6, or PF_UNSPEC permitting both
+ socktype: SOCK_STREAM, SOCK_DGRAM
+ protocol: IPPROTO_UDP, IPPROTO_TCP
+ sau: an uninitialized storage for the resulting socket address
+ returns: STAT_OK, STAT_RETRYLATER
+*/
+int xiogetaddrinfo(const char *node, const char *service,
+ int family, int socktype, int protocol,
+ union sockaddr_union *sau, socklen_t *socklen,
+ unsigned long res_opts0, unsigned long res_opts1) {
+ int port = -1;
+ char *numnode = NULL;
+ size_t nodelen;
+ unsigned long save_res_opts = 0;
+#if HAVE_GETADDRINFO
+ struct addrinfo hints = {0};
+ struct addrinfo *res = NULL;
+#else /* HAVE_GETIPNODEBYNAME || nothing */
+ struct hostent *host;
+#endif
+ int error_num;
+
+#if HAVE_RESOLV_H
+ if (res_opts0 | res_opts1) {
+ if (!(_res.options & RES_INIT)) {
+ Res_init(); /*!!! returns -1 on error */
+ }
+ save_res_opts = _res.options;
+ _res.options &= ~res_opts0;
+ _res.options |= res_opts1;
+ Debug2("changed _res.options from 0x%lx to 0x%lx",
+ save_res_opts, _res.options);
+ }
+#endif /* HAVE_RESOLV_H */
+ memset(sau, 0, *socklen);
+ sau->soa.sa_family = family;
+
+ /* if service is numeric we don't want to have a lookup (might take long
+ with NIS), so we handle this specially */
+ if (service && isdigit(service[0]&0xff)) {
+ char *extra;
+ port = strtoul(service, &extra, 0);
+ if (*extra != '\0') {
+ Warn2("xiogetaddrinfo(, \"%s\", ...): extra trailing data \"%s\"",
+ service, extra);
+ }
+ service = NULL;
+ }
+
+ /* the resolver functions might handle numeric forms of node names by
+ reverse lookup, that's not what we want.
+ So we detect these and handle them specially */
+ if (node && isdigit(node[0]&0xff)) {
+#if HAVE_GETADDRINFO
+ hints.ai_flags |= AI_NUMERICHOST;
+#endif /* HAVE_GETADDRINFO */
+ if (family == PF_UNSPEC) {
+ family = PF_INET;
+#if HAVE_GETADDRINFO
+ } else if (family == PF_INET6) {
+ /* map "explicitely" into IPv6 address space; getipnodebyname() does
+ this with AI_V4MAPPED, but not getaddrinfo() */
+ if ((numnode = Malloc(strlen(node)+7+1)) == NULL) {
+#if HAVE_RESOLV_H
+ if (res_opts0 | res_opts1) {
+ _res.options = (_res.options & (~res_opts0&~res_opts1) |
+ save_res_opts& ( res_opts0| res_opts1));
+ }
+#endif
+ return STAT_NORETRY;
+ }
+ sprintf(numnode, "::ffff:%s", node);
+ node = numnode;
+ hints.ai_flags |= AI_NUMERICHOST;
+#endif /* HAVE_GETADDRINFO */
+ }
+#if WITH_IP6
+ } else if (node && node[0] == '[' && node[(nodelen=strlen(node))-1]==']') {
+ if ((numnode = Malloc(nodelen-1)) == NULL) {
+#if HAVE_RESOLV_H
+ if (res_opts0 | res_opts1) {
+ _res.options = (_res.options & (~res_opts0&~res_opts1) |
+ save_res_opts& ( res_opts0| res_opts1));
+ }
+#endif
+ return STAT_NORETRY;
+ }
+ strncpy(numnode, node+1, nodelen-2);
+ numnode[nodelen-2] = '\0';
+ node = numnode;
+#if HAVE_GETADDRINFO
+ hints.ai_flags |= AI_NUMERICHOST;
+#endif /* HAVE_GETADDRINFO */
+ if (family == PF_UNSPEC) family = PF_INET6;
+#endif /* WITH_IP6 */
+ }
+
+#if HAVE_GETADDRINFO
+ if (node != NULL || service != NULL) {
+ struct addrinfo *record;
+
+ hints.ai_flags |= AI_PASSIVE;
+ hints.ai_family = family;
+ hints.ai_socktype = socktype;
+ hints.ai_protocol = protocol;
+ hints.ai_addrlen = 0;
+ hints.ai_addr = NULL;
+ hints.ai_canonname = NULL;
+ hints.ai_next = NULL;
+
+ if ((error_num = Getaddrinfo(node, service, &hints, &res)) != 0) {
+ Error7("getaddrinfo(\"%s\", \"%s\", {%d,%d,%d,%d}, {}): %s",
+ node, service, hints.ai_flags, hints.ai_family,
+ hints.ai_socktype, hints.ai_protocol,
+ (error_num == EAI_SYSTEM)?
+ strerror(errno):gai_strerror(error_num));
+ if (res != NULL) freeaddrinfo(res);
+ if (numnode) free(numnode);
+
+#if HAVE_RESOLV_H
+ if (res_opts0 | res_opts1) {
+ _res.options = (_res.options & (~res_opts0&~res_opts1) |
+ save_res_opts& ( res_opts0| res_opts1));
+ }
+#endif
+ return STAT_RETRYLATER;
+ }
+
+ record = res;
+ if (family == PF_UNSPEC && xioopts.preferred_ip == '0') {
+ /* we just take the first result */
+ family = res[0].ai_addr->sa_family;
+ }
+ if (family == PF_UNSPEC) {
+ int trypf;
+ trypf = (xioopts.preferred_ip=='6'?PF_INET6:PF_INET);
+ /* we must look for a matching entry */
+ while (record != NULL) {
+ if (record->ai_family == trypf) {
+ family = trypf;
+ break; /* family and record set accordingly */
+ }
+ record = record->ai_next;
+ }
+ if (record == NULL) {
+ /* we did not find a "preferred" entry, take the first */
+ record = res;
+ family = res[0].ai_addr->sa_family;
+ }
+ }
+
+ switch (family) {
+#if WITH_IP4
+ case PF_INET:
+ if (*socklen > record->ai_addrlen) {
+ *socklen = record->ai_addrlen;
+ }
+ memcpy(&sau->ip4, record->ai_addr, *socklen);
+ break;
+#endif /* WITH_IP4 */
+#if WITH_IP6
+ case PF_INET6:
+#if _AIX
+ /* older AIX versions pass wrong length, so we correct it */
+ record->ai_addr->sa_len = sizeof(struct sockaddr_in6);
+#endif
+ if (*socklen > record->ai_addrlen) {
+ *socklen = record->ai_addrlen;
+ }
+ memcpy(&sau->ip6, record->ai_addr, *socklen);
+ break;
+#endif /* WITH_IP6 */
+ default:
+ Error1("address resolved to unknown protocol family %d",
+ record->ai_addr->sa_family);
+ break;
+ }
+ freeaddrinfo(res);
+ } else {
+ switch (family) {
+#if WITH_IP4
+ case PF_INET: *socklen = sizeof(sau->ip4); break;
+#endif /* WITH_IP4 */
+#if WITH_IP6
+ case PF_INET6: *socklen = sizeof(sau->ip6); break;
+#endif /* WITH_IP6 */
+ }
+ }
+
+#elif HAVE_GETIPNODEBYNAME /* !HAVE_GETADDRINFO */
+
+ if (node != NULL) {
+ /* first fallback is getipnodebyname() */
+ if (family == PF_UNSPEC) {
+#if WITH_IP4 && WITH_IP6
+ family = xioopts.default_ip=='6'?PF_INET6:PF_INET;
+#elif WITH_IP6
+ family = PF_INET6;
+#else
+ family = PF_INET;
+#endif
+ }
+ host = Getipnodebyname(node, family, AI_V4MAPPED, &error_num);
+ if (host == NULL) {
+ const static char ai_host_not_found[] = "Host not found";
+ const static char ai_no_address[] = "No address";
+ const static char ai_no_recovery[] = "No recovery";
+ const static char ai_try_again[] = "Try again";
+ const char *error_msg = "Unknown error";
+ switch (error_num) {
+ case HOST_NOT_FOUND: error_msg = ai_host_not_found; break;
+ case NO_ADDRESS: error_msg = ai_no_address;
+ case NO_RECOVERY: error_msg = ai_no_recovery;
+ case TRY_AGAIN: error_msg = ai_try_again;
+ }
+ Error2("getipnodebyname(\"%s\", ...): %s", node, error_msg);
+ } else {
+ switch (family) {
+#if WITH_IP4
+ case PF_INET:
+ *socklen = sizeof(sau->ip4);
+ sau->soa.sa_family = PF_INET;
+ memcpy(&sau->ip4.sin_addr, host->h_addr_list[0], 4);
+ break;
+#endif
+#if WITH_IP6
+ case PF_INET6:
+ *socklen = sizeof(sau->ip6);
+ sau->soa.sa_family = PF_INET6;
+ memcpy(&sau->ip6.sin6_addr, host->h_addr_list[0], 16);
+ break;
+#endif
+ }
+ }
+ freehostent(host);
+ }
+
+#else /* !HAVE_GETIPNODEBYNAME */
+
+ if (node != NULL) {
+ /* this is not a typical IP6 resolver function - but Linux
+ "man gethostbyname" says that the only supported address type with
+ this function is AF_INET _at present_, so maybe this fallback will
+ be useful somewhere sometimesin a future even for IP6 */
+ if (family == PF_UNSPEC) {
+#if WITH_IP4 && WITH_IP6
+ family = xioopts.default_ip=='6'?PF_INET6:PF_INET;
+#elif WITH_IP6
+ family = PF_INET6;
+#else
+ family = PF_INET;
+#endif
+ }
+ /*!!! try gethostbyname2 for IP6 */
+ if ((host = Gethostbyname(node)) == NULL) {
+ Error2("gethostbyname(\"%s\"): %s", node,
+ h_errno == NETDB_INTERNAL ? strerror(errno) :
+ hstrerror(h_errno));
+#if HAVE_RESOLV_H
+ if (res_opts0 | res_opts1) {
+ _res.options = (_res.options & (~res_opts0&~res_opts1) |
+ save_res_opts& ( res_opts0| res_opts1));
+ }
+#endif
+ return STAT_RETRYLATER;
+ }
+ if (host->h_addrtype != family) {
+ Error2("xioaddrinfo(): \"%s\" does not resolve to %s",
+ node, family==PF_INET?"IP4":"IP6");
+ } else {
+ switch (family) {
+#if WITH_IP4
+ case PF_INET:
+ *socklen = sizeof(sau->ip4);
+ sau->soa.sa_family = PF_INET;
+ memcpy(&sau->ip4.sin_addr, host->h_addr_list[0], 4);
+ break;
+#endif /* WITH_IP4 */
+#if WITH_IP6
+ case PF_INET6:
+ *socklen = sizeof(sau->ip6);
+ sau->soa.sa_family = PF_INET6;
+ memcpy(&sau->ip6.sin6_addr, host->h_addr_list[0], 16);
+ break;
+#endif /* WITH_IP6 */
+ }
+ }
+ }
+
+#endif
+
+#if WITH_TCP || WITH_UDP
+ if (service) {
+ port = parseport(service, family);
+ }
+ if (port >= 0) {
+ switch (family) {
+#if WITH_IP4
+ case PF_INET: sau->ip4.sin_port = htons(port); break;
+#endif /* WITH_IP4 */
+#if WITH_IP6
+ case PF_INET6: sau->ip6.sin6_port = htons(port); break;
+#endif /* WITH_IP6 */
+ }
+ }
+#endif /* WITH_TCP || WITH_UDP */
+
+ if (numnode) free(numnode);
+
+#if HAVE_RESOLV_H
+ if (res_opts0 | res_opts1) {
+ _res.options = (_res.options & (~res_opts0&~res_opts1) |
+ save_res_opts& ( res_opts0| res_opts1));
+ }
+#endif /* HAVE_RESOLV_H */
+ return STAT_OK;
+}
+
+
+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;
+
+ 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 */
+ default:
+ Error1("range option not supported with address family %d", pf);
+ return STAT_NORETRY;
+ }
+ return 0;
+}
+
+#endif /* _WITH_IP4 || _WITH_IP6 */
diff --git a/xio-ip.h b/xio-ip.h
new file mode 100644
index 0000000..2cf8277
--- /dev/null
+++ b/xio-ip.h
@@ -0,0 +1,48 @@
+/* $Id: xio-ip.h,v 1.11 2007/03/06 21:19:18 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_ip_h_included
+#define __xio_ip_h_included 1
+
+extern const struct optdesc opt_ip_options;
+extern const struct optdesc opt_ip_pktinfo;
+extern const struct optdesc opt_ip_recvtos;
+extern const struct optdesc opt_ip_recvttl;
+extern const struct optdesc opt_ip_recvopts;
+extern const struct optdesc opt_ip_retopts;
+extern const struct optdesc opt_ip_tos;
+extern const struct optdesc opt_ip_ttl;
+extern const struct optdesc opt_ip_hdrincl;
+extern const struct optdesc opt_ip_recverr;
+extern const struct optdesc opt_ip_mtu_discover;
+extern const struct optdesc opt_ip_mtu;
+extern const struct optdesc opt_ip_freebind;
+extern const struct optdesc opt_ip_router_alert;
+extern const struct optdesc opt_ip_multicast_ttl;
+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_res_debug;
+extern const struct optdesc opt_res_aaonly;
+extern const struct optdesc opt_res_usevc;
+extern const struct optdesc opt_res_primary;
+extern const struct optdesc opt_res_igntc;
+extern const struct optdesc opt_res_recurse;
+extern const struct optdesc opt_res_defnames;
+extern const struct optdesc opt_res_stayopen;
+extern const struct optdesc opt_res_dnsrch;
+
+extern int xiogetaddrinfo(const char *node, const char *service,
+ int family, int socktype, int protocol,
+ 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);
+
+#endif /* !defined(__xio_ip_h_included) */
diff --git a/xio-ip4.c b/xio-ip4.c
new file mode 100644
index 0000000..29e121a
--- /dev/null
+++ b/xio-ip4.c
@@ -0,0 +1,46 @@
+/* $Id: xio-ip4.c,v 1.13 2007/03/06 21:08:38 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for IP4 related functions */
+
+#include "xiosysincludes.h"
+
+#if WITH_IP4
+
+#include "xioopen.h"
+#include "xio-socket.h"
+#include "xio-ip.h"
+#include "xio-ip4.h"
+
+/* 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;
+ char addrbuf[256], maskbuf[256];
+ char peername[256];
+
+ /* is provided client address valid? */
+ if (pa->sin_addr.s_addr == 0) {
+ Warn("invalid client address 0.0.0.0");
+ return -1;
+ }
+ /* client address restriction */
+ Debug2("permitted client subnet: %s:%s",
+ inet4addr_info(ntohl(netaddr_in->s_addr), addrbuf, sizeof(addrbuf)),
+ inet4addr_info(ntohl(netmask_in->s_addr), maskbuf, sizeof(maskbuf)));
+ Debug1("client address is 0x%08x",
+ ntohl(pa->sin_addr.s_addr));
+ Debug1("masked address is 0x%08x",
+ ntohl(pa->sin_addr.s_addr & netmask_in->s_addr));
+ if ((pa->sin_addr.s_addr & netmask_in->s_addr)
+ != netaddr_in->s_addr) {
+ Debug1("client address %s is not permitted",
+ sockaddr_inet4_info(pa, peername, sizeof(peername)));
+ return -1;
+ }
+ return 0;
+}
+
+#endif /* WITH_IP4 */
diff --git a/xio-ip4.h b/xio-ip4.h
new file mode 100644
index 0000000..5af6e23
--- /dev/null
+++ b/xio-ip4.h
@@ -0,0 +1,13 @@
+/* $Id: xio-ip4.h,v 1.9 2007/03/06 21:19:18 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_ip4_h_included
+#define __xio_ip4_h_included 1
+
+extern const struct optdesc opt_ip4_add_membership;
+
+extern
+int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange_ip4 *range);
+
+#endif /* !defined(__xio_ip4_h_included) */
diff --git a/xio-ip6.c b/xio-ip6.c
new file mode 100644
index 0000000..78a233f
--- /dev/null
+++ b/xio-ip6.c
@@ -0,0 +1,145 @@
+/* $Id: xio-ip6.c,v 1.31 2007/03/06 21:19:18 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for IP6 related functions */
+
+#include "xiosysincludes.h"
+
+#if WITH_IP6
+
+#include "xioopen.h"
+#include "xio-socket.h"
+#include "xio-ip.h" /* xiogetaddrinfo() */
+
+#include "xio-ip6.h"
+
+#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
+
+int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *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 *nameaddr = (union xioin6_u *)&sockaddr.ip6.sin6_addr;
+
+ if (rangename[0] != '[' || rangename[strlen(rangename)-1] != ']') {
+ Error1("missing brackets for IPv6 range definition \"%s\"",
+ rangename);
+ return STAT_NORETRY;
+ }
+ if ((delimpos = strchr(rangename, '/')) == NULL) {
+ Error1("xioparsenetwork_ip6(\"%s\",,): missing mask bits delimiter '/'",
+ rangename);
+ return STAT_NORETRY;
+ }
+ delimind = delimpos - rangename;
+
+ if ((baseaddr = strdup(rangename+1)) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", rangename+1);
+ return STAT_NORETRY;
+ }
+ baseaddr[delimind-1] = '\0';
+ if (xiogetaddrinfo(baseaddr, NULL, PF_INET6, 0, 0, &sockaddr, &sockaddrlen,
+ 0, 0)
+ != STAT_OK) {
+ return STAT_NORETRY;
+ }
+ rangeaddr->u6_addr32[0] = nameaddr->u6_addr32[0];
+ rangeaddr->u6_addr32[1] = nameaddr->u6_addr32[1];
+ rangeaddr->u6_addr32[2] = nameaddr->u6_addr32[2];
+ rangeaddr->u6_addr32[3] = nameaddr->u6_addr32[3];
+ bits = strtoul(delimpos+1, NULL, 10);
+ if (bits > 128) {
+ Error1("invalid number of mask bits %u", bits);
+ return STAT_NORETRY;
+ }
+ if (bits < 32) {
+ rangemask->u6_addr32[0] = htonl(0xffffffff << (32-bits));
+ rangemask->u6_addr32[1] = 0;
+ rangemask->u6_addr32[2] = 0;
+ rangemask->u6_addr32[3] = 0;
+ } else if (bits < 64) {
+ rangemask->u6_addr32[0] = 0xffffffff;
+ rangemask->u6_addr32[1] = htonl(0xffffffff << (64-bits));
+ rangemask->u6_addr32[2] = 0;
+ rangemask->u6_addr32[3] = 0;
+ } else if (bits < 96) {
+ rangemask->u6_addr32[0] = 0xffffffff;
+ rangemask->u6_addr32[1] = 0xffffffff;
+ rangemask->u6_addr32[2] = htonl(0xffffffff << (96-bits));
+ rangemask->u6_addr32[3] = 0;
+ } else {
+ rangemask->u6_addr32[0] = 0xffffffff;
+ rangemask->u6_addr32[1] = 0xffffffff;
+ rangemask->u6_addr32[2] = 0xffffffff;
+ rangemask->u6_addr32[3] = htonl(0xffffffff << (128-bits));
+ }
+ return 0;
+}
+
+int xiorange_ip6andmask(struct xiorange_ip6 *range) {
+ int i;
+#if 0
+ range->addr.s6_addr32[0] &= range->mask.s6_addr32[0];
+ range->addr.s6_addr32[1] &= range->mask.s6_addr32[1];
+ range->addr.s6_addr32[2] &= range->mask.s6_addr32[2];
+ 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];
+ }
+#endif
+ return 0;
+}
+
+/* check if peer address is within permitted range.
+ return >= 0 if so. */
+int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange_ip6 *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;
+
+ 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]),
+ htons(rangeaddr->u6_addr16[2]), htons(rangeaddr->u6_addr16[3]),
+ htons(rangeaddr->u6_addr16[4]), htons(rangeaddr->u6_addr16[5]),
+ htons(rangeaddr->u6_addr16[6]), htons(rangeaddr->u6_addr16[7]),
+ htons(rangemask->u6_addr16[0]), htons(rangemask->u6_addr16[1]),
+ htons(rangemask->u6_addr16[2]), htons(rangemask->u6_addr16[3]),
+ htons(rangemask->u6_addr16[4]), htons(rangemask->u6_addr16[5]),
+ htons(rangemask->u6_addr16[6]), htons(rangemask->u6_addr16[7]));
+ Debug1("client address is %s",
+ sockaddr_inet6_info(pa, peername, sizeof(peername)));
+
+ for (i = 0; i < 4; ++i) {
+ masked.u6_addr32[i] = pa->sin6_addr.s6_addr[i] & rangemask->u6_addr16[i];
+ }
+ Debug8("masked address is [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
+ htons(masked.u6_addr16[0]), htons(masked.u6_addr16[1]),
+ htons(masked.u6_addr16[2]), htons(masked.u6_addr16[3]),
+ htons(masked.u6_addr16[4]), htons(masked.u6_addr16[5]),
+ htons(masked.u6_addr16[6]), htons(masked.u6_addr16[7]));
+
+ if (masked.u6_addr32[0] != rangeaddr->u6_addr32[0] ||
+ masked.u6_addr32[1] != rangeaddr->u6_addr32[1] ||
+ masked.u6_addr32[2] != rangeaddr->u6_addr32[2] ||
+ masked.u6_addr32[3] != rangeaddr->u6_addr32[3]) {
+ Debug1("client address %s is not permitted", peername);
+ return -1;
+ }
+ return 0;
+}
+
+#endif /* WITH_IP6 */
diff --git a/xio-ip6.h b/xio-ip6.h
new file mode 100644
index 0000000..2c5b809
--- /dev/null
+++ b/xio-ip6.h
@@ -0,0 +1,22 @@
+/* $Id: xio-ip6.h,v 1.13 2007/03/06 21:19:18 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_ip6_h_included
+#define __xio_ip6_h_included 1
+
+#if WITH_IP6
+
+extern const struct optdesc opt_ipv6_v6only;
+extern const struct optdesc opt_ipv6_join_group;
+
+extern
+int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *range);
+extern int xiorange_ip6andmask(struct xiorange_ip6 *range);
+
+extern
+int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange_ip6 *range);
+
+#endif /* WITH_IP6 */
+
+#endif /* !defined(__xio_ip6_h_included) */
diff --git a/xio-ipapp.c b/xio-ipapp.c
new file mode 100644
index 0000000..b1fd5c3
--- /dev/null
+++ b/xio-ipapp.c
@@ -0,0 +1,298 @@
+/* $Id: xio-ipapp.c,v 1.34 2007/02/08 18:27:00 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for TCP and UDP related options */
+
+#include "xiosysincludes.h"
+
+#if WITH_TCP || WITH_UDP
+
+#include "xioopen.h"
+#include "xio-socket.h"
+#include "xio-ip.h"
+#include "xio-listen.h"
+#include "xio-ip6.h"
+#include "xio-ipapp.h"
+
+const struct optdesc opt_sourceport = { "sourceport", "sp", OPT_SOURCEPORT, GROUP_IPAPP, PH_LATE,TYPE_2BYTE, OFUNC_SPEC };
+/*const struct optdesc opt_port = { "port", NULL, OPT_PORT, GROUP_IPAPP, PH_BIND, TYPE_USHORT, OFUNC_SPEC };*/
+const struct optdesc opt_lowport = { "lowport", NULL, OPT_LOWPORT, GROUP_IPAPP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
+
+#if WITH_IP4
+/* we expect the form "host:port" */
+int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xxfd,
+ unsigned groups, int socktype, int ipproto,
+ int pf) {
+ struct single *xfd = &xxfd->stream;
+ struct opt *opts0 = NULL;
+ const char *hostname = argv[1], *portname = argv[2];
+ bool dofork = false;
+ union sockaddr_union us_sa, *us = &us_sa;
+ union sockaddr_union them_sa, *them = &them_sa;
+ socklen_t uslen = sizeof(us_sa);
+ socklen_t themlen = sizeof(them_sa);
+ bool needbind = false;
+ bool lowport = false;
+ int level;
+ int result;
+
+ if (argc != 3) {
+ Error2("%s: wrong number of parameters (%d instead of 2)", argv[0], argc-1);
+ }
+
+ xfd->howtoend = END_SHUTDOWN;
+
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ retropt_bool(opts, OPT_FORK, &dofork);
+
+ 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) {
+ return STAT_NORETRY;
+ }
+
+ if (xioopts.logopt == 'm') {
+ Info("starting connect loop, switching to syslog");
+ diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';
+ } else {
+ Info("starting connect loop");
+ }
+
+ do { /* loop over retries and forks */
+
+#if WITH_RETRY
+ if (xfd->forever || xfd->retry) {
+ level = E_INFO;
+ } else
+#endif /* WITH_RETRY */
+ level = E_ERROR;
+
+ result =
+ _xioopen_connect(xfd,
+ needbind?(struct sockaddr *)us:NULL, uslen,
+ (struct sockaddr *)them, themlen,
+ opts, pf, socktype, ipproto, lowport, level);
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ case STAT_RETRYNOW:
+ if (xfd->forever || xfd->retry) {
+ --xfd->retry;
+ if (result == STAT_RETRYLATER) {
+ Nanosleep(&xfd->intervall, NULL);
+ }
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ continue;
+ }
+ return STAT_NORETRY;
+#endif /* WITH_RETRY */
+ default:
+ return result;
+ }
+
+#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,
+ 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);
+ 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);
+ }
+ break;
+ }
+ /* parent process */
+ Notice1("forked off child process "F_pid, pid);
+ Close(xfd->fd);
+ /* with and without retry */
+ Nanosleep(&xfd->intervall, NULL);
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ continue; /* with next socket() bind() connect() */
+ } else
+#endif /* WITH_RETRY */
+ {
+ break;
+ }
+ } while (true);
+
+ if ((result = _xio_openlate(xfd, opts)) < 0) {
+ return result;
+ }
+ return 0;
+}
+
+
+/* returns STAT_OK on success or some other value on failure */
+int
+ _xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0,
+ const char *hostname,
+ const char *portname,
+ int *pf,
+ int protocol,
+ unsigned long res_opts0, unsigned long res_opts1,
+ union sockaddr_union *them, socklen_t *themlen,
+ union sockaddr_union *us, socklen_t *uslen,
+ bool *needbind, bool *lowport,
+ int *socktype) {
+ uint16_t port;
+ char infobuff[256];
+ int result;
+
+ retropt_socket_pf(opts, pf);
+
+ if ((result =
+ xiogetaddrinfo(hostname, portname,
+ *pf, *socktype, protocol,
+ (union sockaddr_union *)them, themlen,
+ res_opts0, res_opts1
+ ))
+ != STAT_OK) {
+ return STAT_NORETRY; /*! STAT_RETRYLATER? */
+ }
+ if (*pf == PF_UNSPEC) {
+ *pf = them->soa.sa_family;
+ }
+
+ applyopts(-1, opts, PH_EARLY);
+
+ /* 3 means: IP address AND port accepted */
+ if (retropt_bind(opts, *pf, *socktype, protocol, (struct sockaddr *)us, uslen, 3,
+ res_opts0, res_opts1)
+ != STAT_NOACTION) {
+ *needbind = true;
+ } else {
+ switch (*pf) {
+#if WITH_IP4
+ case PF_INET: socket_in_init(&us->ip4); *uslen = sizeof(us->ip4); break;
+#endif /* WITH_IP4 */
+#if WITH_IP6
+ case PF_INET6: socket_in6_init(&us->ip6); *uslen = sizeof(us->ip6); break;
+#endif /* WITH_IP6 */
+ }
+ }
+
+ if (retropt_2bytes(opts, OPT_SOURCEPORT, &port) >= 0) {
+ switch (*pf) {
+#if WITH_IP4
+ case PF_INET: us->ip4.sin_port = htons(port); break;
+#endif /* WITH_IP4 */
+#if WITH_IP6
+ case PF_INET6: us->ip6.sin6_port = htons(port); break;
+#endif /* WITH_IP6 */
+ default: Error("unsupported protocol family");
+ }
+ *needbind = true;
+ }
+
+ retropt_bool(opts, OPT_LOWPORT, lowport);
+ retropt_int(opts, OPT_SO_TYPE, socktype);
+
+ *opts0 = copyopts(opts, GROUP_ALL);
+
+ Notice1("opening connection to %s",
+ sockaddr_info((struct sockaddr *)them, *themlen, infobuff, sizeof(infobuff)));
+ return STAT_OK;
+}
+#endif /* WITH_IP4 */
+
+
+#if WITH_TCP && WITH_LISTEN
+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) {
+ 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,
+ (union sockaddr_union *)us, uslen,
+ res_opts0, res_opts1))
+ != STAT_OK) {
+ /*! STAT_RETRY? */
+ return result;
+ }
+
+ *opts0 = copyopts(opts, GROUP_ALL);
+ return STAT_OK;
+}
+
+
+/* we expect the form: port */
+/* currently only used for TCP4 */
+int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *fd,
+ unsigned groups, int socktype,
+ int ipproto, int pf) {
+ struct opt *opts0 = NULL;
+ union sockaddr_union us_sa, *us = &us_sa;
+ socklen_t uslen = sizeof(us_sa);
+ int result;
+
+ if (argc != 2) {
+ Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
+ }
+
+ if (pf == PF_UNSPEC) {
+#if WITH_IP4 && WITH_IP6
+ pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
+#elif WITH_IP6
+ pf = PF_INET6;
+#else
+ pf = PF_INET;
+#endif
+ }
+
+ fd->stream.howtoend = END_SHUTDOWN;
+
+ if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+ applyopts(-1, opts, PH_EARLY);
+
+ 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)
+ != STAT_OK) {
+ return STAT_NORETRY;
+ }
+
+ if ((result =
+ xioopen_listen(&fd->stream, xioflags,
+ (struct sockaddr *)us, uslen,
+ opts, opts0, pf, socktype, ipproto))
+ != 0)
+ return result;
+ return 0;
+}
+#endif /* WITH_IP4 && WITH_TCP && WITH_LISTEN */
+
+#endif /* WITH_TCP || WITH_UDP */
diff --git a/xio-ipapp.h b/xio-ipapp.h
new file mode 100644
index 0000000..9d44407
--- /dev/null
+++ b/xio-ipapp.h
@@ -0,0 +1,48 @@
+/* $Id: xio-ipapp.h,v 1.13 2006/05/19 05:54:39 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_ipapp_h_included
+#define __xio_ipapp_h_included 1
+
+
+/* when selecting a low port, this is the lowest possible */
+#define XIO_IPPORT_LOWER 640
+
+
+extern const struct optdesc opt_sourceport;
+/*extern const struct optdesc opt_port;*/
+extern const struct optdesc opt_lowport;
+
+extern int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd,
+ unsigned groups, int socktype,
+ int ipproto, int protname);
+extern int
+ _xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0,
+ const char *hostname,
+ const char *portname, int *pf, int protocol,
+ unsigned long res_opts0, unsigned long res_opts1,
+ union sockaddr_union *them, socklen_t *themlen,
+ union sockaddr_union *us, socklen_t *uslen,
+ bool *needbind, bool *lowport,
+ int *socktype);
+extern int _xioopen_ip4app_connect(const char *hostname, const char *portname,
+ struct single *xfd,
+ int socktype, int ipproto, void *protname,
+ struct opt *opts);
+extern int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *fd,
+ unsigned groups, int socktype,
+ int ipproto, int protname);
+extern 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);
+extern int xioopen_ip6app_connect(int argc, const char *argv[], struct opt *opts,
+ int rw, xiofile_t *fd,
+ unsigned groups, int socktype, int ipproto,
+ void *protname);
+
+#endif /* !defined(__xio_ipapp_h_included) */
diff --git a/xio-listen.c b/xio-listen.c
new file mode 100644
index 0000000..518291b
--- /dev/null
+++ b/xio-listen.c
@@ -0,0 +1,333 @@
+/* $Id: xio-listen.c,v 1.44 2007/02/08 18:27:00 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for listen socket options */
+
+#include "xiosysincludes.h"
+
+#if WITH_LISTEN
+
+#include "xioopen.h"
+#include "xio-named.h"
+#include "xio-socket.h"
+#include "xio-ip.h"
+#include "xio-ip4.h"
+#include "xio-listen.h"
+#include "xio-tcpwrap.h"
+
+/***** LISTEN options *****/
+const struct optdesc opt_backlog = { "backlog", NULL, OPT_BACKLOG, GROUP_LISTEN, PH_LISTEN, TYPE_INT, OFUNC_SPEC };
+const struct optdesc opt_fork = { "fork", NULL, OPT_FORK, GROUP_CHILD, PH_PASTACCEPT, TYPE_BOOL, OFUNC_SPEC };
+/**/
+#if (WITH_UDP || WITH_TCP)
+const struct optdesc opt_range = { "range", NULL, OPT_RANGE, GROUP_RANGE, PH_ACCEPT, TYPE_STRING, OFUNC_SPEC };
+#endif
+
+
+int
+ xioopen_listen(struct single *xfd, int xioflags,
+ struct sockaddr *us, socklen_t uslen,
+ struct opt *opts, struct opt *opts0,
+ int pf, int socktype, int proto) {
+ int level;
+ int result;
+
+#if WITH_RETRY
+ if (xfd->forever || xfd->retry) {
+ level = E_INFO;
+ } else
+#endif /* WITH_RETRY */
+ level = E_ERROR;
+
+ while (true) { /* loop over failed attempts */
+
+ /* tcp listen; this can fork() for us; it only returns on error or on
+ successful establishment of tcp connection */
+ result = _xioopen_listen(xfd, xioflags,
+ (struct sockaddr *)us, uslen,
+ opts, pf, socktype, proto,
+#if WITH_RETRY
+ (xfd->retry||xfd->forever)?E_INFO:E_ERROR
+#else
+ E_ERROR
+#endif /* WITH_RETRY */
+ );
+ /*! not sure if we should try again on retry/forever */
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ case STAT_RETRYNOW:
+ if (xfd->forever || xfd->retry) {
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ if (result == STAT_RETRYLATER) {
+ Nanosleep(&xfd->intervall, NULL);
+ }
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ --xfd->retry;
+ continue;
+ }
+ return STAT_NORETRY;
+#endif /* WITH_RETRY */
+ default:
+ return result;
+ }
+
+ break;
+ } /* drop out on success */
+
+ return result;
+}
+
+
+/* waits for incoming connection, checks its source address and port. Depending
+ on fork option, it may fork a subprocess.
+ 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
+ */
+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) {
+ struct sockaddr sa;
+ socklen_t salen;
+ 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];
+ int result;
+
+ retropt_bool(opts, OPT_FORK, &dofork);
+
+ if (dofork) {
+ if (!(xioflags & XIO_MAYFORK)) {
+ Error("option fork not allowed here");
+ return STAT_NORETRY;
+ }
+ xfd->flags |= XIO_DOESFORK;
+ }
+
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
+
+#if 1
+ if (dofork) {
+#if HAVE_SIGACTION
+ struct sigaction act;
+ memset(&act, 0, sizeof(struct sigaction));
+ act.sa_flags = SA_NOCLDSTOP|SA_RESTART
+#ifdef SA_NOMASK
+ |SA_NOMASK
+#endif
+ ;
+ act.sa_handler = childdied;
+ if (Sigaction(SIGCHLD, &act, NULL) < 0) {
+ /*! man does not say that errno is defined */
+ Warn2("sigaction(SIGCHLD, %p, NULL): %s", childdied, strerror(errno));
+ }
+#else /* HAVE_SIGACTION */
+ if (Signal(SIGCHLD, childdied) == SIG_ERR) {
+ Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
+ }
+#endif /* !HAVE_SIGACTION */
+ }
+#endif /* 1 */
+
+ if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
+ Msg4(level,
+ "socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+
+ applyopts(xfd->fd, opts, PH_PASTSOCKET);
+
+ applyopts_cloexec(xfd->fd, opts);
+
+ applyopts(xfd->fd, opts, PH_PREBIND);
+ applyopts(xfd->fd, opts, PH_BIND);
+ if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
+ Msg4(level, "bind(%d, {%s}, "F_Zd"): %s", xfd->fd,
+ sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
+ strerror(errno));
+ Close(xfd->fd);
+ return STAT_RETRYLATER;
+ }
+
+#if WITH_UNIX
+ if (us->sa_family == AF_UNIX) {
+ applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
+ }
+#endif
+ /* under some circumstances (e.g., TCP listen on port 0) bind() fills empty
+ fields that we want to know. */
+ salen = sizeof(sa);
+ if (Getsockname(xfd->fd, us, &uslen) < 0) {
+ Warn4("getsockname(%d, %p, {%d}): %s",
+ xfd->fd, &us, uslen, strerror(errno));
+ }
+
+ applyopts(xfd->fd, opts, PH_PASTBIND);
+#if WITH_UNIX
+ if (us->sa_family == AF_UNIX) {
+ /*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
+ applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY);
+ applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN);
+ }
+#endif /* WITH_UNIX */
+
+ retropt_int(opts, OPT_BACKLOG, &backlog);
+ if (Listen(xfd->fd, backlog) < 0) {
+ Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+
+#if WITH_IP4 /*|| WITH_IP6*/
+ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
+ if (parserange(rangename, us->sa_family, &xfd->para.socket.range) < 0) {
+ free(rangename);
+ return STAT_NORETRY;
+ }
+ free(rangename);
+ xfd->para.socket.dorange = true;
+ }
+#endif
+
+#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
+ xio_retropt_tcpwrap(xfd, opts);
+#endif /* && (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */
+
+#if WITH_TCP || WITH_UDP
+ if (retropt_ushort(opts, OPT_SOURCEPORT, &xfd->para.socket.ip.sourceport) >= 0) {
+ xfd->para.socket.ip.dosourceport = true;
+ }
+ retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport);
+#endif /* WITH_TCP || WITH_UDP */
+
+ if (xioopts.logopt == 'm') {
+ Info("starting accept loop, switching to syslog");
+ diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';
+ } else {
+ Info("starting accept loop");
+ }
+ while (true) { /* but we only loop if fork option is set */
+ 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 {
+ /*? int level = E_ERROR;*/
+ Notice1("listening on %s", sockaddr_info(us, uslen, lisname, sizeof(lisname)));
+ ps = Accept(xfd->fd, (struct sockaddr *)&sa, &salen);
+ if (ps >= 0) {
+ /*0 Info4("accept(%d, %p, {"F_Zu"}) -> %d", xfd->fd, &sa, salen, ps);*/
+ break; /* success, break out of loop */
+ }
+ if (errno == EINTR) {
+ continue;
+ }
+ if (errno == ECONNABORTED) {
+ Notice4("accept(%d, %p, {"F_Zu"}): %s",
+ xfd->fd, &sa, salen, strerror(errno));
+ continue;
+ }
+ Msg4(level, "accept(%d, %p, {"F_Zu"}): %s",
+ xfd->fd, &sa, salen, strerror(errno));
+ Close(xfd->fd);
+ return STAT_RETRYLATER;
+ } while (true);
+ applyopts_cloexec(ps, opts);
+ if (Getpeername(ps, &pa->soa, &pas) < 0) {
+ Warn4("getpeername(%d, %p, {"F_socklen"}): %s",
+ ps, pa, pas, strerror(errno));
+ }
+ if (Getsockname(ps, &la->soa, &las) < 0) {
+ Warn4("getsockname(%d, %p, {"F_socklen"}): %s",
+ ps, pa, pas, strerror(errno));
+ }
+ Notice2("accepting connection from %s on %s",
+ sockaddr_info(&pa->soa, pas, peername, sizeof(peername)),
+ sockaddr_info(&la->soa, las, sockname, sizeof(sockname)));
+
+ if (xiocheckpeer(xfd, pa, la) < 0) {
+ if (Shutdown(ps, 2) < 0) {
+ Info2("shutdown(%d, 2): %s", ps, strerror(errno));
+ }
+ continue;
+ }
+
+ Info1("permitting connection from %s",
+ sockaddr_info((struct sockaddr *)pa, pas,
+ infobuff, sizeof(infobuff)));
+
+ applyopts(xfd->fd, opts, PH_FD);
+
+ applyopts(xfd->fd, opts, PH_CONNECTED);
+
+ if (dofork) {
+ if ((pid = Fork()) < 0) {
+ Msg1(level, "fork(): %s", strerror(errno));
+ Close(xfd->fd);
+ return STAT_RETRYLATER;
+ }
+ if (pid == 0) { /* child */
+ if (Close(xfd->fd) < 0) {
+ Info2("close(%d): %s", xfd->fd, strerror(errno));
+ }
+ xfd->fd = ps;
+
+#if WITH_RETRY
+ /* !? */
+ xfd->retry = 0;
+ xfd->forever = 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 */
+ xfd->opt_unlink_close = false;
+#endif /* WITH_UNIX */
+
+ break;
+ }
+
+ /* server: continue loop with listen */
+ /* shutdown() closes the socket even for the child process, but
+ close() does what we want */
+ 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->fd) < 0) {
+ Info2("close(%d): %s", xfd->fd, strerror(errno));
+ }
+ xfd->fd = ps;
+ break;
+ }
+ }
+ if ((result = _xio_openlate(xfd, opts)) < 0)
+ return result;
+
+ return 0;
+}
+
+#endif /* WITH_LISTEN */
diff --git a/xio-listen.h b/xio-listen.h
new file mode 100644
index 0000000..7c2adf2
--- /dev/null
+++ b/xio-listen.h
@@ -0,0 +1,21 @@
+/* $Id: xio-listen.h,v 1.10 2006/07/13 06:44:53 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_listen_h_included
+#define __xio_listen_h_included 1
+
+extern const struct optdesc opt_backlog;
+extern const struct optdesc opt_fork;
+extern const struct optdesc opt_range;
+
+int
+ xioopen_listen(struct single *xfd, int xioflags,
+ struct sockaddr *us, socklen_t uslen,
+ struct opt *opts, struct opt *opts0,
+ int pf, int socktype, int proto);
+int _xioopen_listen(struct single *fd, int xioflags,
+ struct sockaddr *us, socklen_t uslen,
+ struct opt *opts, int pf, int socktype, int proto, int level);
+
+#endif /* !defined(__xio_listen_h_included) */
diff --git a/xio-named.c b/xio-named.c
new file mode 100644
index 0000000..ead5333
--- /dev/null
+++ b/xio-named.c
@@ -0,0 +1,216 @@
+/* $Id: xio-named.c,v 1.28 2007/03/06 21:09:01 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for filesystem entry functions */
+
+#include "xiosysincludes.h"
+
+#if _WITH_NAMED
+
+#include "xioopen.h"
+#include "xio-named.h"
+
+
+#if WITH_NAMED
+const struct optdesc opt_group_early = { "group-early", NULL, OPT_GROUP_EARLY, GROUP_NAMED, PH_PREOPEN, TYPE_GIDT, OFUNC_SPEC };
+const struct optdesc opt_perm_early = { "perm-early", NULL, OPT_PERM_EARLY, GROUP_NAMED, PH_PREOPEN, TYPE_MODET,OFUNC_SPEC };
+const struct optdesc opt_user_early = { "user-early", NULL, OPT_USER_EARLY, GROUP_NAMED, PH_PREOPEN, TYPE_UIDT, OFUNC_SPEC };
+/*0 const struct optdesc opt_force = { "force", NULL, OPT_FORCE, GROUP_NAMED, PH_???, TYPE_BOOL, OFUNC_SPEC };*/
+const struct optdesc opt_unlink = { "unlink", NULL, OPT_UNLINK, GROUP_NAMED, PH_PREOPEN, TYPE_BOOL, OFUNC_SPEC };
+const struct optdesc opt_unlink_early= { "unlink-early",NULL, OPT_UNLINK_EARLY,GROUP_NAMED, PH_EARLY, TYPE_BOOL, OFUNC_SPEC };
+const struct optdesc opt_unlink_late = { "unlink-late", NULL, OPT_UNLINK_LATE, GROUP_NAMED, PH_PASTOPEN, TYPE_BOOL, OFUNC_SPEC };
+const struct optdesc opt_unlink_close = { "unlink-close", NULL, OPT_UNLINK_CLOSE, GROUP_NAMED, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
+const struct optdesc opt_umask = { "umask", NULL, OPT_UMASK, GROUP_NAMED, PH_EARLY, TYPE_MODET, OFUNC_SPEC };
+#endif /* _WITH_NAMED */
+
+/* applies to fd all options belonging to phase */
+int applyopts_named(const char *filename, struct opt *opts, unsigned int phase) {
+ struct opt *opt;
+
+ if (!opts) return 0;
+
+ opt = opts; while (opt->desc != ODESC_END) {
+ if (opt->desc == ODESC_DONE ||
+ opt->desc->phase != phase && phase != PH_ALL ||
+ !(opt->desc->group & GROUP_NAMED)) {
+ ++opt; continue; }
+ switch (opt->desc->optcode) {
+ case OPT_GROUP_EARLY:
+ case OPT_GROUP:
+ if (Chown(filename, -1, opt->value.u_gidt) < 0) {
+ Error3("chown(\"%s\", -1, "F_gid"): %s", filename,
+ opt->value.u_gidt, strerror(errno));
+ }
+ break;
+ case OPT_USER_EARLY:
+ case OPT_USER:
+ if (Chown(filename, opt->value.u_uidt, -1) < 0) {
+ Error3("chown(\"%s\", "F_uid", -1): %s", filename,
+ opt->value.u_uidt, strerror(errno));
+ }
+ break;
+ case OPT_PERM_EARLY:
+ case OPT_PERM:
+ if (Chmod(filename, opt->value.u_modet) < 0) {
+ Error3("chmod(\"%s\", "F_mode"): %s",
+ filename, opt->value.u_modet, strerror(errno));
+ }
+ break;
+ case OPT_UNLINK_EARLY:
+ case OPT_UNLINK:
+ case OPT_UNLINK_LATE:
+ if (Unlink(filename) < 0) {
+ if (errno == ENOENT) {
+ Warn2("unlink(\"%s\"): %s", filename, strerror(errno));
+ } else {
+ Error2("unlink(\"%s\"): %s", filename, strerror(errno));
+ }
+ }
+ break;
+ case OPT_UMASK:
+ if (Umask(opt->value.u_modet) < 0) {
+ /* linux docu says it always succeeds, but who believes it? */
+ Error2("umask("F_mode"): %s", opt->value.u_modet, strerror(errno));
+ }
+ break;
+ default: Error1("applyopts_named(): option \"%s\" not implemented",
+ opt->desc->defname);
+ break;
+ }
+ opt->desc = ODESC_DONE;
+ ++opt;
+ }
+ return 0;
+}
+
+
+/* perform actions that are common to all NAMED group addresses: checking if
+ the entry exists, parsing options, ev.removing old filesystem entry or
+ setting early owners and permissions.
+ It applies options of PH_EARLY and PH_PREOPEN.
+ If the path exists, its st_mode field is returned.
+ After this sub you may proceed with open() or whatever...
+ */
+int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd,
+ int groups,
+ bool *exists, struct opt *opts) {
+ const char *path = argv[1];
+ unsigned int iogroups = 0;
+#if HAVE_STAT64
+ struct stat64 statbuf;
+#else
+ struct stat statbuf;
+#endif /* !HAVE_STAT64 */
+ bool opt_unlink_early = false;
+
+ if (argc != 2) {
+ Error2("%s: wrong number of parameters (%d instead of 1)", argv[0]?argv[0]:"<named>", argc);
+ }
+ statbuf.st_mode = 0;
+ /* find the appropriate groupbits */
+ if (
+#if HAVE_STAT64
+ Stat64(path, &statbuf) < 0
+#else
+ Stat(path, &statbuf) < 0
+#endif /* !HAVE_STAT64 */
+ ) {
+ if (errno != ENOENT) {
+ Error2("stat(\"%s\"): %s", path, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ iogroups = GROUP_REG;
+ *exists = false;
+ } else {
+ iogroups = _groupbits(statbuf.st_mode);
+ *exists = true;
+ }
+
+ if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
+ if (*exists && opt_unlink_early) {
+ Info1("\"%s\" already exists; removing it", path);
+ if (Unlink(path) < 0) {
+ Error2("unlink(\"%s\"): %s", path, strerror(errno));
+ *exists = true;
+ } else {
+ *exists = false;
+ }
+ }
+
+ applyopts(-1, opts, PH_EARLY);
+ applyopts_named(path, opts, PH_EARLY);
+ if (*exists) {
+ applyopts_named(path, opts, PH_PREOPEN);
+ } else {
+ dropopts(opts, PH_PREOPEN);
+ }
+
+ return statbuf.st_mode;
+}
+
+
+/* retrieve the OPEN group options and perform the open() call.
+ returns the file descriptor or a negative value.
+ Applies options of phases PREOPEN, OPEN, PASTOPEN, and FD
+*/
+int _xioopen_open(const char *path, int rw, struct opt *opts) {
+ mode_t mode = 0666;
+ flags_t flags = rw;
+ bool flag;
+ int fd;
+
+ applyopts_named(path, opts, PH_PREOPEN);
+
+ /* this only applies pure OPEN flags, not mixed OPEN/FCNTL options */
+ applyopts_flags(opts, GROUP_OPEN, &flags);
+
+ /* we have to handle mixed OPEN/FCNTL flags specially */
+ if (retropt_bool(opts, OPT_O_APPEND, &flag) >= 0 && flag)
+ flags |= O_APPEND;
+ if (retropt_bool(opts, OPT_O_NONBLOCK, &flag) >= 0 && flag)
+ flags |= O_NONBLOCK;
+#ifdef O_ASYNC
+ if (retropt_bool(opts, OPT_O_ASYNC, &flag) >= 0 && flag)
+ flags |= O_ASYNC;
+#endif
+ if (retropt_bool(opts, OPT_O_TRUNC, &flag) >= 0 && flag)
+ flags |= O_TRUNC;
+#ifdef O_BINARY
+ if (retropt_bool(opts, OPT_O_BINARY, &flag) >= 0 && flag)
+ flags |= O_BINARY;
+#endif
+#ifdef O_TEXT
+ if (retropt_bool(opts, OPT_O_TEXT, &flag) >= 0 && flag)
+ flags |= O_TEXT;
+#endif
+#ifdef O_NOINHERIT
+ if (retropt_bool(opts, OPT_O_NOINHERIT, &flag) >= 0 && flag)
+ flags |= O_NOINHERIT;
+#endif
+#ifdef O_NOATIME
+ if (retropt_bool(opts, OPT_O_NOATIME, &flag) >= 0 && flag)
+ flags |= O_NOATIME;
+#endif
+
+ retropt_modet(opts, OPT_PERM, &mode);
+
+ if ((fd = Open(path, flags, mode)) < 0) {
+ Error4("open(\"%s\", 0%lo, 0%03o): %s",
+ path, flags, mode, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ /*0 Info4("open(\"%s\", 0%o, 0%03o) -> %d", path, flags, mode, fd);*/
+ applyopts_named(path, opts, PH_PASTOPEN);
+#if 0
+ applyopts_named(path, opts, PH_FD);
+ applyopts(fd, opts, PH_FD);
+ applyopts_cloexec(fd, opts);
+#endif
+ return fd;
+}
+
+#endif /* WITH_NAMED */
diff --git a/xio-named.h b/xio-named.h
new file mode 100644
index 0000000..e3db995
--- /dev/null
+++ b/xio-named.h
@@ -0,0 +1,26 @@
+/* $Id: xio-named.h,v 1.8 2006/03/18 20:04:31 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_named_h_included
+#define __xio_named_h_included 1
+
+extern const struct optdesc opt_group_early;
+extern const struct optdesc opt_perm_early;
+extern const struct optdesc opt_user_early;
+/*0 extern const struct optdesc opt_cleanup; */
+/*0 extern const struct optdesc opt_force; */
+extern const struct optdesc opt_unlink;
+extern const struct optdesc opt_unlink_early;
+extern const struct optdesc opt_unlink_late;
+extern const struct optdesc opt_unlink_close;
+extern const struct optdesc opt_umask;
+
+extern int
+ applyopts_named(const char *filename, struct opt *opts, unsigned int phase);
+extern int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd,
+ int groups,
+ bool *exists, struct opt *opts);
+extern int _xioopen_open(const char *path, int rw, struct opt *opts);
+
+#endif /* !defined(__xio_named_h_included) */
diff --git a/xio-openssl.c b/xio-openssl.c
new file mode 100644
index 0000000..4f8e98e
--- /dev/null
+++ b/xio-openssl.c
@@ -0,0 +1,1155 @@
+/* $Id: xio-openssl.c,v 1.33 2007/02/26 21:31:40 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2002-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the implementation of the openssl addresses */
+
+#include "xiosysincludes.h"
+#if WITH_OPENSSL /* 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"
+
+/* the openssl library requires a file descriptor for external communications.
+ so our best effort is to provide any possible kind of un*x file descriptor
+ (not only tcp, but also pipes, stdin, files...)
+ for tcp we want to provide support for socks and proxy.
+ read and write functions must use the openssl crypt versions.
+ but currently only plain tcp4 is implemented.
+*/
+
+/* Linux: "man 3 ssl" */
+
+/* generate a simple openssl server for testing:
+ 1) generate a private key
+ openssl genrsa -out server.key 1024
+ 2) generate a self signed cert
+ openssl req -new -key server.key -x509 -days 3653 -out server.crt
+ enter fields...
+ 3) generate the pem file
+ cat server.key server.crt >server.pem
+ openssl s_server (listens on 4433/tcp)
+ */
+
+/* static declaration of ssl's open function */
+static int xioopen_openssl_connect(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *fd, unsigned groups,
+ int dummy1, int dummy2, int dummy3);
+
+/* static declaration of ssl's open function */
+static int xioopen_openssl_listen(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *fd, unsigned groups,
+ int dummy1, int dummy2, int dummy3);
+static int openssl_SSL_ERROR_SSL(int level, const char *funcname);
+static int openssl_handle_peer_certificate(struct single *xfd, bool opt_ver,
+ int level);
+static int xioSSL_set_fd(struct single *xfd, int level);
+static int xioSSL_connect(struct single *xfd, bool opt_ver, int level);
+
+
+/* description record for ssl connect */
+const struct addrdesc addr_openssl = {
+ "openssl", /* keyword for selecting this address type in xioopen calls
+ (canonical or main name) */
+ 3, /* data flow directions this address supports on API layer:
+ 1..read, 2..write, 3..both */
+ xioopen_openssl_connect, /* a function pointer used to "open" these addresses.*/
+ GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_OPENSSL|GROUP_RETRY, /* bitwise OR of address groups this address belongs to.
+ You might have to specify a new group in xioopts.h */
+ 0, /* an integer passed to xioopen_openssl; makes it possible to
+ use the same xioopen_openssl function for slightly different
+ address types. */
+ 0, /* like previous argument */
+ 0 /* like previous arguments, but pointer type.
+ No trailing comma or semicolon! */
+ HELP(":<host>:<port>") /* a text displayed from xio help function.
+ No trailing comma or semicolon!
+ only generates this text if WITH_HELP is != 0 */
+} ;
+
+#if WITH_LISTEN
+/* description record for ssl listen */
+const struct addrdesc addr_openssl_listen = {
+ "openssl-listen", /* keyword for selecting this address type in xioopen calls
+ (canonical or main name) */
+ 3, /* data flow directions this address supports on API layer:
+ 1..read, 2..write, 3..both */
+ xioopen_openssl_listen, /* a function pointer used to "open" these addresses.*/
+ GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_OPENSSL|GROUP_RETRY, /* bitwise OR of address groups this address belongs to.
+ You might have to specify a new group in xioopts.h */
+ 0, /* an integer passed to xioopen_openssl_listen; makes it possible to
+ use the same xioopen_openssl_listen function for slightly different
+ address types. */
+ 0, /* like previous argument */
+ 0 /* like previous arguments, but pointer type.
+ No trailing comma or semicolon! */
+ HELP(":<port>") /* a text displayed from xio help function.
+ No trailing comma or semicolon!
+ only generates this text if WITH_HELP is != 0 */
+} ;
+#endif /* WITH_LISTEN */
+
+/* both client and server */
+const struct optdesc opt_openssl_cipherlist = { "openssl-cipherlist", "ciphers", OPT_OPENSSL_CIPHERLIST, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
+const struct optdesc opt_openssl_method = { "openssl-method", "method", OPT_OPENSSL_METHOD, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
+const struct optdesc opt_openssl_verify = { "openssl-verify", "verify", OPT_OPENSSL_VERIFY, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
+const struct optdesc opt_openssl_certificate = { "openssl-certificate", "cert", OPT_OPENSSL_CERTIFICATE, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
+const struct optdesc opt_openssl_key = { "openssl-key", "key", OPT_OPENSSL_KEY, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
+const struct optdesc opt_openssl_dhparam = { "openssl-dhparam", "dh", OPT_OPENSSL_DHPARAM, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
+const struct optdesc opt_openssl_cafile = { "openssl-cafile", "cafile", OPT_OPENSSL_CAFILE, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
+const struct optdesc opt_openssl_capath = { "openssl-capath", "capath", OPT_OPENSSL_CAPATH, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
+const struct optdesc opt_openssl_egd = { "openssl-egd", "egd", OPT_OPENSSL_EGD, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
+const struct optdesc opt_openssl_pseudo = { "openssl-pseudo", "pseudo", OPT_OPENSSL_PSEUDO, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
+#if WITH_FIPS
+const struct optdesc opt_openssl_fips = { "openssl-fips", "fips", OPT_OPENSSL_FIPS, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
+#endif
+
+
+/* If FIPS is compiled in, we need to track if the user asked for FIPS mode.
+ * On forks, the FIPS mode must be reset by a disable, then enable since
+ * FIPS tracks the process ID that initializes things.
+ * If FIPS is not compiled in, no tracking variable is needed
+ * and we make the reset code compile out. This keeps the
+ * rest of the code below free of FIPS related #ifs
+ */
+#if WITH_FIPS
+static bool xio_openssl_fips = false;
+int xio_reset_fips_mode(void) {
+ if (xio_openssl_fips) {
+ if(!sycFIPS_mode_set(0) || !sycFIPS_mode_set(1)) {
+ ERR_load_crypto_strings();
+ ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE));
+ Error("Failed to reset OpenSSL FIPS mode");
+ xio_openssl_fips = false;
+ return -1;
+ }
+ }
+ return 0;
+}
+#else
+#define xio_reset_fips_mode() 0
+#endif
+
+/* the open function for OpenSSL client */
+static int
+ xioopen_openssl_connect(int argc,
+ const char *argv[], /* the arguments in the address string */
+ struct opt *opts,
+ int xioflags, /* is the open meant for reading (0),
+ writing (1), or both (2) ? */
+ xiofile_t *xxfd, /* a xio file descriptor structure,
+ already allocated */
+ unsigned groups, /* the matching address groups... */
+ int dummy1, /* first transparent integer value from
+ addr_openssl */
+ int dummy2, /* second transparent integer value from
+ addr_openssl */
+ int dummy3) /* transparent pointer value from
+ addr_openssl */
+{
+ struct single *xfd = &xxfd->stream;
+ struct opt *opts0 = NULL;
+ const char *hostname, *portname;
+ int pf = PF_UNSPEC;
+ int ipproto = IPPROTO_TCP;
+ int socktype = SOCK_STREAM;
+ bool dofork = false;
+ union sockaddr_union us_sa, *us = &us_sa;
+ union sockaddr_union them_sa, *them = &them_sa;
+ socklen_t uslen = sizeof(us_sa);
+ socklen_t themlen = sizeof(them_sa);
+ bool needbind = false;
+ bool lowport = false;
+ int level;
+ SSL_CTX* ctx;
+ bool opt_ver = true; /* verify peer certificate */
+ char *opt_cert = NULL; /* file name of client certificate */
+ int result;
+
+ if (!(xioflags & XIO_MAYCONVERT)) {
+ Error("address with data processing not allowed here");
+ return STAT_NORETRY;
+ }
+ xfd->flags |= XIO_DOESCONVERT;
+
+ if (argc != 3) {
+ Error1("%s: 2 parameters required", argv[0]);
+ return STAT_NORETRY;
+ }
+ hostname = argv[1];
+ portname = argv[2];
+
+ xfd->howtoend = END_SHUTDOWN;
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ retropt_bool(opts, OPT_FORK, &dofork);
+
+ retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
+
+ result =
+ _xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert, &ctx);
+ if (result != STAT_OK) return STAT_NORETRY;
+
+ result =
+ _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);
+ if (result != STAT_OK) return STAT_NORETRY;
+
+ if (xioopts.logopt == 'm') {
+ Info("starting connect loop, switching to syslog");
+ diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';
+ } else {
+ Info("starting connect loop");
+ }
+
+ do { /* loop over failed connect and SSL handshake attempts */
+
+#if WITH_RETRY
+ if (xfd->forever || xfd->retry) {
+ level = E_INFO;
+ } else
+#endif /* WITH_RETRY */
+ level = E_ERROR;
+
+ /* this cannot fork because we retrieved fork option above */
+ result =
+ _xioopen_connect(xfd,
+ needbind?(struct sockaddr *)us:NULL, sizeof(*us),
+ (struct sockaddr *)them, themlen,
+ opts, pf, socktype, ipproto, lowport, level);
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ case STAT_RETRYNOW:
+ if (xfd->forever || xfd->retry) {
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ if (result == STAT_RETRYLATER) {
+ Nanosleep(&xfd->intervall, NULL);
+ }
+ --xfd->retry;
+ continue;
+ }
+ return STAT_NORETRY;
+#endif /* WITH_RETRY */
+ default:
+ return result;
+ }
+
+ /*! isn't this too early? */
+ if ((result = _xio_openlate(xfd, opts)) < 0) {
+ return result;
+ }
+
+ result = _xioopen_openssl_connect(xfd, opt_ver, ctx, level);
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ case STAT_RETRYNOW:
+ if (xfd->forever || xfd->retry) {
+ Close(xfd->fd);
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ if (result == STAT_RETRYLATER) {
+ Nanosleep(&xfd->intervall, NULL);
+ }
+ --xfd->retry;
+ continue;
+ }
+#endif /* WITH_RETRY */
+ default: return STAT_NORETRY;
+ }
+
+#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;
+ }
+ 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;
+ break;
+ }
+ /* parent process */
+ Notice1("forked off child process "F_pid, pid);
+ Close(xfd->fd);
+ sycSSL_free(xfd->para.openssl.ssl);
+ xfd->para.openssl.ssl = NULL;
+ /* with and without retry */
+ Nanosleep(&xfd->intervall, NULL);
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ continue; /* with next socket() bind() connect() */
+ }
+#endif /* WITH_RETRY */
+ break;
+ } while (true); /* drop out on success */
+
+ Notice1("SSL connection using %s", SSL_get_cipher(xfd->para.openssl.ssl));
+
+ /* fill in the fd structure */
+ return STAT_OK;
+}
+
+
+/* this function is typically called within the OpenSSL client fork/retry loop.
+ xfd must be of type DATA_OPENSSL, and its fd must be set with a valid file
+ descriptor. this function then performs all SSL related step to make a valid
+ SSL connection from an FD and a CTX. */
+int _xioopen_openssl_connect(struct single *xfd,
+ bool opt_ver,
+ SSL_CTX *ctx,
+ int level) {
+ SSL *ssl;
+ unsigned long err;
+ int result;
+
+ /* create a SSL object */
+ if ((ssl = sycSSL_new(ctx)) == NULL) {
+ if (ERR_peek_error() == 0) Msg(level, "SSL_new() failed");
+ while (err = ERR_get_error()) {
+ Msg1(level, "SSL_new(): %s", ERR_error_string(err, NULL));
+ }
+ /*Error("SSL_new()");*/
+ return STAT_RETRYLATER;
+ }
+ xfd->para.openssl.ssl = ssl;
+
+ result = xioSSL_set_fd(xfd, level);
+ if (result != STAT_OK) {
+ sycSSL_free(xfd->para.openssl.ssl);
+ xfd->para.openssl.ssl = NULL;
+ return result;
+ }
+
+ result = xioSSL_connect(xfd, opt_ver, level);
+ if (result != STAT_OK) {
+ sycSSL_free(xfd->para.openssl.ssl);
+ xfd->para.openssl.ssl = NULL;
+ return result;
+ }
+
+ result = openssl_handle_peer_certificate(xfd, opt_ver, level);
+ if (result != STAT_OK) {
+ sycSSL_free(xfd->para.openssl.ssl);
+ xfd->para.openssl.ssl = NULL;
+ return result;
+ }
+
+ return STAT_OK;
+}
+
+
+#if WITH_LISTEN
+
+static int
+ xioopen_openssl_listen(int argc,
+ const char *argv[], /* the arguments in the address string */
+ struct opt *opts,
+ int xioflags, /* is the open meant for reading (0),
+ writing (1), or both (2) ? */
+ xiofile_t *xxfd, /* a xio file descriptor structure,
+ already allocated */
+ unsigned groups, /* the matching address groups... */
+ int dummy1, /* first transparent integer value from
+ addr_openssl */
+ int dummy2, /* second transparent integer value from
+ addr_openssl */
+ int dummy3) /* transparent pointer value from
+ addr_openssl */
+{
+ struct single *xfd = &xxfd->stream;
+ const char *portname;
+ struct opt *opts0 = NULL;
+ union sockaddr_union us_sa, *us = &us_sa;
+ socklen_t uslen = sizeof(us_sa);
+ int pf;
+ int socktype = SOCK_STREAM;
+ int ipproto = IPPROTO_TCP;
+ /*! lowport? */
+ int level;
+ SSL_CTX* ctx;
+ bool opt_ver = true; /* verify peer certificate - changed with 1.6.0 */
+ char *opt_cert = NULL; /* file name of server certificate */
+ int result;
+
+ if (!(xioflags & XIO_MAYCONVERT)) {
+ Error("address with data processing not allowed here");
+ return STAT_NORETRY;
+ }
+ xfd->flags |= XIO_DOESCONVERT;
+
+ if (argc != 2) {
+ Error1("%s: 1 parameter required", argv[0]);
+ return STAT_NORETRY;
+ }
+
+#if WITH_IP4 && WITH_IP6
+ pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
+#elif WITH_IP6
+ pf = PF_INET6;
+#else
+ pf = PF_INET;
+#endif
+
+ portname = argv[1];
+
+ xfd->howtoend = END_SHUTDOWN;
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
+ if (opt_cert == NULL) {
+ Warn("no certificate given; consider option \"cert\"");
+ }
+
+ applyopts(-1, opts, PH_EARLY);
+
+ result =
+ _xioopen_openssl_prepare(opts, xfd, true, &opt_ver, opt_cert, &ctx);
+ if (result != STAT_OK) return STAT_NORETRY;
+
+ if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto,
+ xfd->para.socket.ip.res_opts[1],
+ xfd->para.socket.ip.res_opts[0],
+ us, &uslen, &socktype)
+ != STAT_OK) {
+ return STAT_NORETRY;
+ }
+
+ xfd->addr = &addr_openssl_listen;
+ xfd->dtype = XIODATA_OPENSSL;
+
+ while (true) { /* loop over failed attempts */
+
+#if WITH_RETRY
+ if (xfd->forever || xfd->retry) {
+ level = E_INFO;
+ } else
+#endif /* WITH_RETRY */
+ level = E_ERROR;
+
+ /* tcp listen; this can fork() for us; it only returns on error or on
+ successful establishment of tcp connection */
+ result = _xioopen_listen(xfd, xioflags,
+ (struct sockaddr *)us, uslen,
+ opts, pf, socktype, IPPROTO_TCP,
+#if WITH_RETRY
+ (xfd->retry||xfd->forever)?E_INFO:E_ERROR
+#else
+ E_ERROR
+#endif /* WITH_RETRY */
+ );
+ /*! not sure if we should try again on retry/forever */
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ case STAT_RETRYNOW:
+ if (xfd->forever || xfd->retry) {
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ if (result == STAT_RETRYLATER) {
+ Nanosleep(&xfd->intervall, NULL);
+ }
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ --xfd->retry;
+ continue;
+ }
+ return STAT_NORETRY;
+#endif /* WITH_RETRY */
+ default:
+ return result;
+ }
+
+ result = _xioopen_openssl_listen(xfd, opt_ver, ctx, level);
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ case STAT_RETRYNOW:
+ if (xfd->forever || xfd->retry) {
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ if (result == STAT_RETRYLATER) {
+ Nanosleep(&xfd->intervall, NULL);
+ }
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ --xfd->retry;
+ continue;
+ }
+ return STAT_NORETRY;
+#endif /* WITH_RETRY */
+ default:
+ return result;
+ }
+
+ Notice1("SSL connection using %s",
+ SSL_get_cipher(xfd->para.openssl.ssl));
+ break;
+
+ } /* drop out on success */
+
+ /* fill in the fd structure */
+
+ return STAT_OK;
+}
+
+
+int _xioopen_openssl_listen(struct single *xfd,
+ bool opt_ver,
+ SSL_CTX *ctx,
+ int level) {
+ char error_string[120];
+ unsigned long err;
+ int errint, ret;
+
+ /* create an SSL object */
+ if ((xfd->para.openssl.ssl = sycSSL_new(ctx)) == NULL) {
+ if (ERR_peek_error() == 0) Msg(level, "SSL_new() failed");
+ while (err = ERR_get_error()) {
+ Msg1(level, "SSL_new(): %s", ERR_error_string(err, NULL));
+ }
+ /*Error("SSL_new()");*/
+ return STAT_NORETRY;
+ }
+
+ /* assign the network connection to the SSL object */
+ if (sycSSL_set_fd(xfd->para.openssl.ssl, xfd->fd) <= 0) {
+ if (ERR_peek_error() == 0) Msg(level, "SSL_set_fd() failed");
+ while (err = ERR_get_error()) {
+ Msg2(level, "SSL_set_fd(, %d): %s",
+ xfd->fd, ERR_error_string(err, NULL));
+ }
+ }
+
+#if WITH_DEBUG
+ {
+ int i = 0;
+ const char *ciphers = NULL;
+ Debug("available ciphers:");
+ do {
+ ciphers = SSL_get_cipher_list(xfd->para.openssl.ssl, i);
+ if (ciphers == NULL) break;
+ Debug2("CIPHERS pri=%d: %s", i, ciphers);
+ ++i;
+ } while (1);
+ }
+#endif /* WITH_DEBUG */
+
+ /* connect via SSL by performing handshake */
+ if ((ret = sycSSL_accept(xfd->para.openssl.ssl)) <= 0) {
+ /*if (ERR_peek_error() == 0) Msg(level, "SSL_accept() failed");*/
+ errint = SSL_get_error(xfd->para.openssl.ssl, ret);
+ switch (errint) {
+ case SSL_ERROR_NONE:
+ Msg(level, "ok"); break;
+ case SSL_ERROR_ZERO_RETURN:
+ Msg(level, "connection closed (wrong version number?)"); break;
+ case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_CONNECT:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ Msg(level, "nonblocking operation did not complete"); break; /*!*/
+ case SSL_ERROR_SYSCALL:
+ if (ERR_peek_error() == 0) {
+ if (ret == 0) {
+ Msg(level, "SSL_accept(): socket closed by peer");
+ } else if (ret == -1) {
+ Msg1(level, "SSL_accept(): %s", strerror(errno));
+ }
+ } else {
+ Msg(level, "I/O error"); /*!*/
+ while (err = ERR_get_error()) {
+ ERR_error_string_n(err, error_string, sizeof(error_string));
+ Msg4(level, "SSL_accept(): %s / %s / %s / %s", error_string,
+ ERR_lib_error_string(err), ERR_func_error_string(err),
+ ERR_reason_error_string(err));
+ }
+ /* Msg1(level, "SSL_connect(): %s", ERR_error_string(e, buf));*/
+ }
+ break;
+ case SSL_ERROR_SSL:
+ /*ERR_print_errors_fp(stderr);*/
+ openssl_SSL_ERROR_SSL(level, "SSL_accept");
+ break;
+ default:
+ Msg(level, "unknown error");
+ }
+
+ return STAT_RETRYLATER;
+ }
+
+ if (openssl_handle_peer_certificate(xfd, opt_ver, E_ERROR/*!*/) < 0) {
+ return STAT_NORETRY;
+ }
+
+ return STAT_OK;
+}
+
+#endif /* WITH_LISTEN */
+
+
+int
+ _xioopen_openssl_prepare(struct opt *opts,
+ struct single *xfd,/* a xio file descriptor
+ structure, already allocated
+ */
+ bool server, /* SSL client: false */
+ bool *opt_ver,
+ const char *opt_cert,
+ SSL_CTX **ctx)
+{
+ bool opt_fips = false;
+ SSL_METHOD *method;
+ char *me_str = NULL; /* method string */
+ char *ci_str = NULL; /* cipher string */
+ char *opt_key = NULL; /* file name of client private key */
+ char *opt_dhparam = NULL; /* file name of DH params */
+ char *opt_cafile = NULL; /* certificate authority file */
+ char *opt_capath = NULL; /* certificate authority directory */
+ char *opt_egd = NULL; /* entropy gathering daemon socket path */
+ bool opt_pseudo = false; /* use pseudo entropy if nothing else */
+ unsigned long err;
+ int result;
+
+ xfd->addr = &addr_openssl;
+ xfd->dtype = XIODATA_OPENSSL;
+
+ retropt_bool(opts, OPT_OPENSSL_FIPS, &opt_fips);
+ retropt_string(opts, OPT_OPENSSL_METHOD, &me_str);
+ retropt_string(opts, OPT_OPENSSL_CIPHERLIST, &ci_str);
+ retropt_bool(opts, OPT_OPENSSL_VERIFY, opt_ver);
+ retropt_string(opts, OPT_OPENSSL_CAFILE, &opt_cafile);
+ retropt_string(opts, OPT_OPENSSL_CAPATH, &opt_capath);
+ retropt_string(opts, OPT_OPENSSL_KEY, &opt_key);
+ retropt_string(opts, OPT_OPENSSL_DHPARAM, &opt_dhparam);
+ retropt_string(opts, OPT_OPENSSL_EGD, &opt_egd);
+ retropt_bool(opts,OPT_OPENSSL_PSEUDO, &opt_pseudo);
+
+#if WITH_FIPS
+ if (opt_fips) {
+ if (!sycFIPS_mode_set(1)) {
+ ERR_load_crypto_strings();
+ ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE));
+ Error("Failed to set FIPS mode");
+ } else {
+ xio_openssl_fips = true;
+ }
+ }
+#endif
+
+ OpenSSL_add_all_algorithms();
+ OpenSSL_add_all_ciphers();
+ OpenSSL_add_all_digests();
+ sycSSL_load_error_strings();
+
+ /* OpenSSL preparation */
+ sycSSL_library_init();
+
+ /*! actions_to_seed_PRNG();*/
+
+ if (!server) {
+ if (me_str != 0) {
+ if (!strcasecmp(me_str, "SSLv2") || !strcasecmp(me_str, "SSL2")) {
+ method = sycSSLv2_client_method();
+ } else if (!strcasecmp(me_str, "SSLv3") || !strcasecmp(me_str, "SSL3")) {
+ method = sycSSLv3_client_method();
+ } else if (!strcasecmp(me_str, "SSLv23") || !strcasecmp(me_str, "SSL23") ||
+ !strcasecmp(me_str, "SSL")) {
+ method = sycSSLv23_client_method();
+ } else if (!strcasecmp(me_str, "TLSv1") || !strcasecmp(me_str, "TLS1") ||
+ !strcasecmp(me_str, "TLS")) {
+ method = sycTLSv1_client_method();
+ } else {
+ Error1("openssl-method=\"%s\": unknown method", me_str);
+ method = sycSSLv23_client_method()/*!*/;
+ }
+ } else {
+ method = sycSSLv23_client_method()/*!*/;
+ }
+ } else /* server */ {
+ if (me_str != 0) {
+ if (!strcasecmp(me_str, "SSLv2") || !strcasecmp(me_str, "SSL2")) {
+ method = sycSSLv2_server_method();
+ } else if (!strcasecmp(me_str, "SSLv3") || !strcasecmp(me_str, "SSL3")) {
+ method = sycSSLv3_server_method();
+ } else if (!strcasecmp(me_str, "SSLv23") || !strcasecmp(me_str, "SSL23") ||
+ !strcasecmp(me_str, "SSL")) {
+ method = sycSSLv23_server_method();
+ } else if (!strcasecmp(me_str, "TLSv1") || !strcasecmp(me_str, "TLS1") ||
+ !strcasecmp(me_str, "TLS")) {
+ method = sycTLSv1_server_method();
+ } else {
+ Error1("openssl-method=\"%s\": unknown method", me_str);
+ method = sycSSLv23_server_method()/*!*/;
+ }
+ } else {
+ method = sycSSLv23_server_method()/*!*/;
+ }
+ }
+
+ if (opt_egd) {
+ sycRAND_egd(opt_egd);
+ }
+
+ if (opt_pseudo) {
+ long int randdata;
+ /* initialize libc random from actual microseconds */
+ struct timeval tv;
+ struct timezone tz;
+ tz.tz_minuteswest = 0;
+ tz.tz_dsttime = 0;
+ if ((result = Gettimeofday(&tv, &tz)) < 0) {
+ Warn2("gettimeofday(%p, {0,0}): %s", &tv, strerror(errno));
+ }
+ srandom(tv.tv_sec*1000000+tv.tv_usec);
+
+ while (!RAND_status()) {
+ randdata = random();
+ Debug2("RAND_seed(0x{%lx}, "F_Zu")",
+ randdata, sizeof(randdata));
+ RAND_seed(&randdata, sizeof(randdata));
+ }
+ }
+
+ if ((*ctx = sycSSL_CTX_new(method)) == NULL) {
+ if (ERR_peek_error() == 0) Error("SSL_CTX_new()");
+ while (err = ERR_get_error()) {
+ Error1("SSL_CTX_new(): %s", ERR_error_string(err, NULL));
+ }
+
+ /*ERR_clear_error;*/
+ return STAT_RETRYLATER;
+ }
+
+ if (opt_cafile != NULL || opt_capath != NULL) {
+ if (sycSSL_CTX_load_verify_locations(*ctx, opt_cafile, opt_capath) != 1) {
+ int result;
+
+ if ((result =
+ openssl_SSL_ERROR_SSL(E_ERROR, "SSL_CTX_load_verify_locations"))
+ != STAT_OK) {
+ /*! free ctx */
+ return STAT_RETRYLATER;
+ }
+ }
+ }
+
+ if (opt_cert) {
+ BIO *bio;
+ DH *dh;
+
+ if (sycSSL_CTX_use_certificate_chain_file(*ctx, opt_cert) <= 0) {
+ /*! trace functions */
+ /*0 ERR_print_errors_fp(stderr);*/
+ if (ERR_peek_error() == 0)
+ Error2("SSL_CTX_use_certificate_file(%p, \"%s\", SSL_FILETYPE_PEM) failed",
+ *ctx, opt_cert);
+ while (err = ERR_get_error()) {
+ Error1("SSL_CTX_use_certificate_file(): %s",
+ ERR_error_string(err, NULL));
+ }
+ return STAT_RETRYLATER;
+ }
+
+ if (sycSSL_CTX_use_PrivateKey_file(*ctx, opt_key?opt_key:opt_cert, SSL_FILETYPE_PEM) <= 0) {
+ /*ERR_print_errors_fp(stderr);*/
+ openssl_SSL_ERROR_SSL(E_ERROR/*!*/, "SSL_CTX_use_PrivateKey_file");
+ return STAT_RETRYLATER;
+ }
+
+ if (opt_dhparam == NULL) {
+ opt_dhparam = (char *)opt_cert;
+ }
+ if ((bio = sycBIO_new_file(opt_dhparam, "r")) == NULL) {
+ Warn2("BIO_new_file(\"%s\", \"r\"): %s",
+ opt_dhparam, strerror(errno));
+ } else {
+ if ((dh = sycPEM_read_bio_DHparams(bio, NULL, NULL, NULL)) == NULL) {
+ Info1("PEM_read_bio_DHparams(%p, NULL, NULL, NULL): error", bio);
+ } else {
+ BIO_free(bio);
+ if (sycSSL_CTX_set_tmp_dh(*ctx, dh) == 0) {
+ Error2("SSL_CTX_set_tmp_dh(%p, %p): error", ctx, dh);
+ }
+ }
+ }
+ }
+
+ /* set pre ssl-connect options */
+ /* SSL_CIPHERS */
+ if (ci_str != NULL) {
+ if (sycSSL_CTX_set_cipher_list(*ctx, ci_str) <= 0) {
+ if (ERR_peek_error() == 0)
+ Error1("SSL_set_cipher_list(, \"%s\") failed", ci_str);
+ while (err = ERR_get_error()) {
+ Error2("SSL_set_cipher_list(, \"%s\"): %s",
+ ci_str, ERR_error_string(err, NULL));
+ }
+ /*Error("SSL_new()");*/
+ return STAT_RETRYLATER;
+ }
+ }
+
+ if (*opt_ver) {
+ sycSSL_CTX_set_verify(*ctx,
+ SSL_VERIFY_PEER| SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ NULL);
+ } else {
+ sycSSL_CTX_set_verify(*ctx,
+ SSL_VERIFY_NONE,
+ NULL);
+ }
+
+ return STAT_OK;
+}
+
+
+/* analyses an OpenSSL error condition, prints the appropriate messages with
+ severity 'level' and returns one of STAT_OK, STAT_RETRYLATER, or
+ STAT_NORETRY */
+static int openssl_SSL_ERROR_SSL(int level, const char *funcname) {
+ unsigned long e;
+ char buf[120]; /* this value demanded by "man ERR_error_string" */
+
+ e = ERR_get_error();
+ Debug1("ERR_get_error(): %lx", e);
+ if (e == ((ERR_LIB_RAND<<24)|
+ (RAND_F_SSLEAY_RAND_BYTES<<12)|
+ (RAND_R_PRNG_NOT_SEEDED)) /*0x24064064*/) {
+ Error("too few entropy; use options \"egd\" or \"pseudo\"");
+ return STAT_NORETRY;
+ } else {
+ Msg2(level, "%s(): %s", funcname, ERR_error_string(e, buf));
+ return level==E_ERROR ? STAT_NORETRY : STAT_RETRYLATER;
+ }
+ return STAT_OK;
+}
+
+static const char *openssl_verify_messages[] = {
+ /* 0 */ "ok",
+ /* 1 */ NULL,
+ /* 2 */ "unable to get issuer certificate",
+ /* 3 */ "unable to get certificate CRL",
+ /* 4 */ "unable to decrypt certificate's signature",
+ /* 5 */ "unable to decrypt CRL's signature",
+ /* 6 */ "unable to decode issuer public key",
+ /* 7 */ "certificate signature failure",
+ /* 8 */ "CRL signature failure",
+ /* 9 */ "certificate is not yet valid",
+ /* 10 */ "certificate has expired",
+ /* 11 */ "CRL is not yet valid",
+ /* 12 */ "CRL has expired",
+ /* 13 */ "format error in certificate's notBefore field",
+ /* 14 */ "format error in certificate's notAfter field",
+ /* 15 */ "format error in CRL's lastUpdate field",
+ /* 16 */ "format error in CRL's nextUpdate field",
+ /* 17 */ "out of memory",
+ /* 18 */ "self signed certificate",
+ /* 19 */ "self signed certificate in certificate chain",
+ /* 20 */ "unable to get local issuer certificate",
+ /* 21 */ "unable to verify the first certificate",
+ /* 22 */ "certificate chain too long",
+ /* 23 */ "certificate revoked",
+ /* 24 */ "invalid CA certificate",
+ /* 25 */ "path length constraint exceeded",
+ /* 26 */ "unsupported certificate purpose",
+ /* 27 */ "certificate not trusted",
+ /* 28 */ "certificate rejected",
+ /* 29 */ "subject issuer mismatch",
+ /* 30 */ "authority and subject key identifier mismatch",
+ /* 31 */ "authority and issuer serial number mismatch",
+ /* 32 */ "key usage does not include certificate signing",
+ /* 33 */ NULL,
+ /* 34 */ NULL,
+ /* 35 */ NULL,
+ /* 36 */ NULL,
+ /* 37 */ NULL,
+ /* 38 */ NULL,
+ /* 39 */ NULL,
+ /* 40 */ NULL,
+ /* 41 */ NULL,
+ /* 42 */ NULL,
+ /* 43 */ NULL,
+ /* 44 */ NULL,
+ /* 45 */ NULL,
+ /* 46 */ NULL,
+ /* 47 */ NULL,
+ /* 48 */ NULL,
+ /* 49 */ NULL,
+ /* 50 */ "application verification failure",
+} ;
+
+static int openssl_handle_peer_certificate(struct single *xfd,
+ bool opt_ver, int level) {
+ X509 *peer_cert;
+ char *str;
+ char buff[2048]; /* hold peer certificate */
+ int status;
+
+ /* SSL_CTX_add_extra_chain_cert
+ SSL_get_verify_result
+ */
+ if ((peer_cert = SSL_get_peer_certificate(xfd->para.openssl.ssl)) != NULL) {
+ Debug("peer certificate:");
+ if ((str = X509_NAME_oneline(X509_get_subject_name(peer_cert), buff, sizeof(buff))) != NULL)
+ Debug1("\tsubject: %s", str); /*free (str); SIGSEGV*/
+ if ((str = X509_NAME_oneline(X509_get_issuer_name(peer_cert), buff, sizeof(buff))) != NULL)
+ Debug1("\tissuer: %s", str); /*free (str); SIGSEGV*/
+ }
+
+ if (peer_cert) {
+ if (opt_ver) {
+ long verify_result;
+ if ((verify_result = sycSSL_get_verify_result(xfd->para.openssl.ssl)) == X509_V_OK) {
+ Info("accepted peer certificate");
+ status = STAT_OK;
+ } else {
+ const char *message = NULL;
+ if (verify_result >= 0 &&
+ (size_t)verify_result <
+ sizeof(openssl_verify_messages)/sizeof(char*))
+ {
+ message = openssl_verify_messages[verify_result];
+ }
+ if (message) {
+ Msg1(level, "%s", message);
+ } else {
+ Msg1(level, "rejected peer certificate with error %ld", verify_result);
+ }
+ status = STAT_RETRYLATER;
+ }
+ } else {
+ Notice("no check of certificate");
+ status = STAT_OK;
+ }
+ } else {
+ if (opt_ver) {
+ Msg(level, "no peer certificate");
+ status = STAT_RETRYLATER;
+ } else {
+ Notice("no peer certificate and no check");
+ status = STAT_OK;
+ }
+ }
+
+ X509_free(peer_cert);
+ return status;
+}
+
+static int xioSSL_set_fd(struct single *xfd, int level) {
+ unsigned long err;
+
+ /* assign a network connection to the SSL object */
+ if (sycSSL_set_fd(xfd->para.openssl.ssl, xfd->fd) <= 0) {
+ Msg(level, "SSL_set_fd() failed");
+ while (err = ERR_get_error()) {
+ Msg2(level, "SSL_set_fd(, %d): %s",
+ xfd->fd, ERR_error_string(err, NULL));
+ }
+ return STAT_RETRYLATER;
+ }
+ return STAT_OK;
+}
+
+
+/* ...
+ in case of an error condition, this function check forever and retry
+ options and ev. sleeps an interval. It returns NORETRY when the caller
+ should not retry for any reason. */
+static int xioSSL_connect(struct single *xfd, bool opt_ver, int level) {
+ char error_string[120];
+ int errint, status, ret;
+ unsigned long err;
+
+ /* connect via SSL by performing handshake */
+ if ((ret = sycSSL_connect(xfd->para.openssl.ssl)) <= 0) {
+ /*if (ERR_peek_error() == 0) Msg(level, "SSL_connect() failed");*/
+ errint = SSL_get_error(xfd->para.openssl.ssl, ret);
+ switch (errint) {
+ case SSL_ERROR_NONE:
+ /* this is not an error, but I dare not continue for security reasons*/
+ Msg(level, "ok");
+ status = STAT_RETRYLATER;
+ case SSL_ERROR_ZERO_RETURN:
+ Msg(level, "connection closed (wrong version number?)");
+ status = STAT_RETRYLATER;
+ break;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_CONNECT:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ Msg(level, "nonblocking operation did not complete");
+ status = STAT_RETRYLATER;
+ break; /*!*/
+ case SSL_ERROR_SYSCALL:
+ if (ERR_peek_error() == 0) {
+ if (ret == 0) {
+ Msg(level, "SSL_connect(): socket closed by peer");
+ } else if (ret == -1) {
+ Msg1(level, "SSL_connect(): %s", strerror(errno));
+ }
+ } else {
+ Msg(level, "I/O error"); /*!*/
+ while (err = ERR_get_error()) {
+ ERR_error_string_n(err, error_string, sizeof(error_string));
+ Msg4(level, "SSL_connect(): %s / %s / %s / %s", error_string,
+ ERR_lib_error_string(err), ERR_func_error_string(err),
+ ERR_reason_error_string(err));
+ }
+ }
+ status = STAT_RETRYLATER;
+ break;
+ case SSL_ERROR_SSL:
+ status = openssl_SSL_ERROR_SSL(level, "SSL_connect");
+ if (openssl_handle_peer_certificate(xfd, opt_ver, level/*!*/) < 0) {
+ return STAT_RETRYLATER;
+ }
+ break;
+ default:
+ Msg(level, "unknown error");
+ status = STAT_RETRYLATER;
+ break;
+ }
+ return status;
+ }
+ return STAT_OK;
+}
+
+/* on result < 0: errno is set (at least to EIO) */
+ssize_t xioread_openssl(struct single *pipe, void *buff, size_t bufsiz) {
+ unsigned long err;
+ char error_string[120];
+ int _errno = EIO; /* if we have no better idea about nature of error */
+ int errint, ret;
+
+ ret = sycSSL_read(pipe->para.openssl.ssl, buff, bufsiz);
+ if (ret < 0) {
+ errint = SSL_get_error(pipe->para.openssl.ssl, ret);
+ switch (errint) {
+ case SSL_ERROR_NONE:
+ /* this is not an error, but I dare not continue for security reasons*/
+ Error("ok");
+ case SSL_ERROR_ZERO_RETURN:
+ Error("connection closed by peer");
+ break;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_CONNECT:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ Error("nonblocking operation did not complete");
+ break; /*!*/
+ case SSL_ERROR_SYSCALL:
+ if (ERR_peek_error() == 0) {
+ if (ret == 0) {
+ Error("SSL_read(): socket closed by peer");
+ } else if (ret == -1) {
+ _errno = errno;
+ Error1("SSL_read(): %s", strerror(errno));
+ }
+ } else {
+ Error("I/O error"); /*!*/
+ while (err = ERR_get_error()) {
+ ERR_error_string_n(err, error_string, sizeof(error_string));
+ Error4("SSL_read(): %s / %s / %s / %s", error_string,
+ ERR_lib_error_string(err), ERR_func_error_string(err),
+ ERR_reason_error_string(err));
+ }
+ }
+ break;
+ case SSL_ERROR_SSL:
+ openssl_SSL_ERROR_SSL(E_ERROR, "SSL_connect");
+ break;
+ default:
+ Error("unknown error");
+ break;
+ }
+ errno = _errno;
+ return -1;
+ }
+ return ret;
+}
+
+ssize_t xiopending_openssl(struct single *pipe) {
+ int bytes = sycSSL_pending(pipe->para.openssl.ssl);
+ return bytes;
+}
+
+/* on result < 0: errno is set (at least to EIO) */
+ssize_t xiowrite_openssl(struct single *pipe, const void *buff, size_t bufsiz) {
+ unsigned long err;
+ char error_string[120];
+ int _errno = EIO; /* if we have no better idea about nature of error */
+ int errint, ret;
+
+ ret = sycSSL_write(pipe->para.openssl.ssl, buff, bufsiz);
+ if (ret < 0) {
+ errint = SSL_get_error(pipe->para.openssl.ssl, ret);
+ switch (errint) {
+ case SSL_ERROR_NONE:
+ /* this is not an error, but I dare not continue for security reasons*/
+ Error("ok");
+ case SSL_ERROR_ZERO_RETURN:
+ Error("connection closed by peer");
+ break;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_CONNECT:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ Error("nonblocking operation did not complete");
+ break; /*!*/
+ case SSL_ERROR_SYSCALL:
+ if (ERR_peek_error() == 0) {
+ if (ret == 0) {
+ Error("SSL_write(): socket closed by peer");
+ } else if (ret == -1) {
+ _errno = errno;
+ Error1("SSL_write(): %s", strerror(errno));
+ }
+ } else {
+ Error("I/O error"); /*!*/
+ while (err = ERR_get_error()) {
+ ERR_error_string_n(err, error_string, sizeof(error_string));
+ Error4("SSL_write(): %s / %s / %s / %s", error_string,
+ ERR_lib_error_string(err), ERR_func_error_string(err),
+ ERR_reason_error_string(err));
+ }
+ }
+ break;
+ case SSL_ERROR_SSL:
+ openssl_SSL_ERROR_SSL(E_ERROR, "SSL_connect");
+ break;
+ default:
+ Error("unknown error");
+ break;
+ }
+ errno = _errno;
+ return -1;
+ }
+ return ret;
+}
+
+
+#endif /* WITH_OPENSSL */
diff --git a/xio-openssl.h b/xio-openssl.h
new file mode 100644
index 0000000..35bc6ac
--- /dev/null
+++ b/xio-openssl.h
@@ -0,0 +1,52 @@
+/* $Id: xio-openssl.h,v 1.8 2007/02/26 21:31:40 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2002-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_openssl_included
+#define __xio_openssl_included 1
+
+#if WITH_OPENSSL /* make this address configure dependend */
+
+#define SSLIO_BASE 0x53530000 /* "SSxx" */
+#define SSLIO_MASK 0xffff0000
+
+extern const struct addrdesc addr_openssl;
+extern const struct addrdesc addr_openssl_listen;
+
+extern const struct optdesc opt_openssl_cipherlist;
+extern const struct optdesc opt_openssl_method;
+extern const struct optdesc opt_openssl_verify;
+extern const struct optdesc opt_openssl_certificate;
+extern const struct optdesc opt_openssl_key;
+extern const struct optdesc opt_openssl_dhparam;
+extern const struct optdesc opt_openssl_cafile;
+extern const struct optdesc opt_openssl_capath;
+extern const struct optdesc opt_openssl_egd;
+extern const struct optdesc opt_openssl_pseudo;
+#if WITH_FIPS
+extern const struct optdesc opt_openssl_fips;
+#endif
+
+extern int
+ _xioopen_openssl_prepare(struct opt *opts, struct single *xfd,
+ bool server, bool *opt_ver, const char *opt_cert,
+ SSL_CTX **ctx);
+extern int
+ _xioopen_openssl_connect(struct single *xfd, bool opt_ver,
+ SSL_CTX *ctx, int level);
+extern int
+ _xioopen_openssl_listen(struct single *xfd, bool opt_ver,
+ SSL_CTX *ctx, int level);
+extern int xioclose_openssl(xiofile_t *xfd);
+extern int xioshutdown_openssl(xiofile_t *xfd, int how);
+extern ssize_t xioread_openssl(struct single *file, void *buff, size_t bufsiz);
+extern ssize_t xiopending_openssl(struct single *pipe);
+extern ssize_t xiowrite_openssl(struct single *file, const void *buff, size_t bufsiz);
+
+#if WITH_FIPS
+extern int xio_reset_fips_mode(void);
+#endif /* WITH_FIPS */
+
+#endif /* WITH_OPENSSL */
+
+#endif /* !defined(__xio_openssl_included) */
diff --git a/xio-pipe.c b/xio-pipe.c
new file mode 100644
index 0000000..e4f6587
--- /dev/null
+++ b/xio-pipe.c
@@ -0,0 +1,177 @@
+/* $Id: xio-pipe.c,v 1.24 2007/01/25 21:36:11 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of pipe type */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-named.h"
+
+
+#if WITH_PIPE
+
+static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
+static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts);
+
+
+const struct addrdesc addr_pipe = { "pipe", 3, xioopen_fifo, GROUP_FD|GROUP_NAMED|GROUP_OPEN|GROUP_FIFO, 0, 0, 0 HELP(":<filename>") };
+
+
+/* process an unnamed bidirectional "pipe" or "fifo" or "echo" argument with
+ options */
+static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
+ struct opt *opts2;
+ int filedes[2];
+ int numleft;
+ int result;
+
+ if (applyopts_single(&sock->stream, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ if (Pipe(filedes) != 0) {
+ Error2("pipe(%p): %s", filedes, strerror(errno));
+ return -1;
+ }
+ /*0 Info2("pipe({%d,%d})", filedes[0], filedes[1]);*/
+
+ sock->common.tag = XIO_TAG_RDWR;
+ sock->stream.dtype = XIODATA_PIPE;
+ sock->stream.fd = filedes[0];
+ sock->stream.para.bipipe.fdout = filedes[1];
+ applyopts_cloexec(sock->stream.fd, opts);
+ applyopts_cloexec(sock->stream.para.bipipe.fdout, opts);
+
+ /* one-time and input-direction options, no second application */
+ retropt_bool(opts, OPT_IGNOREEOF, &sock->stream.ignoreeof);
+
+ /* here we copy opts! */
+ if ((opts2 = copyopts(opts, GROUP_FIFO)) == NULL) {
+ return STAT_NORETRY;
+ }
+
+ /* apply options to first FD */
+ if ((result = applyopts(sock->stream.fd, opts, PH_ALL)) < 0) {
+ return result;
+ }
+ if ((result = applyopts_single(&sock->stream, opts, PH_ALL)) < 0) {
+ return result;
+ }
+
+ /* apply options to second FD */
+ if ((result = applyopts(sock->stream.para.bipipe.fdout, opts2, PH_ALL)) < 0)
+ {
+ return result;
+ }
+
+ if ((numleft = leftopts(opts)) > 0) {
+ Error1("%d option(s) could not be used", numleft);
+ showleft(opts);
+ }
+ Notice("writing to and reading from unnamed pipe");
+ return 0;
+}
+
+
+/* open a named pipe/fifo */
+static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
+ const char *pipename = argv[1];
+ int rw = (xioflags & XIO_ACCMODE);
+#if HAVE_STAT64
+ struct stat64 pipstat;
+#else
+ struct stat pipstat;
+#endif /* !HAVE_STAT64 */
+ bool opt_unlink_early = false;
+ bool opt_unlink_close = true;
+ mode_t mode = 0666;
+ int result;
+
+ if (argc == 1) {
+ return xioopen_fifo_unnamed(fd, fd->stream.opts);
+ }
+
+ if (argc != 2) {
+ Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
+ }
+
+ if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
+ applyopts(-1, opts, PH_EARLY);
+
+ if (opt_unlink_early) {
+ if (Unlink(pipename) < 0) {
+ if (errno == ENOENT) {
+ Warn2("unlink(%s): %s", pipename, strerror(errno));
+ } else {
+ Error2("unlink(%s): %s", pipename, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ }
+ }
+
+ retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
+ retropt_modet(opts, OPT_PERM, &mode);
+ if (applyopts_named(pipename, opts, PH_EARLY) < 0) {
+ return STAT_RETRYLATER;
+ }
+ if (applyopts_named(pipename, opts, PH_PREOPEN) < 0) {
+ return STAT_RETRYLATER;
+ }
+ if (
+#if HAVE_STAT64
+ Stat64(pipename, &pipstat) < 0
+#else
+ Stat(pipename, &pipstat) < 0
+#endif /* !HAVE_STAT64 */
+ ) {
+ if (errno != ENOENT) {
+ Error3("stat(\"%s\", %p): %s", pipename, &pipstat, strerror(errno));
+ } else {
+ Debug1("xioopen_fifo(\"%s\"): does not exist, creating fifo", pipename);
+#if 0
+ result = Mknod(pipename, S_IFIFO|mode, 0);
+ if (result < 0) {
+ Error3("mknod(%s, %d, 0): %s", pipename, mode, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+#else
+ result = Mkfifo(pipename, mode);
+ if (result < 0) {
+ Error3("mkfifo(%s, %d): %s", pipename, mode, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+#endif
+ Notice2("created named pipe \"%s\" for %s", pipename, ddirection[rw]);
+ }
+ if (opt_unlink_close) {
+ if ((fd->stream.unlink_close = strdup(pipename)) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", pipename);
+ }
+ fd->stream.opt_unlink_close = true;
+ }
+ } else {
+ /* exists */
+ Debug1("xioopen_fifo(\"%s\"): already exist, opening it", pipename);
+ Notice3("opening %s \"%s\" for %s",
+ filetypenames[(pipstat.st_mode&S_IFMT)>>12],
+ pipename, ddirection[rw]);
+ /*applyopts_early(pipename, opts);*/
+ applyopts_named(pipename, opts, PH_EARLY);
+ }
+
+ if ((result = _xioopen_open(pipename, rw, opts)) < 0) {
+ return result;
+ }
+ fd->stream.fd = result;
+
+ applyopts_named(pipename, opts, PH_FD);
+ applyopts(fd->stream.fd, opts, PH_FD);
+ applyopts_cloexec(fd->stream.fd, opts);
+ return _xio_openlate(&fd->stream, opts);
+}
+
+#endif /* WITH_PIPE */
diff --git a/xio-pipe.h b/xio-pipe.h
new file mode 100644
index 0000000..1d72cf8
--- /dev/null
+++ b/xio-pipe.h
@@ -0,0 +1,12 @@
+/* $Id: xio-pipe.h,v 1.4 2001/11/04 17:19:20 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_pipe_h_included
+#define __xio_pipe_h_included 1
+
+const extern struct addrdesc addr_pipe;
+
+extern int xioopen_fifo_unnamed(char *arg, xiofile_t *sock);
+
+#endif /* !defined(__xio_pipe_h_included) */
diff --git a/xio-process.c b/xio-process.c
new file mode 100644
index 0000000..1b7960e
--- /dev/null
+++ b/xio-process.c
@@ -0,0 +1,70 @@
+/* $Id: xio-process.c,v 1.9 2003/05/21 05:16:38 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2003 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file handles process related addresses options */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-process.h"
+
+/****** process related options ******/
+const struct optdesc opt_setgid_early= { "setgid-early",NULL, OPT_SETGID_EARLY,GROUP_PROCESS, PH_EARLY, TYPE_GIDT, OFUNC_SPEC };
+const struct optdesc opt_setgid = { "setgid", NULL, OPT_SETGID, GROUP_PROCESS, PH_LATE2, TYPE_GIDT, OFUNC_SPEC };
+const struct optdesc opt_setuid_early= { "setuid-early",NULL, OPT_SETUID_EARLY,GROUP_PROCESS, PH_EARLY, TYPE_UIDT, OFUNC_SPEC };
+const struct optdesc opt_setuid = { "setuid", NULL, OPT_SETUID, GROUP_PROCESS, PH_LATE2, TYPE_UIDT, OFUNC_SPEC };
+const struct optdesc opt_substuser = { "substuser", "su", OPT_SUBSTUSER, GROUP_PROCESS, PH_LATE2, TYPE_UIDT, OFUNC_SPEC };
+const struct optdesc opt_substuser_delayed = { "substuser-delayed", "su-d", OPT_SUBSTUSER_DELAYED, GROUP_PROCESS, PH_INIT, TYPE_UIDT, OFUNC_SPEC };
+const struct optdesc opt_chroot_early = { "chroot-early", NULL, OPT_CHROOT_EARLY, GROUP_PROCESS, PH_EARLY, TYPE_STRING, OFUNC_SPEC };
+const struct optdesc opt_chroot = { "chroot", NULL, OPT_CHROOT, GROUP_PROCESS, PH_LATE, TYPE_STRING, OFUNC_SPEC };
+const struct optdesc opt_setsid = { "setsid", "sid", OPT_SETSID, GROUP_PROCESS, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
+const struct optdesc opt_setpgid = { "setpgid", "pgid",OPT_SETPGID, GROUP_FORK, PH_LATE, TYPE_INT, OFUNC_SPEC };
+
+
+/* for option substuser-delayed, save info for later application */
+bool delayeduser = false;
+uid_t delayeduser_uid; /* numeric user id to switch to */
+gid_t delayeduser_gid; /* numeric group id to switch to */
+gid_t delayeduser_gids[NGROUPS]; /* num.supplementary group ids */
+size_t delayeduser_ngids; /* number of suppl. gids */
+char *delayeduser_name; /* name of user to switch to */
+char *delayeduser_dir; /* home directory of user to switch to */
+char *delayeduser_shell; /* login shell of user to switch to */
+
+
+int _xioopen_setdelayeduser(void) {
+ if (delayeduser) {
+#if HAVE_SETGROUPS
+ if ((Setgroups(delayeduser_ngids, delayeduser_gids)) != 0) {
+ Error3("setgroups("F_Zu", %p): %s",
+ delayeduser_ngids, delayeduser_gids, strerror(errno));
+ }
+#endif /* HAVE_SETGROUPS */
+ if (Setgid(delayeduser_gid) < 0) {
+ Error2("setgid("F_gid"): %s", delayeduser_gid,
+ strerror(errno));
+ }
+ if (Setuid(delayeduser_uid) < 0) {
+ Error2("setuid("F_uid"): %s", delayeduser_uid,
+ strerror(errno));
+ }
+#if 1
+ if (setenv("USER", delayeduser_name, 1) < 0)
+ Error1("setenv(\"USER\", \"%s\", 1): insufficient space",
+ delayeduser_name);
+ if (setenv("LOGNAME", delayeduser_name, 1) < 0)
+ Error1("setenv(\"LOGNAME\", \"%s\", 1): insufficient space",
+ delayeduser_name);
+ if (setenv("HOME", delayeduser_dir, 1) < 0)
+ Error1("setenv(\"HOME\", \"%s\", 1): insufficient space",
+ delayeduser_dir);
+ if (setenv("SHELL", delayeduser_shell, 1) < 0)
+ Error1("setenv(\"SHELL\", \"%s\", 1): insufficient space",
+ delayeduser_shell);
+#endif
+ delayeduser = false;
+ }
+ return 0;
+}
+
diff --git a/xio-process.h b/xio-process.h
new file mode 100644
index 0000000..928b6f9
--- /dev/null
+++ b/xio-process.h
@@ -0,0 +1,31 @@
+/* $Id: xio-process.h,v 1.7 2002/10/01 19:37:51 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001, 2002 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_process_h_included
+#define __xio_process_h_included 1
+
+extern const struct optdesc opt_setgid_early;
+extern const struct optdesc opt_setgid;
+extern const struct optdesc opt_setuid_early;
+extern const struct optdesc opt_setuid;
+extern const struct optdesc opt_substuser;
+extern const struct optdesc opt_substuser_delayed;
+extern const struct optdesc opt_chroot_early;
+extern const struct optdesc opt_chroot;
+extern const struct optdesc opt_setsid;
+extern const struct optdesc opt_setpgid;
+
+/* for option substuser-delayed, save info for later application */
+extern bool delayeduser;
+extern uid_t delayeduser_uid; /* numeric user id to switch to */
+extern gid_t delayeduser_gid; /* numeric group id to switch to */
+extern gid_t delayeduser_gids[NGROUPS]; /* num.supplementary group ids */
+extern size_t delayeduser_ngids; /* number of suppl. gids */
+extern char *delayeduser_name; /* name of user to switch to */
+extern char *delayeduser_dir; /* home directory of user to switch to */
+extern char *delayeduser_shell; /* login shell of user to switch to */
+
+extern int _xioopen_setdelayeduser(void);
+
+#endif /* !defined(__xio_process_h_included) */
diff --git a/xio-progcall.c b/xio-progcall.c
new file mode 100644
index 0000000..aebde1c
--- /dev/null
+++ b/xio-progcall.c
@@ -0,0 +1,618 @@
+/* $Id: xio-progcall.c,v 1.54 2007/03/06 21:11:55 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains common code dealing with program calls (exec, system) */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-process.h"
+#include "xio-progcall.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 };
+#endif /* HAVE_OPENPTY */
+#if HAVE_DEV_PTMX || HAVE_DEV_PTC
+const struct optdesc opt_ptmx = { "ptmx", NULL, OPT_PTMX, GROUP_PTY, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC };
+#endif
+
+#if WITH_EXEC || WITH_SYSTEM
+
+#define MAXPTYNAMELEN 64
+
+const struct optdesc opt_fdin = { "fdin", NULL, OPT_FDIN, GROUP_FORK, PH_PASTBIGEN, TYPE_USHORT, OFUNC_SPEC };
+const struct optdesc opt_fdout = { "fdout", NULL, OPT_FDOUT, GROUP_FORK, PH_PASTBIGEN, TYPE_USHORT, OFUNC_SPEC };
+const struct optdesc opt_path = { "path", NULL, OPT_PATH, GROUP_EXEC, PH_PREEXEC, TYPE_STRING, OFUNC_SPEC };
+const struct optdesc opt_pipes = { "pipes", NULL, OPT_PIPES, GROUP_FORK, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC };
+#if HAVE_PTY
+const struct optdesc opt_pty = { "pty", NULL, OPT_PTY, GROUP_FORK, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC };
+#endif
+const struct optdesc opt_stderr = { "stderr", NULL, OPT_STDERR, GROUP_FORK, PH_PASTFORK, TYPE_BOOL, OFUNC_SPEC };
+const struct optdesc opt_nofork = { "nofork", NULL, OPT_NOFORK, GROUP_FORK, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC };
+const struct optdesc opt_sighup = { "sighup", NULL, OPT_SIGHUP, GROUP_PARENT, PH_LATE, TYPE_CONST, OFUNC_SIGNAL, SIGHUP };
+const struct optdesc opt_sigint = { "sigint", NULL, OPT_SIGINT, GROUP_PARENT, PH_LATE, TYPE_CONST, OFUNC_SIGNAL, SIGINT };
+const struct optdesc opt_sigquit = { "sigquit", NULL, OPT_SIGQUIT, GROUP_PARENT, PH_LATE, TYPE_CONST, OFUNC_SIGNAL, SIGQUIT };
+
+
+/* fork for exec/system, but return before exec'ing.
+ return=0: is child process
+ return>0: is parent process
+ return<0: error occurred, assume parent process and no child exists !!!
+ */
+int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
+ struct single *fd,
+ unsigned groups,
+ struct opt **copts /* in: opts; out: opts for child */
+ ) {
+ struct opt *popts; /* parent process options */
+ int numleft;
+ int d, type, protocol, sv[2], rdpip[2], wrpip[2];
+ int rw = (xioflags & XIO_ACCMODE);
+ bool usepipes = false;
+#if HAVE_PTY
+ int ptyfd = -1, ttyfd = -1;
+ bool usebestpty = false; /* use the best available way to open pty */
+#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
+ bool useptmx = false; /* use /dev/ptmx or equivalent */
+#endif
+#if HAVE_OPENPTY
+ bool useopenpty = false; /* try only openpty */
+#endif /* HAVE_OPENPTY */
+ bool usepty = false; /* any of the pty options is selected */
+ char ptyname[MAXPTYNAMELEN];
+#endif /* HAVE_PTY */
+ pid_t pid = 0; /* mostly int */
+ short fdi = 0, fdo = 1;
+ short result;
+ bool withstderr = false;
+ bool nofork = false;
+ bool withfork;
+
+ popts = moveopts(*copts, GROUP_ALL);
+ if (applyopts_single(fd, popts, PH_INIT) < 0) return -1;
+ applyopts2(-1, popts, PH_INIT, PH_EARLY);
+
+ retropt_bool(popts, OPT_NOFORK, &nofork);
+ withfork = !nofork;
+
+ retropt_bool(popts, OPT_PIPES, &usepipes);
+#if HAVE_PTY
+ retropt_bool(popts, OPT_PTY, &usebestpty);
+#if HAVE_OPENPTY
+ retropt_bool(popts, OPT_OPENPTY, &useopenpty);
+#endif
+#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
+ retropt_bool(popts, OPT_PTMX, &useptmx);
+#endif
+ usepty = (usebestpty
+#if HAVE_OPENPTY
+ || useopenpty
+#endif
+#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
+ || useptmx
+#endif
+ );
+ if (usepipes && usepty) {
+ Warn("_xioopen_foxec(): options \"pipes\" and \"pty\" must not be specified together; ignoring \"pipes\"");
+ usepipes = false;
+ }
+#endif /* HAVE_PTY */
+ retropt_ushort(popts, OPT_FDIN, (unsigned short *)&fdi);
+ retropt_ushort(popts, OPT_FDOUT, (unsigned short *)&fdo);
+
+ if (withfork) {
+ if (!(xioflags&XIO_MAYCHILD)) {
+ Error("cannot fork off child process here");
+ /*!! free something */
+ return -1;
+ }
+ fd->flags |= XIO_DOESCHILD;
+
+#if HAVE_PTY
+ Notice2("forking off child, using %s for %s",
+ &("socket\0\0pipes\0\0\0pty\0\0\0\0\0"[(usepipes<<3)|(usepty<<4)]),
+ ddirection[rw]);
+#else
+ Notice2("forking off child, using %s for %s",
+ &("socket\0\0pipes\0\0\0"[(usepipes<<3)]),
+ ddirection[rw]);
+#endif /* HAVE_PTY */
+ }
+ applyopts(-1, popts, PH_PREBIGEN);
+
+ if (!withfork) {
+ /*0 struct single *stream1, *stream2;*/
+
+ if (!(xioflags & XIO_MAYEXEC /* means exec+nofork */)) {
+ Error("option nofork is not allowed here");
+ /*!! free something */
+ return -1;
+ }
+ fd->flags |= XIO_DOESEXEC;
+
+ free(*copts);
+ *copts = moveopts(popts, GROUP_ALL);
+
+#if 0 /*!! */
+ if (sock1->tag == XIO_TAG_DUAL) {
+ stream1 = &sock1->dual.stream[0]->stream;
+ stream2 = &sock1->dual.stream[1]->stream;
+ } else {
+ stream1 = &sock1->stream;
+ stream2 = &sock1->stream;
+ }
+ if (stream1->dtype == DATA_READLINE || stream2->dtype == DATA_READLINE ||
+ stream1->dtype == DATA_OPENSSL || stream2->dtype == DATA_OPENSSL
+ ) {
+ Error("with option nofork, openssl and readline in address1 do not work");
+ }
+ if (stream1->lineterm != LINETERM_RAW ||
+ stream2->lineterm != LINETERM_RAW ||
+ stream1->ignoreeof || stream2->ignoreeof) {
+ Warn("due to option nofork, address1 options for lineterm and igoreeof do not apply");
+ }
+#endif
+
+ /*! problem: when fdi==WRFD(sock[0]) or fdo==RDFD(sock[0]) */
+ if (rw != XIO_WRONLY) {
+ if (XIO_GETRDFD(sock[0]/*!!*/) == fdi) {
+ if (Fcntl_l(fdi, F_SETFD, 0) < 0) {
+ Warn2("fcntl(%d, F_SETFD, 0): %s", fdi, strerror(errno));
+ }
+ if (Dup2(XIO_GETRDFD(sock[0]), fdi) < 0) {
+ Error3("dup2(%d, %d): %s",
+ XIO_GETRDFD(sock[0]), fdi, strerror(errno));
+ }
+ /*0 Info2("dup2(%d, %d)", XIO_GETRDFD(sock[0]), fdi);*/
+ } else {
+ if (Dup2(XIO_GETRDFD(sock[0]), fdi) < 0) {
+ Error3("dup2(%d, %d): %s",
+ XIO_GETRDFD(sock[0]), fdi, strerror(errno));
+ }
+ /*0 Info2("dup2(%d, %d)", XIO_GETRDFD(sock[0]), fdi);*/
+ }
+ }
+ if (rw != XIO_RDONLY) {
+ if (XIO_GETWRFD(sock[0]) == fdo) {
+ if (Fcntl_l(fdo, F_SETFD, 0) < 0) {
+ Warn2("fcntl(%d, F_SETFD, 0): %s", fdo, strerror(errno));
+ }
+ if (Dup2(XIO_GETWRFD(sock[0]), fdo) < 0) {
+ Error3("dup2(%d, %d): %s)",
+ XIO_GETWRFD(sock[0]), fdo, strerror(errno));
+ }
+ /*0 Info2("dup2(%d, %d)", XIO_GETWRFD(sock[0]), fdo);*/
+ } else {
+ if (Dup2(XIO_GETWRFD(sock[0]), fdo) < 0) {
+ Error3("dup2(%d, %d): %s)",
+ XIO_GETWRFD(sock[0]), fdo, strerror(errno));
+ }
+ /*0 Info2("dup2(%d, %d)", XIO_GETWRFD(sock[0]), fdo);*/
+ }
+ }
+ } else
+#if HAVE_PTY
+ if (usepty) {
+
+#if defined(HAVE_DEV_PTMX)
+# define PTMX "/dev/ptmx" /* Linux */
+#elif HAVE_DEV_PTC
+# define PTMX "/dev/ptc" /* AIX 4.3.3 */
+#endif
+ fd->dtype = XIODATA_PTY;
+#if HAVE_DEV_PTMX || HAVE_DEV_PTC
+ if (usebestpty || useptmx) {
+ if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) {
+ Warn1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620): %s",
+ strerror(errno));
+ /*!*/
+ } else {
+ /*0 Info2("open(\"%s\", O_RDWR|O_NOCTTY, 0620) -> %d", PTMX, ptyfd);*/
+ }
+ if (ptyfd >= 0 && ttyfd < 0) {
+ char *tn = NULL;
+ /* we used PTMX before forking */
+ extern char *ptsname(int);
+#if HAVE_GRANTPT /* AIX, not Linux */
+ if (Grantpt(ptyfd)/*!*/ < 0) {
+ Warn2("grantpt(%d): %s", ptyfd, strerror(errno));
+ }
+#endif /* HAVE_GRANTPT */
+#if HAVE_UNLOCKPT
+ if (Unlockpt(ptyfd)/*!*/ < 0) {
+ Warn2("unlockpt(%d): %s", ptyfd, strerror(errno));
+ }
+#endif /* HAVE_UNLOCKPT */
+#if HAVE_PTSNAME /* AIX, not Linux */
+ if ((tn = Ptsname(ptyfd)) == NULL) {
+ Warn2("ptsname(%d): %s", ptyfd, strerror(errno));
+ }
+#endif /* HAVE_PTSNAME */
+ if (tn == NULL) {
+ if ((tn = Ttyname(ptyfd)) == NULL) {
+ Warn2("ttyname(%d): %s", ptyfd, strerror(errno));
+ }
+ }
+ strncpy(ptyname, tn, MAXPTYNAMELEN);
+ if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) {
+ Warn2("open(\"%s\", O_RDWR|O_NOCTTY, 0620): %s", tn, strerror(errno));
+ } else {
+ /*0 Info2("open(\"%s\", O_RDWR|O_NOCTTY, 0620) -> %d", tn, ttyfd);*/
+ }
+
+#ifdef I_PUSH
+ /* Linux: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> -1 EINVAL */
+ /* AIX: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 1 */
+ /* SunOS: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 0 */
+ /* HP-UX: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 0 */
+ if (Ioctl(ttyfd, I_FIND, "ldterm") == 0) {
+ Ioctl(ttyfd, I_PUSH, "ptem"); /* 0 */
+ Ioctl(ttyfd, I_PUSH, "ldterm"); /* 0 */
+ Ioctl(ttyfd, I_PUSH, "ttcompat"); /* HP-UX: -1 */
+ }
+#endif
+
+#if 0 /* the following block need not work */
+
+ if (ttyfd >= 0 && ((tn = Ttyname(ttyfd)) == NULL)) {
+ Warn2("ttyname(%d): %s", ttyfd, strerror(errno));
+ }
+ if (tn == NULL) {
+ Error("could not open pty");
+ return STAT_NORETRY;
+ }
+#endif
+ Info1("opened pseudo terminal %s", tn);
+ }
+ }
+#endif /* HAVE_DEV_PTMX || HAVE_DEV_PTC */
+#if HAVE_OPENPTY
+ if (ptyfd < 0) {
+ int result;
+ if ((result = Openpty(&ptyfd, &ttyfd, ptyname, NULL, NULL)) < 0) {
+ Error4("openpty(%p, %p, %p, NULL, NULL): %s",
+ &ptyfd, &ttyfd, ptyname, strerror(errno));
+ return -1;
+ }
+ }
+#endif /* HAVE_OPENPTY */
+ free(*copts);
+ if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
+ return STAT_RETRYLATER;
+ }
+ applyopts_cloexec(ptyfd, popts);/*!*/
+ if (fd->howtoend = END_UNSPEC) {
+ fd->howtoend = END_CLOSE_KILL;
+ }
+
+ /* this for parent, was after fork */
+ applyopts(ptyfd, popts, PH_FD);
+ applyopts(ptyfd, popts, PH_LATE);
+ if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
+
+ fd->fd = ptyfd;
+
+ /* this for child, was after fork */
+ applyopts(ttyfd, *copts, PH_FD);
+ } else
+#endif /* HAVE_PTY */
+ if (usepipes) {
+ struct opt *popts2, *copts2;
+
+ if (rw == XIO_RDWR)
+ fd->dtype = XIODATA_2PIPE;
+ if (rw != XIO_WRONLY) {
+ if (Pipe(rdpip) < 0) {
+ Error2("pipe(%p): %s", rdpip, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ }
+ /*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/
+ /* rdpip[0]: read by socat; rdpip[1]: write by child */
+ free(*copts);
+ if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS))
+ == NULL) {
+ return STAT_RETRYLATER;
+ }
+
+ popts2 = copyopts(popts, GROUP_ALL);
+ copts2 = copyopts(*copts, GROUP_ALL);
+
+ if (rw != XIO_WRONLY) {
+ applyopts_cloexec(rdpip[0], popts);
+ applyopts(rdpip[0], popts, PH_FD);
+ applyopts(rdpip[1], *copts, PH_FD);
+ }
+
+ if (rw != XIO_RDONLY) {
+ if (Pipe(wrpip) < 0) {
+ Error2("pipe(%p): %s", wrpip, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ }
+ /*0 Info2("pipe({%d,%d})", wrpip[0], wrpip[1]);*/
+
+ /* wrpip[1]: write by socat; wrpip[0]: read by child */
+ if (rw != XIO_RDONLY) {
+ applyopts_cloexec(wrpip[1], popts2);
+ applyopts(wrpip[1], popts2, PH_FD);
+ applyopts(wrpip[0], copts2, PH_FD);
+ }
+ if (fd->howtoend == END_UNSPEC) {
+ fd->howtoend = END_CLOSE_KILL;
+ }
+
+ /* this for parent, was after fork */
+ switch (rw) {
+ case XIO_RDONLY: fd->fd = rdpip[0]; break;
+ case XIO_WRONLY: fd->fd = wrpip[1]; break;
+ case XIO_RDWR: fd->fd = rdpip[0];
+ fd->para.exec.fdout = wrpip[1];
+ break;
+ }
+ applyopts(fd->fd, popts, PH_FD);
+ applyopts(fd->fd, popts, PH_LATE);
+ if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
+ } else {
+ d = AF_UNIX; type = SOCK_STREAM;
+ protocol = 0; /* PF_UNIX does not work on AIX */
+ retropt_int(popts, OPT_SO_TYPE, &type);
+ result = Socketpair(d, type, protocol, sv);
+ if (result < 0) {
+ Error5("socketpair(%d, %d, %d, %p): %s",
+ d, type, protocol, sv, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ /*0 Info5("socketpair(%d, %d, %d, {%d,%d})",
+ d, type, protocol, sv[0], sv[1]);*/
+ free(*copts);
+ if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
+ return STAT_RETRYLATER;
+ }
+ applyopts(sv[0], *copts, PH_PASTSOCKET);
+ applyopts(sv[1], popts, PH_PASTSOCKET);
+
+ applyopts_cloexec(sv[0], *copts);
+ applyopts(sv[0], *copts, PH_FD);
+ applyopts(sv[1], popts, PH_FD);
+
+ applyopts(sv[0], *copts, PH_PREBIND);
+ applyopts(sv[0], *copts, PH_BIND);
+ applyopts(sv[0], *copts, PH_PASTBIND);
+ applyopts(sv[1], popts, PH_PREBIND);
+ applyopts(sv[1], popts, PH_BIND);
+ applyopts(sv[1], popts, PH_PASTBIND);
+
+ if (fd->howtoend == END_UNSPEC) {
+ fd->howtoend = END_SHUTDOWN_KILL;
+ }
+
+ /* this for parent, was after fork */
+ fd->fd = sv[0];
+ applyopts(fd->fd, popts, PH_FD);
+ applyopts(fd->fd, popts, PH_LATE);
+ if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
+ }
+ /*0 if ((optpr = copyopts(*copts, GROUP_PROCESS)) == NULL)
+ return STAT_RETRYLATER;*/
+ retropt_bool(*copts, OPT_STDERR, &withstderr);
+ if (Signal(SIGCHLD, childdied) == SIG_ERR) {
+ Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
+ }
+
+ if (withfork) {
+ const char *forkwaitstring;
+ int forkwaitsecs = 0;
+
+ pid = Fork();
+ if (pid < 0) {
+ Error1("fork(): %s", strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ /* gdb recommends to have env controlled sleep after fork */
+ if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) {
+ forkwaitsecs = atoi(forkwaitstring);
+ Sleep(forkwaitsecs);
+ }
+
+ if (pid == 0) { /* child */
+ /* drop parents locks, reset FIPS... */
+ if (xio_forked_inchild() != 0) {
+ Exit(1);
+ }
+ }
+ }
+ if (!withfork || pid == 0) { /* child */
+ uid_t user;
+ gid_t group;
+
+ if (withfork) {
+ if (Signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
+ Warn1("signal(SIGCHLD, SIG_IGN): %s", strerror(errno));
+ }
+
+#if HAVE_PTY
+ if (usepty) {
+ if (rw != XIO_RDONLY && fdi != ttyfd) {
+ if (Dup2(ttyfd, fdi) < 0) {
+ Error3("dup2(%d, %d): %s", ttyfd, fdi, strerror(errno));
+ return STAT_RETRYLATER; }
+ /*0 Info2("dup2(%d, %d)", ttyfd, fdi);*/
+ }
+ if (rw != XIO_WRONLY && fdo != ttyfd) {
+ if (Dup2(ttyfd, fdo) < 0) {
+ Error3("dup2(%d, %d): %s", ttyfd, fdo, strerror(errno));
+ return STAT_RETRYLATER; }
+ /*0 Info2("dup2(%d, %d)", ttyfd, fdo);*/
+ }
+ if ((rw == XIO_RDONLY || fdi != ttyfd) &&
+ (rw == XIO_WRONLY || fdo != ttyfd)) {
+ applyopts_cloexec(ttyfd, *copts);
+ }
+
+ applyopts(ttyfd, *copts, PH_LATE);
+
+ applyopts(ttyfd, *copts, PH_LATE2);
+ } else
+#endif /* HAVE_PTY */
+ if (usepipes) {
+ /* we might have a temporary conflict between what FDs are
+ currently allocated, and which are to be used. We try to find
+ a graceful solution via temporary descriptors */
+ int tmpi, tmpo;
+
+ if (fdi == rdpip[1]) { /* a conflict here */
+ if ((tmpi = Dup(wrpip[0])) < 0) {
+ Error2("dup(%d): %s", wrpip[0], strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ /*0 Info2("dup(%d) -> %d", wrpip[0], tmpi);*/
+ rdpip[1] = tmpi;
+ }
+ if (fdo == wrpip[0]) { /* a conflict here */
+ if ((tmpo = Dup(rdpip[1])) < 0) {
+ Error2("dup(%d): %s", rdpip[1], strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ /*0 Info2("dup(%d) -> %d", rdpip[1], tmpo);*/
+ wrpip[0] = tmpo;
+ }
+
+ if (rw != XIO_WRONLY && rdpip[1] != fdo) {
+ if (Dup2(rdpip[1], fdo) < 0) {
+ Error3("dup2(%d, %d): %s", rdpip[1], fdo, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ Close(rdpip[1]);
+ /*0 Info2("dup2(%d, %d)", rdpip[1], fdo);*/
+ /*0 applyopts_cloexec(fdo, *copts);*/
+ }
+ if (rw != XIO_RDONLY && wrpip[0] != fdi) {
+ if (Dup2(wrpip[0], fdi) < 0) {
+ Error3("dup2(%d, %d): %s", wrpip[0], fdi, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ Close(wrpip[0]);
+ /*0 Info2("dup2(%d, %d)", wrpip[0], fdi);*/
+ /*0 applyopts_cloexec(wrpip[0], *copts);*/ /* option is already consumed! */
+ /* applyopts_cloexec(fdi, *copts);*/ /* option is already consumed! */
+ }
+
+ applyopts(fdi, *copts, PH_LATE);
+ applyopts(fdo, *copts, PH_LATE);
+ applyopts(fdi, *copts, PH_LATE2);
+ applyopts(fdo, *copts, PH_LATE2);
+
+ } else { /* socketpair */
+ if (rw != XIO_RDONLY && fdi != sv[1]) {
+ if (Dup2(sv[1], fdi) < 0) {
+ Error3("dup2(%d, %d): %s", sv[1], fdi, strerror(errno));
+ return STAT_RETRYLATER; }
+ /*0 Info2("dup2(%d, %d)", sv[1], fdi);*/
+ }
+ if (rw != XIO_WRONLY && fdo != sv[1]) {
+ if (Dup2(sv[1], fdo) < 0) {
+ Error3("dup2(%d, %d): %s", sv[1], fdo, strerror(errno));
+ return STAT_RETRYLATER; }
+ /*0 Info2("dup2(%d, %d)", sv[1], fdo);*/
+ }
+ if (fdi != sv[1] && fdo != sv[1]) {
+ applyopts_cloexec(sv[1], *copts);
+ }
+
+ applyopts(fdi, *copts, PH_LATE);
+ applyopts(fdi, *copts, PH_LATE2);
+ }
+ } /* withfork */
+ else {
+ applyopts(-1, *copts, PH_LATE);
+ applyopts(-1, *copts, PH_LATE2);
+ }
+
+ /* what to do with stderr? */
+ if (withstderr) {
+ /* handle it just like ordinary process output, i.e. copy output fd */
+ if (!withfork) {
+ if (Dup2(fdo, 2) < 0) {
+ Error2("dup2(%d, 2): %s", fdo, strerror(errno));
+ }
+ /*0 Info1("dup2(%d, 2)", fdo);*/
+ } else
+#if HAVE_PTY
+ if (usepty) {
+ if (Dup2(ttyfd, 2) < 0) {
+ Error2("dup2(%d, 2): %s", ttyfd, strerror(errno));
+ }
+ /*0 Info1("dup2(%d, 2)", ttyfd);*/
+ } else
+#endif /* HAVE_PTY */
+ if (usepipes) {
+ if (Dup2(/*rdpip[1]*/ fdo, 2) < 0) {
+ Error2("dup2(%d, 2): %s", /*rdpip[1]*/ fdo, strerror(errno));
+ }
+ /*0 Info1("dup2(%d, 2)", rdpip[1]);*/
+ } else {
+ if (Dup2(sv[1], 2) < 0) {
+ Error2("dup2(%d, 2): %s", sv[1], strerror(errno));
+ }
+ /*0 Info1("dup2(%d, 2)", sv[1]);*/
+ }
+ }
+ _xioopen_setdelayeduser();
+ /* set group before user - maybe you are not permitted afterwards */
+ if (retropt_gidt(*copts, OPT_SETGID, &group) >= 0) {
+ Setgid(group);
+ }
+ if (retropt_uidt(*copts, OPT_SETUID, &user) >= 0) {
+ Setuid(user);
+ }
+ return 0; /* indicate child process */
+ }
+
+ /* for parent (this is our socat process) */
+ Notice1("forked off child process "F_pid, pid);
+
+#if 0
+ if ((popts = copyopts(*copts,
+ GROUP_FD|GROUP_TERMIOS|GROUP_FORK|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_FIFO)) == NULL)
+ return STAT_RETRYLATER;
+#endif
+
+#if HAVE_PTY
+ if (usepty) {
+ if (Close(ttyfd) < 0) {
+ Info2("close(%d): %s", ttyfd, strerror(errno));
+ }
+ } /*0 else*/
+#endif /* HAVE_PTY */
+#if 0
+ if (usepipes) {
+ } else {
+ }
+#endif
+ fd->para.exec.pid = pid;
+
+ if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
+ applyopts_signal(fd, popts);
+ if ((numleft = leftopts(popts)) > 0) {
+ Error1("%d option(s) could not be used", numleft);
+ showleft(popts);
+ return STAT_NORETRY;
+ }
+
+ return pid; /* indicate parent (main) process */
+}
+#endif /* WITH_EXEC || WITH_SYSTEM */
+
+
+int setopt_path(struct opt *opts, char **path) {
+ if (retropt_string(opts, OPT_PATH, path) >= 0) {
+ if (setenv("PATH", *path, 1) < 0) {
+ Error1("setenv(\"PATH\", \"%s\", 1): insufficient space", *path);
+ return -1;
+ }
+ }
+ return 0;
+}
diff --git a/xio-progcall.h b/xio-progcall.h
new file mode 100644
index 0000000..d89ce31
--- /dev/null
+++ b/xio-progcall.h
@@ -0,0 +1,28 @@
+/* $Id: xio-progcall.h,v 1.13 2006/02/08 19:37:15 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_progcall_h_included
+#define __xio_progcall_h_included 1
+
+extern const struct optdesc opt_fdin;
+extern const struct optdesc opt_fdout;
+extern const struct optdesc opt_path;
+extern const struct optdesc opt_pipes;
+extern const struct optdesc opt_pty;
+extern const struct optdesc opt_openpty;
+extern const struct optdesc opt_ptmx;
+extern const struct optdesc opt_stderr;
+extern const struct optdesc opt_nofork;
+extern const struct optdesc opt_sighup;
+extern const struct optdesc opt_sigint;
+extern const struct optdesc opt_sigquit;
+
+extern int _xioopen_foxec(int rw, /* O_RDONLY etc. */
+ struct single *fd,
+ unsigned groups,
+ struct opt **opts
+ );
+extern int setopt_path(struct opt *opts, char **path);
+
+#endif /* !defined(__xio_progcall_h_included) */
diff --git a/xio-proxy.c b/xio-proxy.c
new file mode 100644
index 0000000..df673f2
--- /dev/null
+++ b/xio-proxy.c
@@ -0,0 +1,561 @@
+/* $Id: xio-proxy.c,v 1.28 2006/12/28 14:02:54 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2002-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of HTTP proxy CONNECT
+ type */
+
+#include "xiosysincludes.h"
+
+#if WITH_PROXY
+
+#include "xioopen.h"
+#include "xio-socket.h"
+#include "xio-ipapp.h"
+#include "xio-ascii.h" /* for base64 encoding of authentication */
+
+#include "xio-proxy.h"
+
+
+#define PROXYPORT "8080"
+
+static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *fd,
+ unsigned groups, int dummy1, int dummy2,
+ int dummy3);
+
+const struct optdesc opt_proxyport = { "proxyport", NULL, OPT_PROXYPORT, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
+const struct optdesc opt_ignorecr = { "ignorecr", NULL, OPT_IGNORECR, GROUP_HTTP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
+const struct optdesc opt_proxy_resolve = { "proxy-resolve", "resolve", OPT_PROXY_RESOLVE, GROUP_HTTP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
+const struct optdesc opt_proxy_authorization = { "proxy-authorization", "proxyauth", OPT_PROXY_AUTHORIZATION, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
+
+const struct addrdesc addr_proxy_connect = { "proxy", 3, xioopen_proxy_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_HTTP|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<proxy-server>:<host>:<port>") };
+
+
+/*0#define CONNLEN 40*/ /* "CONNECT 123.156.189.123:65432 HTTP/1.0\r\n\0" */
+#define CONNLEN 281 /* "CONNECT <255bytes>:65432 HTTP/1.0\r\n\0" */
+
+/* states during receiving answer */
+enum {
+ XIOSTATE_HTTP1, /* 0 or more bytes of first line received, no \r */
+ XIOSTATE_HTTP2, /* first line received including \r */
+ XIOSTATE_HTTP3, /* received status and \r\n */
+ XIOSTATE_HTTP4, /* within header */
+ XIOSTATE_HTTP5, /* within header, \r */
+ XIOSTATE_HTTP6, /* received status and 1 or more headers, \r\n */
+ XIOSTATE_HTTP7, /* received status line, ev. headers, \r\n\r */
+ XIOSTATE_HTTP8, /* complete answer received */
+ XIOSTATE_ERROR /* error during HTTP headers */
+} ;
+
+
+/* get buflen bytes from proxy server;
+ handles EINTR;
+ returns <0 when error occurs
+*/
+static ssize_t
+ xioproxy_recvbytes(struct single *xfd, char *buff, size_t buflen, int level) {
+ ssize_t result;
+ do {
+ /* we need at least buflen bytes... */
+ result = Read(xfd->fd, buff, buflen);
+ } while (result < 0 && errno == EINTR); /*! EAGAIN? */
+ if (result < 0) {
+ Msg4(level, "read(%d, %p, "F_Zu"): %s",
+ xfd->fd, buff, buflen, strerror(errno));
+ return result;
+ }
+ if (result == 0) {
+ Msg(level, "proxy_connect: connection closed by proxy");
+ }
+ return result;
+}
+
+
+#define BUFLEN 2048
+
+
+static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xxfd,
+ unsigned groups, int dummy1, int dummy2,
+ int dummy3) {
+ /* we expect the form: host:host:port */
+ struct single *xfd = &xxfd->stream;
+ struct opt *opts0 = NULL;
+ struct proxyvars struct_proxyvars = { 0 }, *proxyvars = &struct_proxyvars;
+ /* variables to be filled with address option values */
+ bool dofork = false;
+ /* */
+ int pf = PF_UNSPEC;
+ union sockaddr_union us_sa, *us = &us_sa;
+ union sockaddr_union them_sa, *them = &them_sa;
+ socklen_t uslen = sizeof(us_sa);
+ socklen_t themlen = sizeof(them_sa);
+ const char *proxyname; char *proxyport = NULL;
+ const char *targetname, *targetport;
+ int ipproto = IPPROTO_TCP;
+ bool needbind = false;
+ bool lowport = false;
+ int socktype = SOCK_STREAM;
+ int level;
+ int result;
+
+ if (argc != 4) {
+ Error1("%s: 3 parameters required", argv[0]);
+ return STAT_NORETRY;
+ }
+ proxyname = argv[1];
+ targetname = argv[2];
+ targetport = argv[3];
+
+ xfd->howtoend = END_SHUTDOWN;
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ retropt_int(opts, OPT_SO_TYPE, &socktype);
+
+ retropt_bool(opts, OPT_FORK, &dofork);
+
+ if (retropt_string(opts, OPT_PROXYPORT, &proxyport) < 0) {
+ if ((proxyport = strdup(PROXYPORT)) == NULL) {
+ errno = ENOMEM; return -1;
+ }
+ }
+
+ result = _xioopen_proxy_prepare(proxyvars, opts, targetname, targetport);
+ if (result != STAT_OK) return result;
+
+ result =
+ _xioopen_ipapp_prepare(opts, &opts0, proxyname, proxyport,
+ &pf, ipproto,
+ xfd->para.socket.ip.res_opts[1],
+ xfd->para.socket.ip.res_opts[0],
+ them, &themlen, us, &uslen,
+ &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);
+
+ do { /* loop over failed connect and proxy connect attempts */
+
+#if WITH_RETRY
+ if (xfd->forever || xfd->retry) {
+ level = E_INFO;
+ } else
+#endif /* WITH_RETRY */
+ level = E_ERROR;
+
+ result =
+ _xioopen_connect(xfd,
+ needbind?(struct sockaddr *)us:NULL, sizeof(*us),
+ (struct sockaddr *)them, themlen,
+ opts, pf, socktype, IPPROTO_TCP, lowport, level);
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ case STAT_RETRYNOW:
+ if (xfd->forever || xfd->retry--) {
+ if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL);
+ continue;
+ }
+#endif /* WITH_RETRY */
+ default:
+ return result;
+ }
+
+ applyopts(xfd->fd, opts, PH_ALL);
+
+ if ((result = _xio_openlate(xfd, opts)) < 0)
+ return result;
+
+ result = _xioopen_proxy_connect(xfd, proxyvars, level);
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ case STAT_RETRYNOW:
+ if (xfd->forever || xfd->retry--) {
+ if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL);
+ continue;
+ }
+#endif /* WITH_RETRY */
+ default:
+ return result;
+ }
+
+#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;
+ }
+ 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);
+ }
+ xfd->forever = false; xfd->retry = 0;
+ break;
+ }
+ /* parent process */
+ Notice1("forked off child process "F_pid, pid);
+ Close(xfd->fd);
+ Nanosleep(&xfd->intervall, NULL);
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ continue;
+ } else
+#endif /* WITH_RETRY */
+ {
+ break;
+ }
+
+ } while (true); /* end of complete open loop - drop out on success */
+
+ Notice4("successfully connected to %s:%u via proxy %s:%s",
+ proxyvars->targetaddr, proxyvars->targetport,
+ proxyname, proxyport);
+
+ return 0;
+}
+
+
+int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts,
+ const char *targetname, const char *targetport) {
+ struct hostent *host;
+
+ retropt_bool(opts, OPT_IGNORECR, &proxyvars->ignorecr);
+ retropt_bool(opts, OPT_PROXY_RESOLVE, &proxyvars->doresolve);
+ retropt_string(opts, OPT_PROXY_AUTHORIZATION, &proxyvars->authstring);
+
+ if (proxyvars->doresolve) {
+ /* currently we only resolve to IPv4 addresses. This is in accordance to
+ RFC 2396; however once it becomes clear how IPv6 addresses should be
+ represented in CONNECT commands this code might be extended */
+ host = Gethostbyname(targetname);
+ if (host == NULL) {
+ int level = E_WARN;
+ Msg2(level, "gethostbyname(\"%s\"): %s", targetname,
+ h_errno == NETDB_INTERNAL ? strerror(errno) :
+ hstrerror(h_errno)/*0 h_messages[h_errno-1]*/);
+ proxyvars->targetaddr = strdup(targetname);
+ } else {
+#define LEN 16 /* www.xxx.yyy.zzz\0 */
+ if ((proxyvars->targetaddr = Malloc(LEN)) == NULL) {
+ return STAT_RETRYLATER;
+ }
+ snprintf(proxyvars->targetaddr, LEN, "%u.%u.%u.%u",
+ (unsigned char)host->h_addr_list[0][0],
+ (unsigned char)host->h_addr_list[0][1],
+ (unsigned char)host->h_addr_list[0][2],
+ (unsigned char)host->h_addr_list[0][3]);
+#undef LEN
+ }
+ } else {
+ proxyvars->targetaddr = strdup(targetname);
+ }
+
+ proxyvars->targetport = htons(parseport(targetport, IPPROTO_TCP));
+
+ return STAT_OK;
+}
+
+int _xioopen_proxy_connect(struct single *xfd,
+ struct proxyvars *proxyvars,
+ int level) {
+ size_t offset;
+ char request[CONNLEN];
+ char buff[BUFLEN+1];
+#if CONNLEN > BUFLEN
+#error not enough buffer space
+#endif
+ char textbuff[2*BUFLEN+1]; /* just for sanitizing print data */
+ char *eol = buff;
+ int state;
+ ssize_t sresult;
+
+ /* generate proxy request header - points to final target */
+ sprintf(request, "CONNECT %s:%u HTTP/1.0\r\n",
+ proxyvars->targetaddr, proxyvars->targetport);
+
+ /* send proxy CONNECT request (target addr+port) */
+ * xiosanitize(request, strlen(request), textbuff) = '\0';
+ Info1("sending \"%s\"", textbuff);
+ /* write errors are assumed to always be hard errors, no retry */
+ do {
+ sresult = Write(xfd->fd, request, strlen(request));
+ } while (sresult < 0 && errno == EINTR);
+ if (sresult < 0) {
+ Msg4(level, "write(%d, %p, "F_Zu"): %s",
+ xfd->fd, request, strlen(request), strerror(errno));
+ if (Close(xfd->fd) < 0) {
+ Info2("close(%d): %s", xfd->fd, strerror(errno));
+ }
+ return STAT_RETRYLATER;
+ }
+
+ if (proxyvars->authstring) {
+ /* send proxy authentication header */
+# define XIOAUTHHEAD "Proxy-authorization: Basic "
+# define XIOAUTHLEN 27
+ static const char *authhead = XIOAUTHHEAD;
+# define HEADLEN 256
+ char *header, *next;
+
+ /* ...\r\n\0 */
+ if ((header =
+ Malloc(XIOAUTHLEN+((strlen(proxyvars->authstring)+2)/3)*4+3))
+ == NULL) {
+ return -1;
+ }
+ strcpy(header, authhead);
+ next = xiob64encodeline(proxyvars->authstring,
+ strlen(proxyvars->authstring),
+ strchr(header, '\0'));
+ *next = '\0';
+ Info1("sending \"%s\\r\\n\"", header);
+ *next++ = '\r'; *next++ = '\n'; *next++ = '\0';
+ do {
+ sresult = Write(xfd->fd, header, strlen(header));
+ } while (sresult < 0 && errno == EINTR);
+ if (sresult < 0) {
+ Msg4(level, "write(%d, %p, "F_Zu"): %s",
+ xfd->fd, header, strlen(header), strerror(errno));
+ if (Close(xfd->fd) < 0) {
+ Info2("close(%d): %s", xfd->fd, strerror(errno));
+ }
+ return STAT_RETRYLATER;
+ }
+
+ free(header);
+ }
+
+ Info("sending \"\\r\\n\"");
+ do {
+ sresult = Write(xfd->fd, "\r\n", 2);
+ } while (sresult < 0 && errno == EINTR);
+ /*! */
+
+ /* request is kept for later error messages */
+ *strstr(request, " HTTP") = '\0';
+
+ /* receive proxy answer; looks like "HTTP/1.0 200 .*\r\nHeaders..\r\n\r\n" */
+ /* socat version 1 depends on a valid fd for data transfer; address
+ therefore cannot buffer data. So, to prevent reading beyond the end of
+ the answer headers, only single bytes are read. puh. */
+ state = XIOSTATE_HTTP1;
+ offset = 0; /* up to where the buffer is filled (relative) */
+ /*eol;*/ /* points to the first lineterm of the current line */
+ do {
+ sresult = xioproxy_recvbytes(xfd, buff+offset, 1, level);
+ if (sresult <= 0) {
+ state = XIOSTATE_ERROR;
+ break; /* leave read cycles */
+ }
+
+ switch (state) {
+
+ case XIOSTATE_HTTP1:
+ /* 0 or more bytes of first line received, no '\r' yet */
+ if (*(buff+offset) == '\r') {
+ eol = buff+offset;
+ state = XIOSTATE_HTTP2;
+ break;
+ }
+ if (proxyvars->ignorecr && *(buff+offset) == '\n') {
+ eol = buff+offset;
+ state = XIOSTATE_HTTP3;
+ break;
+ }
+ break;
+
+ case XIOSTATE_HTTP2:
+ /* first line received including '\r' */
+ if (*(buff+offset) != '\n') {
+ state = XIOSTATE_HTTP1;
+ break;
+ }
+ state = XIOSTATE_HTTP3;
+ break;
+
+ case XIOSTATE_HTTP3:
+ /* received status (first line) and "\r\n" */
+ if (*(buff+offset) == '\r') {
+ state = XIOSTATE_HTTP7;
+ break;
+ }
+ if (proxyvars->ignorecr && *(buff+offset) == '\n') {
+ state = XIOSTATE_HTTP8;
+ break;
+ }
+ state = XIOSTATE_HTTP4;
+ break;
+
+ case XIOSTATE_HTTP4:
+ /* within header */
+ if (*(buff+offset) == '\r') {
+ eol = buff+offset;
+ state = XIOSTATE_HTTP5;
+ break;
+ }
+ if (proxyvars->ignorecr && *(buff+offset) == '\n') {
+ eol = buff+offset;
+ state = XIOSTATE_HTTP6;
+ break;
+ }
+ break;
+
+ case XIOSTATE_HTTP5:
+ /* within header, '\r' received */
+ if (*(buff+offset) != '\n') {
+ state = XIOSTATE_HTTP4;
+ break;
+ }
+ state = XIOSTATE_HTTP6;
+ break;
+
+ case XIOSTATE_HTTP6:
+ /* received status (first line) and 1 or more headers, "\r\n" */
+ if (*(buff+offset) == '\r') {
+ state = XIOSTATE_HTTP7;
+ break;
+ }
+ if (proxyvars->ignorecr && *(buff+offset) == '\n') {
+ state = XIOSTATE_HTTP8;
+ break;
+ }
+ state = XIOSTATE_HTTP4;
+ break;
+
+ case XIOSTATE_HTTP7:
+ /* received status (first line), 0 or more headers, "\r\n\r" */
+ if (*(buff+offset) == '\n') {
+ state = XIOSTATE_HTTP8;
+ break;
+ }
+ if (*(buff+offset) == '\r') {
+ if (proxyvars->ignorecr) {
+ break; /* ignore it, keep waiting for '\n' */
+ } else {
+ state = XIOSTATE_HTTP5;
+ }
+ break;
+ }
+ state = XIOSTATE_HTTP4;
+ break;
+
+ }
+ ++offset;
+
+ /* end of status line reached */
+ if (state == XIOSTATE_HTTP3) {
+ char *ptr;
+ /* set a terminating null - on or after CRLF? */
+ *(buff+offset) = '\0';
+
+ * xiosanitize(buff, Min(offset, (sizeof(textbuff)-1)>>1), textbuff)
+ = '\0';
+ Info1("proxy_connect: received answer \"%s\"", textbuff);
+ *eol = '\0';
+ * xiosanitize(buff, Min(strlen(buff), (sizeof(textbuff)-1)>>1),
+ textbuff) = '\0';
+ if (strncmp(buff, "HTTP/1.0 ", 9) &&
+ strncmp(buff, "HTTP/1.1 ", 9)) {
+ /* invalid answer */
+ Msg1(level, "proxy: invalid answer \"%s\"", textbuff);
+ return STAT_RETRYLATER;
+ }
+ ptr = buff+9;
+
+ /* skip multiple spaces */
+ while (*ptr == ' ') ++ptr;
+
+ /* HTTP answer */
+ if (strncmp(ptr, "200", 3)) {
+ /* not ok */
+ /* CERN:
+ "HTTP/1.0 200 Connection established"
+ "HTTP/1.0 400 Invalid request "CONNECT 10.244.9.3:8080 HTTP/1.0" (unknown method)"
+ "HTTP/1.0 403 Forbidden - by rule"
+ "HTTP/1.0 407 Proxy Authentication Required"
+ Proxy-Authenticate: Basic realm="Squid proxy-caching web server"
+> 50 72 6f 78 79 2d 61 75 74 68 6f 72 69 7a 61 74 Proxy-authorizat
+> 69 6f 6e 3a 20 42 61 73 69 63 20 61 57 4e 6f 63 ion: Basic aWNoc
+> 32 56 73 59 6e 4e 30 4f 6e 4e 30 63 6d 56 75 5a 2VsYnN0OnN0cmVuZ
+> 32 64 6c 61 47 56 70 62 51 3d 3d 0d 0a 2dlaGVpbQ==..
+ b64encode("username:password")
+ "HTTP/1.0 500 Can't connect to host"
+ */
+ /* Squid:
+ "HTTP/1.0 400 Bad Request"
+ "HTTP/1.0 403 Forbidden"
+ "HTTP/1.0 503 Service Unavailable"
+ interesting header: "X-Squid-Error: ERR_CONNECT_FAIL 111" */
+ /* Apache:
+ "HTTP/1.0 400 Bad Request"
+ "HTTP/1.1 405 Method Not Allowed"
+ */
+ /* WTE:
+ "HTTP/1.1 200 Connection established"
+ "HTTP/1.1 404 Host not found or not responding, errno: 79"
+ "HTTP/1.1 404 Host not found or not responding, errno: 32"
+ "HTTP/1.1 404 Host not found or not responding, errno: 13"
+ */
+ /* IIS:
+ "HTTP/1.1 404 Object Not Found"
+ */
+ ptr += 3;
+ while (*ptr == ' ') ++ptr;
+
+ Msg2(level, "%s: %s", request, ptr);
+ return STAT_RETRYLATER;
+ }
+
+ /* ok!! */
+ /* "HTTP/1.0 200 Connection established" */
+ /*Info1("proxy: \"%s\"", textbuff+13);*/
+ offset = 0;
+
+ } else if (state == XIOSTATE_HTTP6) {
+ /* end of a header line reached */
+ char *endp;
+
+ /* set a terminating null */
+ *(buff+offset) = '\0';
+
+ endp =
+ xiosanitize(buff, Min(offset, (sizeof(textbuff)-1)>>1),
+ textbuff);
+ *endp = '\0';
+ Info1("proxy_connect: received header \"%s\"", textbuff);
+ offset = 0;
+ }
+
+ } while (state != XIOSTATE_HTTP8 && offset < BUFLEN);
+
+ if (state == XIOSTATE_ERROR) {
+ return STAT_RETRYLATER;
+ }
+
+ if (offset >= BUFLEN) {
+ Msg1(level, "proxy answer exceeds "F_Zu" bytes, aborting", BUFLEN);
+ return STAT_NORETRY;
+ }
+
+ return STAT_OK;
+}
+
+#endif /* WITH_PROXY */
+
diff --git a/xio-proxy.h b/xio-proxy.h
new file mode 100644
index 0000000..bcaa054
--- /dev/null
+++ b/xio-proxy.h
@@ -0,0 +1,30 @@
+/* $Id: xio-proxy.h,v 1.6 2006/05/31 19:17:57 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2002-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_proxy_h_included
+#define __xio_proxy_h_included 1
+
+
+struct proxyvars {
+ bool ignorecr;
+ bool doresolve;
+ char *authstring;
+ char *targetaddr; /* name/address of host, in malloced string */
+ uint16_t targetport;
+} ;
+
+extern const struct optdesc opt_proxyport;
+extern const struct optdesc opt_ignorecr;
+extern const struct optdesc opt_proxy_resolve;
+extern const struct optdesc opt_proxy_authorization;
+
+extern const struct addrdesc addr_proxy_connect;
+
+int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts,
+ const char *targetname, const char *targetport);
+int _xioopen_proxy_connect(struct single *xfd,
+ struct proxyvars *proxyvars,
+ int level);
+
+#endif /* !defined(__xio_proxy_h_included) */
diff --git a/xio-pty.c b/xio-pty.c
new file mode 100644
index 0000000..c56f17e
--- /dev/null
+++ b/xio-pty.c
@@ -0,0 +1,212 @@
+/* $Id: xio-pty.c,v 1.20 2007/01/25 21:36:11 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2002-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for creating pty addresses */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-named.h"
+#include "xio-termios.h"
+
+
+#if WITH_PTY
+
+/* here define the preferred polling intervall, in seconds */
+#define PTY_INTERVALL 1,0 /* for struct timespec */
+
+#define MAXPTYNAMELEN 64
+
+static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
+
+const struct addrdesc addr_pty = { "pty", 3, xioopen_pty, GROUP_NAMED|GROUP_FD|GROUP_TERMIOS|GROUP_PTY, 0, 0, 0 HELP("") };
+
+const struct optdesc opt_symbolic_link = { "symbolic-link", "link", OPT_SYMBOLIC_LINK, GROUP_PTY, PH_LATE, TYPE_FILENAME, OFUNC_SPEC, 0, 0 };
+#if HAVE_POLL
+const struct optdesc opt_pty_wait_slave = { "pty-wait-slave", "wait-slave", OPT_PTY_WAIT_SLAVE, GROUP_PTY, PH_EARLY, TYPE_BOOL, OFUNC_SPEC, 0, 0 };
+const struct optdesc opt_pty_intervall = { "pty-intervall", NULL, OPT_PTY_INTERVALL, GROUP_PTY, PH_EARLY, TYPE_TIMESPEC, OFUNC_SPEC, 0, 0 };
+#endif /* HAVE_POLL */
+
+static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3) {
+ /* we expect the form: filename */
+ int ptyfd = -1, ttyfd = -1;
+#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
+ bool useptmx = false; /* use /dev/ptmx or equivalent */
+#endif
+#if HAVE_OPENPTY
+ bool useopenpty = false; /* try only openpty */
+#endif /* HAVE_OPENPTY */
+ char ptyname[MAXPTYNAMELEN];
+ char *tn = NULL;
+ char *linkname = NULL;
+ bool opt_unlink_close = true; /* remove symlink afterwards */
+ bool wait_slave = false; /* true would be better for many platforms, but
+ some OSes cannot handle this, and for common
+ default behaviour as well as backward
+ compatibility we choose "no" as default */
+ struct timespec pollintv = { PTY_INTERVALL };
+
+ xfd->stream.howtoend = END_CLOSE;
+
+ applyopts(-1, opts, PH_INIT);
+ if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
+
+ retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
+
+ /* trying to set user-early, perm-early etc. here might be useless because
+ file system entry is eventually available only past pty creation */
+ /* name not yet known; umask should not be handled with this function! */
+ /* umask does not affect resulting mode, on Linux 2.4 */
+ applyopts_named("", opts, PH_EARLY); /* umask! */
+
+#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
+ retropt_bool(opts, OPT_PTMX, &useptmx);
+#endif
+#if HAVE_OPENPTY
+ retropt_bool(opts, OPT_OPENPTY, &useopenpty);
+#endif
+
+#if (defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC))
+# if HAVE_OPENPTY
+ useopenpty = !useptmx;
+# else /* !HAVE_OPENPTY */
+ useptmx = true;
+# endif /* !HAVE_OPENPTY */
+#else
+ useopenpty = true;
+#endif /* ! (defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)) */
+
+#if HAVE_POLL
+ retropt_bool(opts, OPT_PTY_WAIT_SLAVE, &wait_slave);
+ retropt_timespec(opts, OPT_PTY_INTERVALL, &pollintv);
+#endif /* HAVE_POLL */
+
+ applyopts2(-1, opts, PH_INIT, PH_EARLY);
+ if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
+
+ applyopts(-1, opts, PH_PREBIGEN);
+
+#if defined(HAVE_DEV_PTMX)
+# define PTMX "/dev/ptmx" /* Linux */
+#elif HAVE_DEV_PTC
+# define PTMX "/dev/ptc" /* AIX 4.3.3 */
+#endif
+#if HAVE_DEV_PTMX || HAVE_DEV_PTC
+ if (useptmx) {
+ if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) {
+ Warn1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620): %s",
+ strerror(errno));
+ /*!*/
+ } else {
+ ;/*0 Info1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620) -> %d", ptyfd);*/
+ }
+ if (ptyfd >= 0 && ttyfd < 0) {
+ /* we used PTMX before forking */
+ /*0 extern char *ptsname(int);*/
+#if HAVE_GRANTPT /* AIX, not Linux */
+ if (Grantpt(ptyfd)/*!*/ < 0) {
+ Warn2("grantpt(%d): %s", ptyfd, strerror(errno));
+ }
+#endif /* HAVE_GRANTPT */
+#if HAVE_UNLOCKPT
+ if (Unlockpt(ptyfd)/*!*/ < 0) {
+ Warn2("unlockpt(%d): %s", ptyfd, strerror(errno));
+ }
+#endif /* HAVE_UNLOCKPT */
+#if HAVE_PTSNAME /* AIX, not Linux */
+ if ((tn = Ptsname(ptyfd)) == NULL) {
+ Warn2("ptsname(%d): %s", ptyfd, strerror(errno));
+ } else {
+ Notice1("PTY is %s", tn);
+ }
+#endif /* HAVE_PTSNAME */
+ if (tn == NULL) {
+ if ((tn = Ttyname(ptyfd)) == NULL) {
+ Warn2("ttyname(%d): %s", ptyfd, strerror(errno));
+ }
+ }
+ strncpy(ptyname, tn, MAXPTYNAMELEN);
+ }
+ }
+#endif /* HAVE_DEV_PTMX || HAVE_DEV_PTC */
+#if HAVE_OPENPTY
+ if (ptyfd < 0) {
+ int result;
+ if ((result = Openpty(&ptyfd, &ttyfd, ptyname, NULL, NULL)) < 0) {
+ Error4("openpty(%p, %p, %p, NULL, NULL): %s",
+ &ptyfd, &ttyfd, ptyname, strerror(errno));
+ return -1;
+ }
+ Notice1("PTY is %s", ptyname);
+ }
+#endif /* HAVE_OPENPTY */
+
+ if (!retropt_string(opts, OPT_SYMBOLIC_LINK, &linkname)) {
+ if (Unlink(linkname) < 0 && errno != ENOENT) {
+ Error2("unlink(\"%s\"): %s", linkname, strerror(errno));
+ }
+ if (Symlink(ptyname, linkname) < 0) {
+ Error3("symlink(\"%s\", \"%s\"): %s",
+ ptyname, linkname, strerror(errno));
+ }
+ if (opt_unlink_close) {
+ if ((xfd->stream.unlink_close = strdup(linkname)) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", linkname);
+ }
+ xfd->stream.opt_unlink_close = true;
+ }
+ }
+
+ applyopts_named(ptyname, opts, PH_PASTOPEN);
+ applyopts_named(ptyname, opts, PH_FD);
+
+ applyopts_cloexec(ptyfd, opts);/*!*/
+ xfd->stream.dtype = XIODATA_PTY;
+
+ applyopts(ptyfd, opts, PH_FD);
+
+ xfd->stream.fd = ptyfd;
+ applyopts(ptyfd, opts, PH_LATE);
+ if (applyopts_single(&xfd->stream, opts, PH_LATE) < 0) return -1;
+
+#if HAVE_POLL
+ /* if you can and wish: */
+ if (wait_slave) {
+ /* try to wait until someone opens the slave side of the pty */
+ /* we want to get a HUP (hangup) condition on the pty */
+#if HAVE_DEV_PTMX || HAVE_DEV_PTC
+ if (useptmx) {
+ ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620);
+ Close(ttyfd);
+ }
+#endif
+#if HAVE_OPENPTY
+ if (useopenpty) {
+ Close(ttyfd);
+ }
+#endif /* HAVE_OPENPTY */
+
+ /* now we poll until the HUP vanishes - this indicates a slave conn. */
+ while (true) {
+ struct pollfd ufd;
+ ufd.fd = ptyfd;
+ ufd.events = (POLLHUP);
+ if (Poll(&ufd, 1, 0) < 0) {
+ Error3("poll({%d, 0x%04hu,}, 1, 0): %s",
+ ufd.fd, ufd.events, strerror(errno));
+ /*! close something */
+ return -1;
+ }
+ if (!(ufd.revents & POLLHUP)) {
+ break;
+ }
+ Nanosleep(&pollintv, NULL);
+ continue;
+ }
+ }
+#endif /* HAVE_POLL */
+
+ return STAT_OK;
+}
+#endif /* WITH_PTY */
diff --git a/xio-pty.h b/xio-pty.h
new file mode 100644
index 0000000..1d77414
--- /dev/null
+++ b/xio-pty.h
@@ -0,0 +1,16 @@
+/* $Id: xio-pty.h,v 1.2 2004/10/24 13:49:53 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2002-2004 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_pty_h_included
+#define __xio_pty_h_included 1
+
+extern const struct addrdesc addr_pty;
+
+extern const struct optdesc opt_symbolic_link;
+#if HAVE_POLL
+extern const struct optdesc opt_pty_wait_slave;
+extern const struct optdesc opt_pty_intervall;
+#endif /* HAVE_POLL */
+
+#endif /* !defined(__xio_pty_h_included) */
diff --git a/xio-rawip.c b/xio-rawip.c
new file mode 100644
index 0000000..187942f
--- /dev/null
+++ b/xio-rawip.c
@@ -0,0 +1,303 @@
+/* $Id: xio-rawip.c,v 1.32 2007/02/05 19:56:34 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of raw IP type */
+
+#include "xiosysincludes.h"
+
+#if (WITH_IP4 || WITH_IP6) && WITH_RAWIP
+
+#include "xioopen.h"
+#include "xio-socket.h"
+#include "xio-ip.h"
+#include "xio-ip6.h"
+#include "xio-tcpwrap.h"
+
+#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,
+ int dummy2, int dummy3);
+static
+int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *fd, unsigned groups, int pf,
+ int dummy2, int dummy3);
+static
+int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xfd, unsigned groups,
+ int pf, int dummy2, int dummy3);
+static
+int xioopen_rawip_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_rawip_sendto(const char *hostname, const char *protname,
+ struct opt *opts, int xioflags,
+ xiofile_t *xxfd, unsigned groups, int pf);
+
+const struct addrdesc addr_rawip_sendto = { "ip-sendto", 3, xioopen_rawip_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc addr_rawip_datagram= { "ip-datagram", 3, xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc addr_rawip_recvfrom= { "ip-recvfrom", 3, xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, SOCK_RAW, 0 HELP(":<protocol>") };
+const struct addrdesc addr_rawip_recv = { "ip-recv", 1, xioopen_rawip_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE, PF_UNSPEC, SOCK_RAW, 0 HELP(":<protocol>") };
+
+#if WITH_IP4
+const struct addrdesc addr_rawip4_sendto = { "ip4-sendto", 3, xioopen_rawip_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4, PF_INET, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc addr_rawip4_datagram= { "ip4-datagram", 3, xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_RANGE, PF_INET, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc addr_rawip4_recvfrom= { "ip4-recvfrom", 3, xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_CHILD|GROUP_RANGE, PF_INET, SOCK_RAW, 0 HELP(":<protocol>") };
+const struct addrdesc addr_rawip4_recv = { "ip4-recv", 1, xioopen_rawip_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_RANGE, PF_INET, SOCK_RAW, 0 HELP(":<protocol>") };
+#endif
+
+#if WITH_IP6
+const struct addrdesc addr_rawip6_sendto = { "ip6-sendto", 3, xioopen_rawip_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6, PF_INET6, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc addr_rawip6_datagram= { "ip6-datagram", 3, xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_RANGE, PF_INET6, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc addr_rawip6_recvfrom= { "ip6-recvfrom", 3, xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_CHILD|GROUP_RANGE, PF_INET6, SOCK_RAW, 0 HELP(":<protocol>") };
+const struct addrdesc addr_rawip6_recv = { "ip6-recv", 1, xioopen_rawip_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_RANGE, PF_INET6, SOCK_RAW, 0 HELP(":<protocol>") };
+#endif
+
+
+/* we expect the form: host:protocol */
+/* struct sockaddr_in sa;*/
+/* socklen_t salen;*/
+static
+int xioopen_rawip_sendto(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xxfd, unsigned groups,
+ int pf, int dummy2, int dummy3) {
+ int result;
+
+ if (argc != 3) {
+ Error2("%s: wrong number of parameters (%d instead of 2)",
+ argv[0], argc-1);
+ return STAT_NORETRY;
+ }
+ if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
+ groups, pf)) != STAT_OK) {
+ return result;
+ }
+ _xio_openlate(&xxfd->stream, opts);
+ return STAT_OK;
+}
+
+static
+int _xioopen_rawip_sendto(const char *hostname, const char *protname,
+ struct opt *opts, int xioflags, xiofile_t *xxfd,
+ unsigned groups, int pf) {
+ char *garbage;
+ xiosingle_t *xfd = &xxfd->stream;
+ union sockaddr_union us;
+ socklen_t uslen;
+ int feats = 1; /* option bind supports only address, not port */
+ int socktype = SOCK_RAW;
+ int ipproto;
+ bool needbind = false;
+ int result;
+
+ if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) {
+ Error3("xioopen_rawip_sendto(\"%s:%s\",,): protocol number exceeds 255 (%u)",
+ hostname, protname, ipproto);
+ return STAT_NORETRY;
+ } else if (*garbage) {
+ Warn2("xioopen_rawip_sendto(\"%s:%s\",,): trailing garbage in protocol specification",
+ hostname, protname);
+ /*return STAT_NORETRY;*/
+ }
+
+ xfd->howtoend = END_SHUTDOWN;
+ retropt_int(opts, OPT_SO_TYPE, &socktype);
+
+ /* ...res_opts[] */
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ xfd->salen = sizeof(xfd->peersa);
+ if ((result =
+ 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;
+ }
+
+ uslen = socket_init(pf, &us);
+
+ xfd->dtype = XIODATA_RECVFROM_SKIPIP;
+
+ 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);
+}
+
+
+/* we expect the form: address:protocol */
+static
+int xioopen_rawip_datagram(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xxfd, unsigned groups,
+ int pf, int dummy2, int dummy3) {
+ xiosingle_t *xfd = &xxfd->stream;
+ char *rangename;
+ int result;
+
+ if (argc != 3) {
+ Error2("%s: wrong number of parameters (%d instead of 2)",
+ argv[0], argc-1);
+ return STAT_NORETRY;
+ }
+ if ((result =
+ _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
+ groups, pf)) != STAT_OK) {
+ return result;
+ }
+
+ xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
+ if (pf == PF_INET) {
+ xfd->dtype |= XIOREAD_RECV_SKIPIP;
+ }
+
+ xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family;
+
+ /* 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) {
+ free(rangename);
+ return STAT_NORETRY;
+ }
+ xfd->para.socket.dorange = true;
+ xfd->dtype |= XIOREAD_RECV_CHECKRANGE;
+ free(rangename);
+ }
+
+#if WITH_LIBWRAP
+ xio_retropt_tcpwrap(xfd, opts);
+#endif /* WITH_LIBWRAP */
+
+ _xio_openlate(xfd, opts);
+ return STAT_OK;
+}
+
+
+static
+int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xfd, unsigned groups,
+ int pf, int socktype, int dummy3) {
+ const char *protname = argv[1];
+ char *garbage;
+ union sockaddr_union us;
+ socklen_t uslen = sizeof(us);
+ int ipproto;
+ 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;
+ }
+
+ if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) {
+ Error2("xioopen_rawip_recvfrom(\"%s\",,): protocol number exceeds 255 (%u)",
+ protname, ipproto);
+ return STAT_NORETRY;
+ } else if (*garbage) {
+ Warn1("xioopen_rawip_recvfrom(\"%s\",,): trailing garbage in protocol specification",
+ protname);
+ /*return STAT_NORETRY;*/
+ }
+ xfd->stream.howtoend = END_NONE;
+ retropt_int(opts, OPT_SO_TYPE, &socktype);
+
+ retropt_socket_pf(opts, &pf);
+ if (pf == PF_UNSPEC) {
+#if WITH_IP4 && WITH_IP6
+ pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
+#elif WITH_IP6
+ pf = PF_INET6;
+#else
+ pf = PF_INET;
+#endif
+ }
+
+ if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, 1,
+ xfd->stream.para.socket.ip.res_opts[0],
+ xfd->stream.para.socket.ip.res_opts[1]) != STAT_NOACTION) {
+ needbind = true;
+ }
+
+ xfd->stream.dtype = XIODATA_RECVFROM_SKIPIP_ONE;
+ if ((result =
+ _xioopen_dgram_recvfrom(&xfd->stream, xioflags, needbind?&us.soa:NULL,
+ uslen, opts, pf, socktype, ipproto, E_ERROR))
+ != STAT_OK) {
+ return result;
+ }
+ _xio_openlate(&xfd->stream, opts);
+ return STAT_OK;
+}
+
+
+static
+int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xfd, unsigned groups,
+ int pf, int socktype, int ipproto) {
+ const char *protname = argv[1];
+ char *garbage;
+ union sockaddr_union us;
+ socklen_t uslen = sizeof(us);
+ int result;
+
+ if (argc != 2) {
+ Error2("%s: wrong number of parameters (%d instead of 1)",
+ argv[0], argc-1);
+ return STAT_NORETRY;
+ }
+
+ if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) {
+ Error2("xioopen_rawip_recvfrom(\"%s\",,): protocol number exceeds 255 (%u)",
+ protname, ipproto);
+ return STAT_NORETRY;
+ } else if (*garbage) {
+ Warn1("xioopen_rawip_recvfrom(\"%s\",,): trailing garbage in protocol specification",
+ protname);
+ /*return STAT_NORETRY;*/
+ }
+ retropt_int(opts, OPT_SO_TYPE, &socktype);
+
+ retropt_socket_pf(opts, &pf);
+ if (pf == PF_UNSPEC) {
+#if WITH_IP4 && WITH_IP6
+ pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
+#elif WITH_IP6
+ pf = PF_INET6;
+#else
+ pf = PF_INET;
+#endif
+ }
+
+ if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, 1,
+ xfd->stream.para.socket.ip.res_opts[0],
+ xfd->stream.para.socket.ip.res_opts[1]) !=
+ STAT_OK) {
+ /* pf is required during xioread checks */
+ xfd->stream.para.socket.la.soa.sa_family = pf;
+ }
+
+ xfd->stream.dtype = XIODATA_RECV_SKIPIP;
+ result = _xioopen_dgram_recv(&xfd->stream, xioflags, NULL/*&us.soa*/, uslen,
+ opts, pf, socktype, ipproto, E_ERROR);
+ _xio_openlate(&xfd->stream, opts);
+ return result;
+}
+
+#endif /* (WITH_IP4 || WITH_IP6) && WITH_RAWIP */
diff --git a/xio-rawip.h b/xio-rawip.h
new file mode 100644
index 0000000..0c57a02
--- /dev/null
+++ b/xio-rawip.h
@@ -0,0 +1,21 @@
+/* $Id: xio-rawip.h,v 1.13 2007/02/05 19:56:34 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_rawip_h_included
+#define __xio_rawip_h_included 1
+
+extern const struct addrdesc addr_rawip_sendto;
+extern const struct addrdesc addr_rawip_datagram;
+extern const struct addrdesc addr_rawip_recvfrom;
+extern const struct addrdesc addr_rawip_recv;
+extern const struct addrdesc addr_rawip4_sendto;
+extern const struct addrdesc addr_rawip4_datagram;
+extern const struct addrdesc addr_rawip4_recvfrom;
+extern const struct addrdesc addr_rawip4_recv;
+extern const struct addrdesc addr_rawip6_sendto;
+extern const struct addrdesc addr_rawip6_datagram;
+extern const struct addrdesc addr_rawip6_recvfrom;
+extern const struct addrdesc addr_rawip6_recv;
+
+#endif /* !defined(__xio_rawip_h_included) */
diff --git a/xio-readline.c b/xio-readline.c
new file mode 100644
index 0000000..584543f
--- /dev/null
+++ b/xio-readline.c
@@ -0,0 +1,244 @@
+/* $Id: xio-readline.c,v 1.17 2007/01/25 21:36:11 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2002-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening the readline address */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-termios.h"
+#include "xio-readline.h"
+
+
+#if WITH_READLINE
+
+/*
+options: history file
+ prompt
+ mode=vi?
+ inputrc=?
+
+uses stdin!!
+*/
+
+/* length of buffer for dynamic prompt */
+#define READLINE_MAXPROMPT 512
+
+static int xioopen_readline(int argc, const char *argv[], struct opt *opts,
+ int rw, xiofile_t *xfd, unsigned groups,
+ int dummy1, int dummy2, int dummy3);
+
+
+const struct addrdesc addr_readline = {
+ "readline", 3, xioopen_readline, GROUP_FD|GROUP_TERMIOS|GROUP_READLINE, 0, 0, 0 HELP(NULL) };
+
+const struct optdesc opt_history_file = { "history-file", "history", OPT_HISTORY_FILE, GROUP_READLINE, PH_LATE, TYPE_STRING, OFUNC_OFFSET, (int)&((xiofile_t *)0)->stream.para.readline.history_file };
+const struct optdesc opt_prompt = { "prompt", NULL, OPT_PROMPT, GROUP_READLINE, PH_LATE, TYPE_STRING, OFUNC_OFFSET, (int)&((xiofile_t *)0)->stream.para.readline.prompt };
+const struct optdesc opt_noprompt = { "noprompt", NULL, OPT_NOPROMPT, GROUP_READLINE, PH_LATE, TYPE_BOOL, OFUNC_SPEC, 0 };
+const struct optdesc opt_noecho = { "noecho", NULL, OPT_NOECHO, GROUP_READLINE, PH_LATE, TYPE_STRING, OFUNC_SPEC, 0 };
+
+static int xioopen_readline(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xfd, unsigned groups,
+ int dummy1, int dummy2, int dummy3) {
+ int rw = (xioflags & XIO_ACCMODE);
+ char msgbuf[256], *cp = msgbuf;
+ bool noprompt = false;
+ char *noecho = NULL;
+
+ if (argc != 1) {
+ Error1("%s: 0 parameters required", argv[0]);
+ return STAT_NORETRY;
+ }
+
+ if (!(xioflags & XIO_MAYCONVERT)) {
+ Error("address with data processing not allowed here");
+ return STAT_NORETRY;
+ }
+ xfd->common.flags |= XIO_DOESCONVERT;
+
+ strcpy(cp, "using "); cp = strchr(cp, '\0');
+ if ((rw+1)&1) {
+ strcpy(cp, "readline on stdin for reading"); cp = strchr(cp, '\0');
+
+ if ((rw+1)&2)
+ strcpy(cp, " and "); cp = strchr(cp, '\0');
+ }
+ if ((rw+1)&2) {
+ strcpy(cp, "stdio for writing"); cp = strchr(cp, '\0');
+ }
+ Notice(msgbuf);
+
+ xfd->stream.fd = 0; /* stdin */
+ xfd->stream.howtoend = END_NONE;
+ xfd->stream.dtype = XIODATA_READLINE;
+
+#if WITH_TERMIOS
+ if (Isatty(xfd->stream.fd)) {
+ if (Tcgetattr(xfd->stream.fd, &xfd->stream.savetty) < 0) {
+ Warn2("cannot query current terminal settings on fd %d. %s",
+ xfd->stream.fd, strerror(errno));
+ } else {
+ xfd->stream.ttyvalid = true;
+ }
+ }
+#endif /* WITH_TERMIOS */
+
+ if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ applyopts2(xfd->stream.fd, opts, PH_INIT, PH_FD);
+
+ Using_history();
+ applyopts_offset(&xfd->stream, opts);
+ retropt_bool(opts, OPT_NOPROMPT, &noprompt);
+ if (!noprompt && !xfd->stream.para.readline.prompt) {
+ xfd->stream.para.readline.dynbytes = READLINE_MAXPROMPT;
+ xfd->stream.para.readline.dynprompt =
+ Malloc(xfd->stream.para.readline.dynbytes+1);
+ xfd->stream.para.readline.dynend =
+ xfd->stream.para.readline.dynprompt;
+ }
+
+#if HAVE_REGEX_H
+ retropt_string(opts, OPT_NOECHO, &noecho);
+ if (noecho) {
+ int errcode;
+ char errbuf[128];
+ if ((errcode = regcomp(&xfd->stream.para.readline.noecho, noecho,
+ REG_EXTENDED|REG_NOSUB))
+ != 0) {
+ regerror(errcode, &xfd->stream.para.readline.noecho,
+ errbuf, sizeof(errbuf));
+ Error3("regcomp(%p, \"%s\", REG_EXTENDED|REG_NOSUB): %s",
+ &xfd->stream.para.readline.noecho, noecho, errbuf);
+ return -1;
+ }
+ xfd->stream.para.readline.hasnoecho = true;
+ }
+#endif /* HAVE_REGEX_H */
+ if (xfd->stream.para.readline.history_file) {
+ Read_history(xfd->stream.para.readline.history_file);
+ }
+ xiotermios_clrflag(xfd->stream.fd, 3, ICANON);
+ xiotermios_clrflag(xfd->stream.fd, 3, ECHO);
+ return _xio_openlate(&xfd->stream, opts);
+}
+
+
+ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz) {
+ /*! indent */
+ ssize_t bytes;
+ char *line;
+ int _errno;
+
+#if HAVE_REGEX_H
+ if (pipe->para.readline.dynprompt &&
+ pipe->para.readline.hasnoecho &&
+ !regexec(&pipe->para.readline.noecho,
+ pipe->para.readline.dynprompt, 0, NULL, 0)) {
+ /* under these conditions, we do not echo input, thus we circumvent
+ readline */
+ struct termios saveterm, setterm;
+ *pipe->para.readline.dynend = '\0';
+ Tcgetattr(pipe->fd, &saveterm); /*! error */
+ setterm = saveterm;
+ setterm.c_lflag |= ICANON;
+ Tcsetattr(pipe->fd, TCSANOW, &setterm); /*!*/
+ do {
+ bytes = Read(pipe->fd, buff, bufsiz);
+ } while (bytes < 0 && errno == EINTR);
+ if (bytes < 0) {
+ _errno = errno;
+ Error4("read(%d, %p, "F_Zu"): %s",
+ pipe->fd, buff, bufsiz, strerror(_errno));
+ errno = _errno;
+ return -1;
+ }
+ setterm.c_lflag &= ~ICANON;
+ Tcgetattr(pipe->fd, &setterm); /*! error */
+ Tcsetattr(pipe->fd, TCSANOW, &saveterm); /*!*/
+ pipe->para.readline.dynend = pipe->para.readline.dynprompt;
+ /*Write(pipe->fd, "\n", 1);*/ /*!*/
+ return bytes;
+ }
+#endif /* HAVE_REGEX_H */
+
+ xiotermios_setflag(pipe->fd, 3, ECHO);
+ if (pipe->para.readline.prompt || pipe->para.readline.dynprompt) {
+ /* we must carriage return, because readline will first print the
+ prompt */
+ ssize_t writt;
+ do {
+ writt = Write(pipe->fd, "\r", 1);
+ } while (writt < 0 && errno == EINTR);
+ if (writt < 0) {
+ Warn2("write(%d, \"\\r\", 1): %s",
+ pipe->fd, strerror(errno));
+ } else if (writt < 1) {
+ Warn1("write() only wrote "F_Zu" of 1 byte", writt);
+ }
+ }
+
+ if (pipe->para.readline.dynprompt) {
+ *pipe->para.readline.dynend = '\0';
+ line = Readline(pipe->para.readline.dynprompt);
+ pipe->para.readline.dynend = pipe->para.readline.dynprompt;
+ } else {
+ line = Readline(pipe->para.readline.prompt);
+ }
+ /* GNU readline defines no error return */
+ if (line == NULL) {
+ return 0; /* EOF */
+ }
+ xiotermios_clrflag(pipe->fd, 3, ECHO);
+ Add_history(line);
+ bytes = strlen(line);
+ strncpy(buff, line, bufsiz);
+ free(line);
+ if ((size_t)bytes < bufsiz) {
+ strcat(buff, "\n"); ++bytes;
+ }
+ return bytes;
+}
+
+void xioscan_readline(struct single *pipe, const void *buff, size_t bytes) {
+ if (pipe->dtype == XIODATA_READLINE && pipe->para.readline.dynprompt) {
+ /* we save the last part of the output as possible prompt */
+ const void *ptr = buff;
+ const void *pcr = memrchr(buff, '\r', bytes);
+ const void *plf = memrchr(buff, '\n', bytes);
+ size_t len;
+ if (bytes > pipe->para.readline.dynbytes) {
+ ptr = (const char *)buff + bytes - pipe->para.readline.dynbytes;
+ }
+ if (pcr) {
+ /* forget old prompt */
+ pipe->para.readline.dynend = pipe->para.readline.dynprompt;
+ /* new prompt starts here */
+ ptr = (const char *)pcr+1;
+ }
+ if (plf && plf >= ptr) {
+ /* forget old prompt */
+ pipe->para.readline.dynend = pipe->para.readline.dynprompt;
+ /* new prompt starts here */
+ ptr = (const char *)plf+1;
+ }
+ len = (const char *)buff-(const char *)ptr+bytes;
+ if (pipe->para.readline.dynend - pipe->para.readline.dynprompt + len >
+ pipe->para.readline.dynbytes) {
+ memmove(pipe->para.readline.dynprompt,
+ pipe->para.readline.dynend -
+ (pipe->para.readline.dynbytes - len),
+ pipe->para.readline.dynbytes - len);
+ pipe->para.readline.dynend =
+ pipe->para.readline.dynprompt + pipe->para.readline.dynbytes - len;
+ }
+ memcpy(pipe->para.readline.dynend, ptr, len);
+ /*pipe->para.readline.dynend = pipe->para.readline.dynprompt + len;*/
+ pipe->para.readline.dynend = pipe->para.readline.dynend + len;
+ }
+ return;
+}
+
+#endif /* WITH_READLINE */
diff --git a/xio-readline.h b/xio-readline.h
new file mode 100644
index 0000000..921d605
--- /dev/null
+++ b/xio-readline.h
@@ -0,0 +1,17 @@
+/* $Id: xio-readline.h,v 1.4 2003/12/23 21:38:59 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2002, 2003 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_readline_h_included
+#define __xio_readline_h_included 1
+
+extern const struct addrdesc addr_readline;
+
+extern const struct optdesc opt_history_file;
+extern const struct optdesc opt_prompt;
+extern const struct optdesc opt_noprompt;
+extern const struct optdesc opt_noecho;
+
+extern ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz);extern void xioscan_readline(struct single *pipe, const void *buff, size_t bytes);
+
+#endif /* !defined(__xio_readline_h_included) */
diff --git a/xio-socket.c b/xio-socket.c
new file mode 100644
index 0000000..c9b3d3e
--- /dev/null
+++ b/xio-socket.c
@@ -0,0 +1,1091 @@
+/* $Id: xio-socket.c,v 1.45 2007/03/06 21:12:09 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for socket related functions */
+
+#include "xiosysincludes.h"
+
+#if _WITH_SOCKET
+
+#include "xioopen.h"
+#include "xio-socket.h"
+#include "xio-named.h"
+#if WITH_IP4
+#include "xio-ip4.h"
+#endif /* WITH_IP4 */
+#if WITH_IP6
+#include "xio-ip6.h"
+#endif /* WITH_IP6 */
+#include "xio-ip.h"
+#include "xio-ipapp.h" /*! not clean */
+#include "xio-tcpwrap.h"
+
+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};
+#endif /* SO_ACCEPTCONN */
+const struct optdesc opt_so_broadcast= { "so-broadcast", "broadcast", OPT_SO_BROADCAST,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_BROADCAST};
+const struct optdesc opt_so_reuseaddr= { "so-reuseaddr", "reuseaddr", OPT_SO_REUSEADDR,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_REUSEADDR};
+const struct optdesc opt_so_keepalive= { "so-keepalive", "keepalive", OPT_SO_KEEPALIVE,GROUP_SOCKET, PH_FD, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_KEEPALIVE};
+#if HAVE_STRUCT_LINGER
+const struct optdesc opt_so_linger = { "so-linger", "linger", OPT_SO_LINGER, GROUP_SOCKET, PH_PASTSOCKET, TYPE_LINGER,OFUNC_SOCKOPT,SOL_SOCKET, SO_LINGER };
+#else /* !HAVE_STRUCT_LINGER */
+const struct optdesc opt_so_linger = { "so-linger", "linger", OPT_SO_LINGER, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_LINGER };
+#endif /* !HAVE_STRUCT_LINGER */
+const struct optdesc opt_so_oobinline= { "so-oobinline", "oobinline", OPT_SO_OOBINLINE,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_OOBINLINE};
+const struct optdesc opt_so_sndbuf = { "so-sndbuf", "sndbuf", OPT_SO_SNDBUF, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_SNDBUF};
+const struct optdesc opt_so_sndbuf_late={ "so-sndbuf-late","sndbuf-late",OPT_SO_SNDBUF_LATE,GROUP_SOCKET,PH_LATE,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SNDBUF };
+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_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 };
+#endif
+#ifdef SO_RCVTIMEO
+const struct optdesc opt_so_rcvtimeo = { "so-rcvtimeo", "rcvtimeo", OPT_SO_RCVTIMEO, GROUP_SOCKET, PH_PASTSOCKET, TYPE_TIMEVAL,OFUNC_SOCKOPT,SOL_SOCKET,SO_RCVTIMEO };
+#endif
+#ifdef SO_SNDLOWAT
+const struct optdesc opt_so_sndlowat = { "so-sndlowat", "sndlowat", OPT_SO_SNDLOWAT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_SNDLOWAT };
+#endif
+#ifdef SO_SNDTIMEO
+const struct optdesc opt_so_sndtimeo = { "so-sndtimeo", "sndtimeo", OPT_SO_SNDTIMEO, GROUP_SOCKET, PH_PASTSOCKET, TYPE_TIMEVAL,OFUNC_SOCKOPT,SOL_SOCKET,SO_SNDTIMEO };
+#endif
+/* end of setsockopt options of UNIX98 standard */
+
+#ifdef SO_AUDIT /* AIX 4.3.3 */
+const struct optdesc opt_so_audit = { "so-audit", "audit", OPT_SO_AUDIT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_AUDIT };
+#endif /* SO_AUDIT */
+#ifdef SO_ATTACH_FILTER
+const struct optdesc opt_so_attach_filter={"so-attach-filter","attachfilter",OPT_SO_ATTACH_FILTER,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_ATTACH_FILTER};
+#endif
+#ifdef SO_DETACH_FILTER
+const struct optdesc opt_so_detach_filter={"so-detach-filter","detachfilter",OPT_SO_DETACH_FILTER,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DETACH_FILTER};
+#endif
+#ifdef SO_BINDTODEVICE /* Linux: man 7 socket */
+const struct optdesc opt_so_bindtodevice={"so-bindtodevice","if",OPT_SO_BINDTODEVICE,GROUP_SOCKET,PH_PASTSOCKET,TYPE_NAME,OFUNC_SOCKOPT,SOL_SOCKET,SO_BINDTODEVICE};
+#endif
+#ifdef SO_BSDCOMPAT
+const struct optdesc opt_so_bsdcompat= { "so-bsdcompat","bsdcompat",OPT_SO_BSDCOMPAT,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_BSDCOMPAT };
+#endif
+#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_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 */
+#ifdef SO_NO_CHECK
+const struct optdesc opt_so_no_check = { "so-no-check", "nocheck",OPT_SO_NO_CHECK, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_NO_CHECK };
+#endif
+#ifdef SO_NOREUSEADDR /* AIX 4.3.3 */
+const struct optdesc opt_so_noreuseaddr={"so-noreuseaddr","noreuseaddr",OPT_SO_NOREUSEADDR,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET, SO_NOREUSEADDR};
+#endif /* SO_NOREUSEADDR */
+#ifdef SO_PASSCRED
+const struct optdesc opt_so_passcred = { "so-passcred", "passcred", OPT_SO_PASSCRED, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_PASSCRED};
+#endif
+#ifdef SO_PEERCRED
+const struct optdesc opt_so_peercred = { "so-peercred", "peercred", OPT_SO_PEERCRED, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT3,OFUNC_SOCKOPT, SOL_SOCKET, SO_PEERCRED};
+#endif
+#ifdef SO_PRIORITY
+const struct optdesc opt_so_priority = { "so-priority", "priority", OPT_SO_PRIORITY, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_PRIORITY};
+#endif
+#ifdef SO_REUSEPORT /* AIX 4.3.3, BSD, HP-UX */
+const struct optdesc opt_so_reuseport= { "so-reuseport","reuseport",OPT_SO_REUSEPORT,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_REUSEPORT };
+#endif /* defined(SO_REUSEPORT) */
+#ifdef SO_SECURITY_AUTHENTICATION
+const struct optdesc opt_so_security_authentication={"so-security-authentication","securityauthentication",OPT_SO_SECURITY_AUTHENTICATION,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_AUTHENTICATION};
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_NETWORK
+const struct optdesc opt_so_security_encryption_network={"so-security-encryption-network","securityencryptionnetwork",OPT_SO_SECURITY_ENCRYPTION_NETWORK,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_ENCRYPTION_NETWORK};
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
+const struct optdesc opt_so_security_encryption_transport={"so-security-encryption-transport","securityencryptiontransport",OPT_SO_SECURITY_ENCRYPTION_TRANSPORT,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_ENCRYPTION_TRANSPORT};
+#endif
+#ifdef SO_USE_IFBUFS
+const struct optdesc opt_so_use_ifbufs={ "so-use-ifbufs","useifbufs",OPT_SO_USE_IFBUFS,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_USE_IFBUFS};
+#endif /* SO_USE_IFBUFS */
+#ifdef SO_USELOOPBACK /* AIX433, Solaris, HP-UX */
+const struct optdesc opt_so_useloopback={"so-useloopback","useloopback",OPT_SO_USELOOPBACK,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT, SOL_SOCKET, SO_USELOOPBACK};
+#endif /* SO_USELOOPBACK */
+#ifdef SO_DGRAM_ERRIND /* Solaris */
+const struct optdesc opt_so_dgram_errind={"so-dgram-errind","dgramerrind",OPT_SO_DGRAM_ERRIND,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DGRAM_ERRIND};
+#endif /* SO_DGRAM_ERRIND */
+#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
+#ifdef FIOSETOWN
+const struct optdesc opt_fiosetown = { "fiosetown", NULL, OPT_FIOSETOWN, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_IOCTL, FIOSETOWN };
+#endif
+#ifdef SIOCSPGRP
+const struct optdesc opt_siocspgrp = { "siocspgrp", NULL, OPT_SIOCSPGRP, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_IOCTL, SIOCSPGRP };
+#endif
+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 };
+
+/* a subroutine that is common to all socket addresses that want to connect
+ to a peer address.
+ might fork.
+ 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,
+ bool alt, int level) {
+ int fcntl_flags = 0;
+ char infobuff[256];
+ union sockaddr_union la;
+ socklen_t lalen = themlen;
+ int _errno;
+ int result;
+
+ if ((xfd->fd = Socket(pf, stype, proto)) < 0) {
+ Msg4(level,
+ "socket(%d, %d, %d): %s", pf, stype, proto, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+
+ applyopts_offset(xfd, opts);
+ applyopts(xfd->fd, opts, PH_PASTSOCKET);
+ applyopts(xfd->fd, opts, PH_FD);
+
+ applyopts_cloexec(xfd->fd, opts);
+
+ applyopts(xfd->fd, opts, PH_PREBIND);
+ applyopts(xfd->fd, opts, PH_BIND);
+#if WITH_TCP || WITH_UDP
+ if (alt) {
+ union sockaddr_union sin, *sinp;
+ unsigned short *port, i, N;
+ div_t dv;
+ bool problem;
+
+ /* prepare sockaddr for bind probing */
+ if (us) {
+ sinp = (union sockaddr_union *)us;
+ } else {
+ if (them->sa_family == AF_INET) {
+ socket_in_init(&sin.ip4);
+#if WITH_IP6
+ } else {
+ socket_in6_init(&sin.ip6);
+#endif
+ }
+ sinp = &sin;
+ }
+ if (them->sa_family == AF_INET) {
+ port = &sin.ip4.sin_port;
+#if WITH_IP6
+ } else if (them->sa_family == AF_INET6) {
+ port = &sin.ip6.sin6_port;
+#endif
+ } else {
+ port = 0; /* just to make compiler happy */
+ }
+ /* combine random+step variant to quickly find a free port when only
+ few are in use, and certainly find a free port in defined time even
+ if there are almost all in use */
+ /* dirt 1: having tcp/udp code in socket function */
+ /* dirt 2: using a time related system call for init of random */
+ {
+ /* generate a random port, with millisecond random init */
+#if 0
+ struct timeb tb;
+ ftime(&tb);
+ srandom(tb.time*1000+tb.millitm);
+#else
+ struct timeval tv;
+ struct timezone tz;
+ tz.tz_minuteswest = 0;
+ tz.tz_dsttime = 0;
+ if ((result = Gettimeofday(&tv, &tz)) < 0) {
+ Warn2("gettimeofday(%p, {0,0}): %s", &tv, strerror(errno));
+ }
+ srandom(tv.tv_sec*1000000+tv.tv_usec);
+#endif
+ }
+ dv = div(random(), IPPORT_RESERVED-XIO_IPPORT_LOWER);
+ i = N = XIO_IPPORT_LOWER + dv.rem;
+ problem = false;
+ do { /* loop over lowport bind() attempts */
+ *port = htons(i);
+ if (Bind(xfd->fd, (struct sockaddr *)sinp, sizeof(*sinp)) < 0) {
+ Msg4(errno==EADDRINUSE?E_INFO:level,
+ "bind(%d, {%s}, "F_Zd"): %s", xfd->fd,
+ sockaddr_info(&sinp->soa, sizeof(*sinp), infobuff, sizeof(infobuff)),
+ sizeof(*sinp), strerror(errno));
+ if (errno != EADDRINUSE) {
+ Close(xfd->fd);
+ return STAT_RETRYLATER;
+ }
+ } else {
+ break; /* could bind to port, good, continue past loop */
+ }
+ --i; if (i < XIO_IPPORT_LOWER) i = IPPORT_RESERVED-1;
+ if (i == N) {
+ Msg(level, "no low port available");
+ /*errno = EADDRINUSE; still assigned */
+ Close(xfd->fd);
+ return STAT_RETRYLATER;
+ }
+ } while (i != N);
+ } else
+#endif /* WITH_TCP || WITH_UDP */
+
+ if (us) {
+ if (Bind(xfd->fd, us, uslen) < 0) {
+ Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
+ xfd->fd, sockaddr_info(us, uslen, infobuff, sizeof(infobuff)),
+ uslen, strerror(errno));
+ Close(xfd->fd);
+ return STAT_RETRYLATER;
+ }
+ }
+
+ applyopts(xfd->fd, opts, PH_PASTBIND);
+
+ applyopts(xfd->fd, opts, PH_CONNECT);
+
+ if (xfd->para.socket.connect_timeout.tv_sec != 0 ||
+ xfd->para.socket.connect_timeout.tv_usec != 0) {
+ fcntl_flags = Fcntl(xfd->fd, F_GETFL);
+ Fcntl_l(xfd->fd, F_SETFL, fcntl_flags|O_NONBLOCK);
+ }
+
+ result = Connect(xfd->fd, (struct sockaddr *)them, themlen);
+ _errno = errno;
+ la.soa.sa_family = them->sa_family; lalen = sizeof(la);
+ if (Getsockname(xfd->fd, &la.soa, &lalen) < 0) {
+ Msg4(level-1, "getsockname(%d, %p, {%d}): %s",
+ xfd->fd, &la.soa, lalen, strerror(errno));
+ }
+ errno = _errno;
+ if (result < 0) {
+ if (errno == EINPROGRESS) {
+ 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;
+ int result;
+ Info4("connect(%d, %s, "F_Zd"): %s",
+ xfd->fd, 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->fd, &readfds); FD_SET(xfd->fd, &writefds);
+ result =
+ Select(xfd->fd+1, &readfds, &writefds, &exceptfds, &timeout);
+ if (result < 0) {
+ Msg2(level, "select(%d,,,,): %s", xfd->fd+1, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ if (result == 0) {
+ Msg2(level, "connecting to %s: %s",
+ sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
+ strerror(ETIMEDOUT));
+ return STAT_RETRYLATER;
+ }
+ if (FD_ISSET(xfd->fd, &readfds)) {
+#if 0
+ unsigned char dummy[1];
+ Read(xfd->fd, &dummy, 1); /* get error message */
+ Msg2(level, "connecting to %s: %s",
+ sockaddr_info(them, infobuff, sizeof(infobuff)),
+ strerror(errno));
+#else
+ Connect(xfd->fd, them, themlen); /* get error message */
+ Msg4(level, "connect(%d, %s, "F_Zd"): %s",
+ xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
+ themlen, strerror(errno));
+#endif
+ return STAT_RETRYLATER;
+ }
+ /* otherwise OK */
+ Fcntl_l(xfd->fd, F_SETFL, fcntl_flags);
+ } else {
+ Warn4("connect(%d, %s, "F_Zd"): %s",
+ xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
+ themlen, strerror(errno));
+ }
+ } else if (pf == PF_UNIX && errno == EPROTOTYPE) {
+ /* this is for UNIX domain sockets: a connect attempt seems to be
+ the only way to distinguish stream and datagram sockets */
+ int _errno = errno;
+ Info4("connect(%d, %s, "F_Zd"): %s",
+ xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
+ themlen, strerror(errno));
+#if 0
+ Info("assuming datagram socket");
+ xfd->dtype = DATA_RECVFROM;
+ xfd->salen = themlen;
+ memcpy(&xfd->peersa.soa, them, xfd->salen);
+#endif
+ /*!!! and remove bind socket */
+ Close(xfd->fd); xfd->fd = -1;
+ errno = _errno;
+ return -1;
+ } else {
+ Msg4(level, "connect(%d, %s, "F_Zd"): %s",
+ xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
+ themlen, strerror(errno));
+ Close(xfd->fd);
+ return STAT_RETRYLATER;
+ }
+ }
+
+ applyopts_fchown(xfd->fd, opts);
+ applyopts(xfd->fd, opts, PH_CONNECTED);
+ applyopts(xfd->fd, opts, PH_LATE);
+
+ Notice1("successfully connected from local address %s",
+ sockaddr_info(&la.soa, themlen, infobuff, sizeof(infobuff)));
+
+ return STAT_OK;
+}
+
+
+/* a subroutine that is common to all socket addresses that want to connect
+ to a peer address.
+ might fork.
+ 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,
+ bool alt) {
+ bool dofork = false;
+ struct opt *opts0;
+ char infobuff[256];
+ int level;
+ int result;
+
+ retropt_bool(opts, OPT_FORK, &dofork);
+ retropt_int(opts, OPT_SO_TYPE, &stype);
+
+ opts0 = copyopts(opts, GROUP_ALL);
+
+ Notice1("opening connection to %s",
+ sockaddr_info(them, themlen, infobuff, sizeof(infobuff)));
+
+ do { /* loop over retries and forks */
+
+#if WITH_RETRY
+ if (xfd->forever || xfd->retry) {
+ level = E_INFO;
+ } else
+#endif /* WITH_RETRY */
+ level = E_ERROR;
+ result =
+ _xioopen_connect(xfd, us, uslen, them, themlen, opts,
+ pf, stype, proto, alt, level);
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ if (xfd->forever || xfd->retry) {
+ --xfd->retry;
+ if (result == STAT_RETRYLATER) {
+ Nanosleep(&xfd->intervall, NULL);
+ }
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ continue;
+ }
+ return STAT_NORETRY;
+#endif /* WITH_RETRY */
+ default:
+ return result;
+ }
+
+#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,
+ 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);
+ 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);
+ }
+ break;
+ }
+ /* parent process */
+ Notice1("forked off child process "F_pid, pid);
+ Close(xfd->fd);
+ /* with and without retry */
+ Nanosleep(&xfd->intervall, NULL);
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ continue; /* with next socket() bind() connect() */
+ } else
+#endif /* WITH_RETRY */
+ {
+ break;
+ }
+#if 0
+ if ((result = _xio_openlate(fd, opts)) < 0)
+ return result;
+#endif
+ } while (true);
+
+ return 0;
+}
+
+
+/* common to xioopen_udp_sendto, ..unix_sendto, ..rawip */
+int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
+ union sockaddr_union *us, socklen_t uslen,
+ struct opt *opts,
+ int xioflags, xiosingle_t *xfd, unsigned groups,
+ int pf, int socktype, int ipproto) {
+ int level = E_ERROR;
+ union sockaddr_union la; socklen_t lalen = sizeof(la);
+ char infobuff[256];
+
+ if ((xfd->fd = Socket(pf, socktype, ipproto)) < 0) {
+ Msg4(level,
+ "socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+
+ applyopts_offset(xfd, opts);
+ applyopts_single(xfd, opts, PH_PASTSOCKET);
+ applyopts(xfd->fd, opts, PH_PASTSOCKET);
+ applyopts(xfd->fd, opts, PH_FD);
+
+ applyopts_cloexec(xfd->fd, opts);
+
+ applyopts(xfd->fd, opts, PH_PREBIND);
+ applyopts(xfd->fd, opts, PH_BIND);
+
+ if (us) {
+ if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
+ Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
+ xfd->fd, sockaddr_info((struct sockaddr *)us, uslen, infobuff, sizeof(infobuff)),
+ uslen, strerror(errno));
+ Close(xfd->fd);
+ return STAT_RETRYLATER;
+ }
+ }
+
+ applyopts(xfd->fd, opts, PH_PASTBIND);
+
+ /*applyopts(xfd->fd, opts, PH_CONNECT);*/
+
+ if (Getsockname(xfd->fd, &la.soa, &lalen) < 0) {
+ Warn4("getsockname(%d, %p, {%d}): %s",
+ xfd->fd, &la.soa, lalen, strerror(errno));
+ }
+
+ applyopts_fchown(xfd->fd, opts);
+ applyopts(xfd->fd, opts, PH_CONNECTED);
+ applyopts(xfd->fd, opts, PH_LATE);
+
+ /* xfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */
+ Notice1("successfully prepared local socket %s",
+ sockaddr_info(&la.soa, lalen, infobuff, sizeof(infobuff)));
+
+ return STAT_OK;
+}
+
+
+static pid_t xio_waitingfor;
+static bool xio_hashappened;
+void xiosigaction_hasread(int signum, siginfo_t *siginfo, void *ucontext) {
+ Debug5("xiosigaction_hasread(%d, {%d,%d,%d,"F_pid"}, )",
+ signum, siginfo->si_signo, siginfo->si_errno, siginfo->si_code,
+ siginfo->si_pid);
+ if (xio_waitingfor == siginfo->si_pid) {
+ xio_hashappened = true;
+ }
+ Debug("xiosigaction_hasread() ->");
+ return;
+}
+
+
+/* waits for incoming packet, checks its source address and port. Depending
+ on fork option, it may fork a subprocess.
+ Returns STAT_OK if a the packet was accepted; with fork option, this is already in
+ a new 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
+ */
+int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
+ struct sockaddr *us, socklen_t uslen,
+ struct opt *opts,
+ int pf, int socktype, int proto, int level) {
+ char *rangename;
+ socklen_t salen;
+ bool dofork = false;
+ pid_t pid; /* mostly int; only used with fork */
+ char infobuff[256];
+ char lisname[256];
+ bool drop = false; /* true if current packet must be dropped */
+ int result;
+
+ retropt_bool(opts, OPT_FORK, &dofork);
+
+ if (dofork) {
+ if (!(xioflags & XIO_MAYFORK)) {
+ Error("option fork not allowed here");
+ return STAT_NORETRY;
+ }
+ xfd->flags |= XIO_DOESFORK;
+ }
+
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
+
+#if 1
+ if (dofork) {
+#if HAVE_SIGACTION
+ struct sigaction act;
+ memset(&act, 0, sizeof(struct sigaction));
+ act.sa_flags = SA_NOCLDSTOP|SA_RESTART
+#ifdef SA_NOMASK
+ |SA_NOMASK
+#endif
+ ;
+ act.sa_handler = childdied;
+ if (Sigaction(SIGCHLD, &act, NULL) < 0) {
+ /*! man does not say that errno is defined */
+ Warn2("sigaction(SIGCHLD, %p, NULL): %s", childdied, strerror(errno));
+ }
+#else /* HAVE_SIGACTION */
+ if (Signal(SIGCHLD, childdied) == SIG_ERR) {
+ Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
+ }
+#endif /* !HAVE_SIGACTION */
+ }
+#endif /* 1 */
+
+ if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
+ Msg4(level,
+ "socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+
+ applyopts_single(xfd, opts, PH_PASTSOCKET);
+ applyopts(xfd->fd, opts, PH_PASTSOCKET);
+
+ applyopts_cloexec(xfd->fd, opts);
+
+ applyopts(xfd->fd, opts, PH_PREBIND);
+ applyopts(xfd->fd, opts, PH_BIND);
+ if ((us != NULL) && Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
+ Msg4(level, "bind(%d, {%s}, "F_Zd"): %s", xfd->fd,
+ sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
+ strerror(errno));
+ Close(xfd->fd);
+ return STAT_RETRYLATER;
+ }
+
+#if WITH_UNIX
+ if (pf == AF_UNIX && us != NULL) {
+ applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
+ }
+#endif
+
+ applyopts(xfd->fd, opts, PH_PASTBIND);
+#if WITH_UNIX
+ if (pf == AF_UNIX && us != NULL) {
+ /*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
+ applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY);
+ applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN);
+ }
+#endif /* WITH_UNIX */
+
+#if WITH_IP4 /*|| WITH_IP6*/
+ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
+ if (parserange(rangename, pf, &xfd->para.socket.range)
+ < 0) {
+ free(rangename);
+ return STAT_NORETRY;
+ }
+ free(rangename);
+ xfd->para.socket.dorange = true;
+ }
+#endif
+
+#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
+ xio_retropt_tcpwrap(xfd, opts);
+#endif /* && (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */
+
+ if (xioopts.logopt == 'm') {
+ Info("starting recvfrom loop, switching to syslog");
+ diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';
+ } else {
+ Info("starting recvfrom loop");
+ }
+
+ if (dofork) {
+#if HAVE_SIGACTION
+ {
+ struct sigaction act;
+ memset(&act, 0, sizeof(struct sigaction));
+ act.sa_flags = SA_NOCLDSTOP|SA_RESTART
+#ifdef SA_SIGINFO /* not on Linux 2.0(.33) */
+ |SA_SIGINFO
+#endif
+#ifdef SA_NOMASK
+ |SA_NOMASK
+#endif
+ ;
+#if 1 || HAVE_SIGACTION_SASIGACTION
+ act.sa_sigaction = xiosigaction_hasread;
+#else /* Linux 2.0(.33) does not have sigaction.sa_sigaction */
+ act.sa_handler = xiosighandler_hasread;
+#endif
+ if (Sigaction(SIGUSR1, &act, NULL) < 0) {
+ /*! Linux man does not explicitely say that errno is defined */
+ Warn1("sigaction(SIGUSR1, {&xiosigaction_subaddr_ok}, NULL): %s", strerror(errno));
+ }
+ if (Sigaction(SIGCHLD, &act, NULL) < 0) {
+ /*! Linux man does not explicitely say that errno is defined */
+ Warn1("sigaction(SIGCHLD, {&xiosigaction_subaddr_ok}, NULL): %s", strerror(errno));
+ }
+ }
+#else /* !HAVE_SIGACTION */
+ /*!!!*/
+ if (Signal(SIGUSR1, xiosigaction_hasread) == SIG_ERR) {
+ Warn1("signal(SIGUSR1, xiosigaction_hasread): %s", strerror(errno));
+ }
+ if (Signal(SIGCHLD, xiosigaction_hasread) == SIG_ERR) {
+ Warn1("signal(SIGCHLD, xiosigaction_hasread): %s", strerror(errno));
+ }
+#endif /* !HAVE_SIGACTION */
+ }
+
+ while (true) { /* but we only loop if fork option is set */
+ char peername[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 palen = sizeof(_peername); /* peer address size */
+
+ socket_init(pf, pa);
+ salen = sizeof(struct sockaddr);
+
+ if (drop) {
+ char *dummy[2];
+
+ Recv(xfd->fd, dummy, sizeof(dummy), 0);
+ drop = true;
+ }
+
+ /* loop until select() returns valid */
+ do {
+ fd_set in, out, expt;
+ /*? 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->fd, &in);
+ if (Select(xfd->fd+1, &in, &out, &expt, NULL) > 0) {
+ break;
+ }
+
+ if (errno == EINTR) {
+ continue;
+ }
+
+ Msg2(level, "select(, {%d}): %s", xfd->fd, strerror(errno));
+ Close(xfd->fd);
+ return STAT_RETRYLATER;
+ } while (true);
+
+ if (xiogetpacketsrc(xfd->fd, pa, &palen) < 0) {
+ return STAT_RETRYLATER;
+ }
+
+ Notice1("receiving packet from %s"/*"src"*/,
+ sockaddr_info((struct sockaddr *)pa, palen, peername, sizeof(peername))/*,
+ sockaddr_info(&la->soa, sockname, sizeof(sockname))*/);
+
+ if (xiocheckpeer(xfd, pa, la) < 0) {
+ /* drop packet */
+ char buff[512];
+ Recv(xfd->fd, buff, sizeof(buff), 0);
+ continue;
+ }
+ Info1("permitting packet from %s",
+ sockaddr_info((struct sockaddr *)pa, palen,
+ infobuff, sizeof(infobuff)));
+
+ applyopts(xfd->fd, opts, PH_FD);
+
+ applyopts(xfd->fd, opts, PH_CONNECTED);
+
+ xfd->peersa = *(union sockaddr_union *)pa;
+ xfd->salen = palen;
+
+ 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
+ indicates that is has consumed the last packet; CHLD means it has
+ terminated */
+ /* block SIGCHLD and SIGUSR1 until parent is ready to react */
+ sigemptyset(&mask_sigchldusr1);
+ sigaddset(&mask_sigchldusr1, SIGCHLD);
+ sigaddset(&mask_sigchldusr1, SIGUSR1);
+ Sigprocmask(SIG_BLOCK, &mask_sigchldusr1, NULL);
+
+ if ((pid = Fork()) < 0) {
+ Msg1(level, "fork(): %s", strerror(errno));
+ Close(xfd->fd);
+ 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 */
+ Sigprocmask(SIG_UNBLOCK, &mask_sigchldusr1, NULL);
+ xfd->ppid = Getppid(); /* send parent a signal when packet has
+ been consumed */
+
+#if WITH_RETRY
+ /* !? */
+ xfd->retry = 0;
+ xfd->forever = 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 */
+ xfd->opt_unlink_close = false;
+#endif /* WITH_UNIX */
+
+ break;
+ }
+
+ /* 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);
+
+ while (!xio_hashappened) {
+ Sleep(UINT_MAX); /* any signal lets us continue */
+ }
+ xio_waitingfor = 0; /* so this child will not set hashappened again */
+ xio_hashappened = false;
+
+ Info("continue listening");
+ } else {
+ break;
+ }
+ }
+ if ((result = _xio_openlate(xfd, opts)) != 0)
+ return STAT_NORETRY;
+
+ return STAT_OK;
+}
+
+
+/* returns STAT_* */
+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) {
+ char *rangename;
+ char infobuff[256];
+
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
+
+ if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
+ Msg4(level,
+ "socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+
+ applyopts_single(xfd, opts, PH_PASTSOCKET);
+ applyopts(xfd->fd, opts, PH_PASTSOCKET);
+
+ applyopts_cloexec(xfd->fd, opts);
+
+ applyopts(xfd->fd, opts, PH_PREBIND);
+ applyopts(xfd->fd, opts, PH_BIND);
+ if ((us != NULL) && Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
+ Msg4(level, "bind(%d, {%s}, "F_Zd"): %s", xfd->fd,
+ sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
+ strerror(errno));
+ Close(xfd->fd);
+ return STAT_RETRYLATER;
+ }
+
+#if WITH_UNIX
+ if (pf == AF_UNIX && us != NULL) {
+ applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
+ }
+#endif
+
+ applyopts(xfd->fd, opts, PH_PASTBIND);
+#if WITH_UNIX
+ if (pf == AF_UNIX && us != NULL) {
+ /*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
+ applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY);
+ applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN);
+ }
+#endif /* WITH_UNIX */
+
+#if WITH_IP4 /*|| WITH_IP6*/
+ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
+ if (parserange(rangename, pf, &xfd->para.socket.range)
+ < 0) {
+ free(rangename);
+ return STAT_NORETRY;
+ }
+ free(rangename);
+ xfd->para.socket.dorange = true;
+ }
+#endif
+
+#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
+ xio_retropt_tcpwrap(xfd, opts);
+#endif /* && (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */
+
+ if (xioopts.logopt == 'm') {
+ Info("starting recvfrom loop, switching to syslog");
+ diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';
+ } else {
+ Info("starting recvfrom loop");
+ }
+
+ return STAT_OK;
+}
+
+
+int retropt_socket_pf(struct opt *opts, int *pf) {
+ char *pfname;
+
+ if (retropt_string(opts, OPT_PROTOCOL_FAMILY, &pfname) >= 0) {
+ if (false) {
+ ;
+#if WITH_IP4
+ } else if (!strcasecmp("inet", pfname) ||
+ !strcasecmp("inet4", pfname) ||
+ !strcasecmp("ip4", pfname) ||
+ !strcasecmp("ipv4", pfname) ||
+ !strcasecmp("2", pfname)) {
+ *pf = PF_INET;
+#endif /* WITH_IP4 */
+#if WITH_IP6
+ } else if (!strcasecmp("inet6", pfname) ||
+ !strcasecmp("ip6", pfname) ||
+ !strcasecmp("ipv6", pfname) ||
+ !strcasecmp("10", pfname)) {
+ *pf = PF_INET6;
+#endif /* WITH_IP6 */
+ } else {
+ Error1("unknown protocol family \"%s\"", pfname);
+ /*! Warn("falling back to INET");*/
+ }
+ free(pfname);
+ return 0;
+ }
+ return -1;
+}
+
+
+
+int xiogetpacketsrc(int fd, union sockaddr_union *pa, socklen_t *palen) {
+ char infobuff[256];
+ 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);
+#endif
+#if HAVE_STRUCT_MSGHDR_MSGFLAGS
+ msgh.msg_flags = 0;
+#endif
+ if (Recvmsg(fd, &msgh, MSG_PEEK
+#ifdef 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) {
+ switch (sa->soa.sa_family) {
+#if WITH_IP4
+ case PF_INET:
+ return
+ xiocheckrange_ip4(&sa->ip4, &range->ip4);
+#endif /* WITH_IP4 */
+#if WITH_IP6
+ case PF_INET6:
+ return
+ xiocheckrange_ip6(&sa->ip6, &range->ip6);
+#endif /* WITH_IP6 */
+ }
+ return -1;
+}
+
+int xiocheckpeer(xiosingle_t *xfd,
+ union sockaddr_union *pa, union sockaddr_union *la) {
+ char infobuff[256];
+ int result;
+
+#if WITH_IP4
+ if (xfd->para.socket.dorange) {
+ if (xiocheckrange(pa, &xfd->para.socket.range) < 0) {
+ char infobuff[256];
+ Warn1("refusing connection from %s due to range option",
+ sockaddr_info((struct sockaddr *)pa, 0,
+ infobuff, sizeof(infobuff)));
+ return -1;
+ }
+ Info1("permitting connection from %s due to range option",
+ sockaddr_info((struct sockaddr *)pa, 0,
+ infobuff, sizeof(infobuff)));
+ }
+#endif /* WITH_IP4 */
+
+#if WITH_TCP || WITH_UDP
+ if (xfd->para.socket.ip.dosourceport) {
+#if WITH_IP4
+ if (pa->soa.sa_family == AF_INET &&
+ ntohs(((struct sockaddr_in *)pa)->sin_port) != xfd->para.socket.ip.sourceport) {
+ Warn1("refusing connection from %s due to wrong sourceport",
+ sockaddr_info((struct sockaddr *)pa, 0,
+ infobuff, sizeof(infobuff)));
+ return -1;
+ }
+#endif /* WITH_IP4 */
+#if WITH_IP6
+ if (pa->soa.sa_family == AF_INET6 &&
+ ntohs(((struct sockaddr_in6 *)pa)->sin6_port) != xfd->para.socket.ip.sourceport) {
+ Warn1("refusing connection from %s due to sourceport option",
+ sockaddr_info((struct sockaddr *)pa, 0,
+ infobuff, sizeof(infobuff)));
+ return -1;
+ }
+#endif /* WITH_IP6 */
+ Info1("permitting connection from %s due to sourceport option",
+ sockaddr_info((struct sockaddr *)pa, 0,
+ infobuff, sizeof(infobuff)));
+ } else if (xfd->para.socket.ip.lowport) {
+ 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",
+ sockaddr_info((struct sockaddr *)pa, 0,
+ infobuff, sizeof(infobuff)));
+ return -1;
+ }
+#if WITH_IP6
+ else if (pa->soa.sa_family == AF_INET6 &&
+ ntohs(((struct sockaddr_in6 *)pa)->sin6_port) >=
+ IPPORT_RESERVED) {
+ Warn1("refusing connection from %s due to lowport option",
+ sockaddr_info((struct sockaddr *)pa, 0,
+ infobuff, sizeof(infobuff)));
+ return -1;
+ }
+#endif /* WITH_IP6 */
+ Info1("permitting connection from %s due to lowport option",
+ sockaddr_info((struct sockaddr *)pa, 0,
+ infobuff, sizeof(infobuff)));
+ }
+#endif /* WITH_TCP || WITH_UDP */
+
+#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
+ result = xio_tcpwrap_check(xfd, la, pa);
+ if (result < 0) {
+ char infobuff[256];
+ Warn1("refusing connection from %s due to tcpwrapper option",
+ sockaddr_info((struct sockaddr *)pa, 0,
+ infobuff, sizeof(infobuff)));
+ return -1;
+ } else if (result > 0) {
+ Info1("permitting connection from %s due to tcpwrapper option",
+ sockaddr_info((struct sockaddr *)pa, 0,
+ infobuff, sizeof(infobuff)));
+ }
+#endif /* (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */
+
+ return 0; /* permitted */
+}
+
+#endif /* _WITH_SOCKET */
diff --git a/xio-socket.h b/xio-socket.h
new file mode 100644
index 0000000..1bccf1f
--- /dev/null
+++ b/xio-socket.h
@@ -0,0 +1,90 @@
+/* $Id: xio-socket.h,v 1.16 2006/12/30 23:04:21 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_socket_h_included
+#define __xio_socket_h_included 1
+
+extern const struct optdesc opt_connect_timeout;
+extern const struct optdesc opt_so_debug;
+extern const struct optdesc opt_so_acceptconn;
+extern const struct optdesc opt_so_broadcast;
+extern const struct optdesc opt_so_reuseaddr;
+extern const struct optdesc opt_so_keepalive;
+extern const struct optdesc opt_so_linger;
+extern const struct optdesc opt_so_linger;
+extern const struct optdesc opt_so_oobinline;
+extern const struct optdesc opt_so_sndbuf;
+extern const struct optdesc opt_so_sndbuf_late;
+extern const struct optdesc opt_so_rcvbuf;
+extern const struct optdesc opt_so_rcvbuf_late;
+extern const struct optdesc opt_so_error;
+extern const struct optdesc opt_so_type;
+extern const struct optdesc opt_so_dontroute;
+extern const struct optdesc opt_so_rcvlowat;
+extern const struct optdesc opt_so_rcvtimeo;
+extern const struct optdesc opt_so_sndlowat;
+extern const struct optdesc opt_so_sndtimeo;
+extern const struct optdesc opt_so_audit;
+extern const struct optdesc opt_so_attach_filter;
+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_kernaccept;
+extern const struct optdesc opt_so_no_check;
+extern const struct optdesc opt_so_noreuseaddr;
+extern const struct optdesc opt_so_passcred;
+extern const struct optdesc opt_so_peercred;
+extern const struct optdesc opt_so_priority;
+extern const struct optdesc opt_so_reuseport;
+extern const struct optdesc opt_so_security_authentication;
+extern const struct optdesc opt_so_security_encryption_network;
+extern const struct optdesc opt_so_security_encryption_transport;
+extern const struct optdesc opt_so_use_ifbufs;
+extern const struct optdesc opt_so_useloopback;
+extern const struct optdesc opt_so_dgram_errind;
+extern const struct optdesc opt_so_dontlinger;
+extern const struct optdesc opt_so_prototype;
+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 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,
+ 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,
+ bool alt, int level);
+
+/* common to xioopen_udp_sendto, ..unix_sendto, ..rawip */
+extern
+int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
+ union sockaddr_union *us, socklen_t uslen,
+ struct opt *opts,
+ int xioflags, xiosingle_t *xfd, unsigned groups,
+ int pf, int socktype, int ipproto);
+extern
+int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
+ struct sockaddr *us, socklen_t uslen,
+ struct opt *opts,
+ int pf, int socktype, int proto, int level);
+extern
+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 xiogetpacketsrc(int fd, union sockaddr_union *pa, socklen_t *palen);
+extern
+int xiocheckpeer(xiosingle_t *xfd,
+ union sockaddr_union *pa, union sockaddr_union *la);
+
+#endif /* !defined(__xio_socket_h_included) */
diff --git a/xio-socks.c b/xio-socks.c
new file mode 100644
index 0000000..8e990de
--- /dev/null
+++ b/xio-socks.c
@@ -0,0 +1,430 @@
+/* $Id: xio-socks.c,v 1.33 2006/12/28 14:06:37 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of socks4 type */
+
+#include "xiosysincludes.h"
+
+#if WITH_SOCKS4 || WITH_SOCKS4A
+
+#include "xioopen.h"
+#include "xio-ascii.h"
+#include "xio-socket.h"
+#include "xio-ip.h"
+#include "xio-ipapp.h"
+
+#include "xio-socks.h"
+
+
+enum {
+ SOCKS_CD_GRANTED = 90,
+ SOCKS_CD_FAILED,
+ SOCKS_CD_NOIDENT,
+ SOCKS_CD_IDENTFAILED
+} ;
+
+#define SOCKSPORT "1080"
+#define BUFF_LEN (SIZEOF_STRUCT_SOCKS4+512)
+
+static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *fd,
+ unsigned groups, int dummy1, int dummy2,
+ int dummy3);
+
+const struct optdesc opt_socksport = { "socksport", NULL, OPT_SOCKSPORT, GROUP_IP_SOCKS4, PH_LATE, TYPE_STRING, OFUNC_SPEC };
+const struct optdesc opt_socksuser = { "socksuser", NULL, OPT_SOCKSUSER, GROUP_IP_SOCKS4, PH_LATE, TYPE_NAME, OFUNC_SPEC };
+
+const struct addrdesc addr_socks4_connect = { "socks4", 3, xioopen_socks4_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<socks-server>:<host>:<port>") };
+
+const struct addrdesc addr_socks4a_connect = { "socks4a", 3, xioopen_socks4_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, 1, 0, 0 HELP(":<socks-server>:<host>:<port>") };
+
+static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xxfd,
+ unsigned groups, int socks4a, int dummy2,
+ int dummy3) {
+ /* we expect the form: host:host:port */
+ struct single *xfd = &xxfd->stream;
+ struct opt *opts0 = NULL;
+ const char *sockdname; char *socksport;
+ const char *targetname, *targetport;
+ int pf = PF_UNSPEC;
+ int ipproto = IPPROTO_TCP;
+ bool dofork = false;
+ union sockaddr_union us_sa, *us = &us_sa;
+ union sockaddr_union them_sa, *them = &them_sa;
+ socklen_t uslen = sizeof(us_sa);
+ socklen_t themlen = sizeof(them_sa);
+ bool needbind = false;
+ bool lowport = false;
+ unsigned char buff[BUFF_LEN];
+ struct socks4 *sockhead = (struct socks4 *)buff;
+ size_t buflen = sizeof(buff);
+ int socktype = SOCK_STREAM;
+ int level;
+ int result;
+
+ if (argc != 4) {
+ Error1("%s: 3 parameters required", argv[0]);
+ return STAT_NORETRY;
+ }
+ sockdname = argv[1];
+ targetname = argv[2];
+ targetport = argv[3];
+
+ xfd->howtoend = END_SHUTDOWN;
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ retropt_int(opts, OPT_SO_TYPE, &socktype);
+
+ retropt_bool(opts, OPT_FORK, &dofork);
+
+ result = _xioopen_socks4_prepare(targetport, opts, &socksport, sockhead, &buflen);
+ if (result != STAT_OK) return result;
+ result =
+ _xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
+ &pf, ipproto,
+ xfd->para.socket.ip.res_opts[1],
+ xfd->para.socket.ip.res_opts[0],
+ them, &themlen, us, &uslen,
+ &needbind, &lowport, &socktype);
+
+ Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
+ targetname,
+ ntohs(sockhead->port),
+ sockdname, socksport, sockhead->userid);
+
+ do { /* loop over failed connect and socks-request attempts */
+
+#if WITH_RETRY
+ if (xfd->forever || xfd->retry) {
+ level = E_INFO;
+ } else
+#endif /* WITH_RETRY */
+ level = E_ERROR;
+
+ /* we try to resolve the target address _before_ connecting to the socks
+ server: this avoids unnecessary socks connects and timeouts */
+ result =
+ _xioopen_socks4_connect0(xfd, targetname, socks4a, sockhead,
+ (ssize_t *)&buflen, level);
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ case STAT_RETRYNOW:
+ if (xfd->forever || xfd->retry--) {
+ if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL);
+ continue;
+ }
+#endif /* WITH_RETRY */
+ default:
+ return result;
+ }
+
+ /* this cannot fork because we retrieved fork option above */
+ result =
+ _xioopen_connect (xfd,
+ needbind?(struct sockaddr *)us:NULL, sizeof(*us),
+ (struct sockaddr *)them, themlen,
+ opts, pf, socktype, IPPROTO_TCP, lowport, level);
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ case STAT_RETRYNOW:
+ if (xfd->forever || xfd->retry--) {
+ if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL);
+ continue;
+ }
+#endif /* WITH_RETRY */
+ default:
+ return result;
+ }
+
+ applyopts(xfd->fd, opts, PH_ALL);
+
+ if ((result = _xio_openlate(xfd, opts)) < 0)
+ return result;
+
+ result = _xioopen_socks4_connect(xfd, sockhead, buflen, level);
+ switch (result) {
+ case STAT_OK: break;
+#if WITH_RETRY
+ case STAT_RETRYLATER:
+ case STAT_RETRYNOW:
+ if (xfd->forever || xfd->retry--) {
+ if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL);
+ continue;
+ }
+#endif /* WITH_RETRY */
+ default:
+ return result;
+ }
+
+#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;
+ }
+ 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);
+ }
+ xfd->forever = false; xfd->retry = 0;
+ break;
+ }
+ /* parent process */
+ Notice1("forked off child process "F_pid, pid);
+ Close(xfd->fd);
+ Nanosleep(&xfd->intervall, NULL);
+ dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+ continue;
+ } else
+#endif /* WITH_RETRY */
+ {
+ break;
+ }
+
+ } while (true); /* end of complete open loop - drop out on success */
+ return 0;
+}
+
+
+int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen) {
+ struct servent *se;
+ char *userid;
+
+ /* generate socks header - points to final target */
+ sockhead->version = 4;
+ sockhead->action = 1;
+ sockhead->port = parseport(targetport, IPPROTO_TCP);
+
+ if (retropt_string(opts, OPT_SOCKSPORT, socksport) < 0) {
+ if ((se = getservbyname("socks", "tcp")) != NULL) {
+ Debug1("\"socks/tcp\" resolves to %u", ntohs(se->s_port));
+ if ((*socksport = Malloc(6)) == NULL) {
+ return -1;
+ }
+ sprintf(*socksport, "%u", ntohs(se->s_port));
+ } else {
+ Debug1("cannot resolve service \"socks/tcp\", using %s", SOCKSPORT);
+ if ((*socksport = strdup(SOCKSPORT)) == NULL) {
+ errno = ENOMEM; return -1;
+ }
+ }
+ }
+
+ if (retropt_string(opts, OPT_SOCKSUSER, &userid) < 0) {
+ if ((userid = getenv("LOGNAME")) == NULL) {
+ if ((userid = getenv("USER")) == NULL) {
+ userid = "anonymous";
+ }
+ }
+ }
+ strncpy(sockhead->userid, userid, *headlen-SIZEOF_STRUCT_SOCKS4);
+ *headlen = SIZEOF_STRUCT_SOCKS4+strlen(userid)+1;
+ return STAT_OK;
+}
+
+
+/* called within retry/fork loop, before connect() */
+int
+ _xioopen_socks4_connect0(struct single *xfd,
+ const char *hostname, /* socks target host */
+ int socks4a,
+ struct socks4 *sockhead,
+ ssize_t *headlen, /* get available space,
+ return used length*/
+ int level) {
+ int result;
+
+ if (!socks4a) {
+ union sockaddr_union sau;
+ socklen_t saulen = sizeof(sau);
+
+ if ((result = xiogetaddrinfo(hostname, NULL,
+ PF_INET, SOCK_STREAM, IPPROTO_TCP,
+ &sau, &saulen,
+ xfd->para.socket.ip.res_opts[1],
+ xfd->para.socket.ip.res_opts[0]))
+ != STAT_OK) {
+ return result; /*! STAT_RETRY? */
+ }
+ memcpy(&sockhead->dest, &sau.ip4.sin_addr, 4);
+ }
+#if WITH_SOCKS4A
+ else {
+ /*! noresolve */
+ sockhead->dest = htonl(0x00000001); /* three bytes zero */
+ }
+#endif /* WITH_SOCKS4A */
+#if WITH_SOCKS4A
+ if (socks4a) {
+ /* SOCKS4A requires us to append the host name to resolve
+ after the user name's trailing 0 byte. */
+ char* insert_position = (char*) sockhead + *headlen;
+
+ strncpy(insert_position, hostname, BUFF_LEN-*headlen);
+ ((char *)sockhead)[BUFF_LEN-1] = 0;
+ *headlen += strlen(hostname) + 1;
+ if (*headlen > BUFF_LEN) {
+ *headlen = BUFF_LEN;
+ }
+ }
+#endif /* WITH_SOCKS4A */
+ return STAT_OK;
+}
+
+
+/* perform socks4 client dialog on existing FD.
+ Called within fork/retry loop, after connect() */
+int _xioopen_socks4_connect(struct single *xfd,
+ struct socks4 *sockhead,
+ size_t headlen,
+ int level) {
+ ssize_t bytes;
+ int result;
+ unsigned char buff[SIZEOF_STRUCT_SOCKS4];
+ struct socks4 *replyhead = (struct socks4 *)buff;
+ char *destdomname = NULL;
+
+ /* send socks header (target addr+port, +auth) */
+#if WITH_MSGLEVEL <= E_INFO
+ if (ntohl(sockhead->dest) <= 0x000000ff) {
+ destdomname = strchr(sockhead->userid, '\0')+1;
+ }
+ Info11("sending socks4%s request VN=%d DC=%d DSTPORT=%d DSTIP=%d.%d.%d.%d USERID=%s%s%s",
+ destdomname?"a":"",
+ sockhead->version, sockhead->action, sockhead->port,
+ ((unsigned char *)&sockhead->dest)[0],
+ ((unsigned char *)&sockhead->dest)[1],
+ ((unsigned char *)&sockhead->dest)[2],
+ ((unsigned char *)&sockhead->dest)[3],
+ sockhead->userid,
+ destdomname?" DESTNAME=":"",
+ destdomname?destdomname:"");
+#endif /* WITH_MSGLEVEL <= E_INFO */
+#if WITH_MSGLEVEL <= E_DEBUG
+ {
+ char *msgbuff;
+ if ((msgbuff = Malloc(3*headlen)) != NULL) {
+ xiohexdump((const unsigned char *)sockhead, headlen, msgbuff);
+ Debug1("sending socks4(a) request data %s", msgbuff);
+ }
+ }
+#endif /* WITH_MSGLEVEL <= E_DEBUG */
+ do {
+ result = Write(xfd->fd, sockhead, headlen);
+ } while (result < 0 && errno == EINTR);
+ if (result < 0) {
+ Msg4(level, "write(%d, %p, "F_Zu"): %s",
+ xfd->fd, sockhead, headlen, strerror(errno));
+ if (Close(xfd->fd) < 0) {
+ Info2("close(%d): %s", xfd->fd, strerror(errno));
+ }
+ return STAT_RETRYLATER; /* retry complete open cycle */
+ }
+
+ bytes = 0;
+ Info("waiting for socks reply");
+ while (bytes >= 0) { /* loop over answer chunks until complete or error */
+ /* receive socks answer */
+ do {
+ result = Read(xfd->fd, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes);
+ } while (result < 0 && errno == EINTR);
+ if (result < 0) {
+ Msg4(level, "read(%d, %p, "F_Zu"): %s",
+ xfd->fd, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes,
+ strerror(errno));
+ if (Close(xfd->fd) < 0) {
+ Info2("close(%d): %s", xfd->fd, strerror(errno));
+ }
+ }
+ if (result == 0) {
+ Msg(level, "read(): EOF during read of socks reply, peer might not be a socks4 server");
+ if (Close(xfd->fd) < 0) {
+ Info2("close(%d): %s", xfd->fd, strerror(errno));
+ }
+ return STAT_RETRYLATER;
+ }
+#if WITH_MSGLEVEL <= E_DEBUG
+ {
+ char msgbuff[3*SIZEOF_STRUCT_SOCKS4];
+ * xiohexdump((const unsigned char *)replyhead+bytes, result, msgbuff)
+ = '\0';
+ Debug2("received socks4 reply data (offset %u): %s", bytes, msgbuff);
+ }
+#endif /* WITH_MSGLEVEL <= E_DEBUG */
+ bytes += result;
+ if (bytes == SIZEOF_STRUCT_SOCKS4) {
+ Debug1("received all "F_Zd" bytes", bytes);
+ break;
+ }
+ Debug2("received "F_Zd" bytes, waiting for "F_Zu" more bytes",
+ result, SIZEOF_STRUCT_SOCKS4-bytes);
+ }
+ if (result <= 0) { /* we had a problem while reading socks answer */
+ return STAT_RETRYLATER; /* retry complete open cycle */
+ }
+
+ Info7("received socks reply VN=%u CD=%u DSTPORT=%u DSTIP=%u.%u.%u.%u",
+ replyhead->version, replyhead->action, ntohs(replyhead->port),
+ ((uint8_t *)&replyhead->dest)[0],
+ ((uint8_t *)&replyhead->dest)[1],
+ ((uint8_t *)&replyhead->dest)[2],
+ ((uint8_t *)&replyhead->dest)[3]);
+ if (replyhead->version != 0) {
+ Warn1("socks: reply code version is not 0 (%d)",
+ replyhead->version);
+ }
+
+ switch (replyhead->action) {
+ case SOCKS_CD_GRANTED:
+ /* Notice("socks: connect request succeeded"); */
+#if 0
+ if (Getsockname(xfd->fd, (struct sockaddr *)&us, &uslen) < 0) {
+ Warn4("getsockname(%d, %p, {%d}): %s",
+ xfd->fd, &us, uslen, strerror(errno));
+ }
+ Notice1("successfully connected from %s via socks4",
+ sockaddr_info((struct sockaddr *)&us, infobuff, sizeof(infobuff)));
+#else
+ Notice("successfully connected via socks4");
+#endif
+ break;
+
+ case SOCKS_CD_FAILED:
+ Msg(level, "socks: connect request rejected or failed");
+ return STAT_RETRYLATER;
+
+ case SOCKS_CD_NOIDENT:
+ Msg(level, "socks: ident refused by client");
+ return STAT_RETRYLATER;
+
+ case SOCKS_CD_IDENTFAILED:
+ Msg(level, "socks: ident failed");
+ return STAT_RETRYLATER;
+
+ default:
+ Msg1(level, "socks: undefined status %u", replyhead->action);
+ }
+
+ return STAT_OK;
+}
+#endif /* WITH_SOCKS4 || WITH_SOCKS4A */
+
diff --git a/xio-socks.h b/xio-socks.h
new file mode 100644
index 0000000..5b97b11
--- /dev/null
+++ b/xio-socks.h
@@ -0,0 +1,37 @@
+/* $Id: xio-socks.h,v 1.6 2004/06/06 19:03:28 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2004 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_socks_h_included
+#define __xio_socks_h_included 1
+
+struct socks4 {
+ uint8_t version;
+ uint8_t action;
+ uint16_t port;
+ uint32_t dest;
+ char userid[1]; /* just to have access via this struct */
+} ;
+#define SIZEOF_STRUCT_SOCKS4 8
+
+extern const struct optdesc opt_socksport;
+extern const struct optdesc opt_socksuser;
+
+extern const struct addrdesc addr_socks4_connect;
+extern const struct addrdesc addr_socks4a_connect;
+
+extern int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen);
+extern int
+ _xioopen_socks4_connect0(struct single *xfd,
+ const char *hostname, /* socks target host */
+ int socks4a,
+ struct socks4 *sockhead,
+ ssize_t *headlen, /* get available space,
+ return used length*/
+ int level);
+extern int _xioopen_socks4_connect(struct single *xfd,
+ struct socks4 *sockhead,
+ size_t headlen,
+ int level);
+
+#endif /* !defined(__xio_socks_h_included) */
diff --git a/xio-stdio.c b/xio-stdio.c
new file mode 100644
index 0000000..64cc4ee
--- /dev/null
+++ b/xio-stdio.c
@@ -0,0 +1,150 @@
+/* $Id: xio-stdio.c,v 1.18 2006/12/28 14:07:01 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses stdio type */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-fdnum.h"
+#include "xio-stdio.h"
+
+
+#if WITH_STDIO
+
+static int xioopen_stdio(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
+static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int fd, int dummy2, int dummy3);
+
+
+/* we specify all option groups that we can imagine for a FD, becasue the
+ changed parsing mechanism does not allow us to check the type of FD before
+ applying the options */
+const struct addrdesc addr_stdio = { "stdio", 3, xioopen_stdio, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(NULL) };
+const struct addrdesc addr_stdin = { "stdin", 1, xioopen_stdfd, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(NULL) };
+const struct addrdesc addr_stdout = { "stdout", 2, xioopen_stdfd, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 1, 0, 0 HELP(NULL) };
+const struct addrdesc addr_stderr = { "stderr", 2, xioopen_stdfd, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 2, 0, 0 HELP(NULL) };
+
+
+/* process a bidirectional "stdio" or "-" argument with options.
+ generate a dual address. */
+int xioopen_stdio_bi(xiofile_t *sock) {
+ struct opt *opts1, *opts2, *optspr;
+ unsigned int groups1 = addr_stdio.groups, groups2 = addr_stdio.groups;
+ int result;
+
+ if (xioopen_makedual(sock) < 0) {
+ return -1;
+ }
+
+ sock->dual.stream[0]->tag = XIO_TAG_RDONLY;
+ sock->dual.stream[0]->fd = 0 /*stdin*/;
+ sock->dual.stream[1]->tag = XIO_TAG_WRONLY;
+ sock->dual.stream[1]->fd = 1 /*stdout*/;
+ sock->dual.stream[0]->howtoend =
+ sock->dual.stream[1]->howtoend = END_NONE;
+
+#if WITH_TERMIOS
+ if (Isatty(sock->dual.stream[0]->fd)) {
+ if (Tcgetattr(sock->dual.stream[0]->fd,
+ &sock->dual.stream[0]->savetty)
+ < 0) {
+ Warn2("cannot query current terminal settings on fd %d: %s",
+ sock->dual.stream[0]->fd, strerror(errno));
+ } else {
+ sock->dual.stream[0]->ttyvalid = true;
+ }
+ }
+ if (Isatty(sock->dual.stream[1]->fd)) {
+ if (Tcgetattr(sock->dual.stream[1]->fd,
+ &sock->dual.stream[1]->savetty)
+ < 0) {
+ Warn2("cannot query current terminal settings on fd %d: %s",
+ sock->dual.stream[1]->fd, strerror(errno));
+ } else {
+ sock->dual.stream[1]->ttyvalid = true;
+ }
+ }
+#endif /* WITH_TERMIOS */
+
+ if (applyopts_single(&sock->stream, sock->stream.opts, PH_INIT) < 0) return -1;
+ applyopts(-1, sock->stream.opts, PH_INIT);
+
+ /* options here are one-time and one-direction, no second use */
+ retropt_bool(sock->stream.opts, OPT_IGNOREEOF, &sock->dual.stream[0]->ignoreeof);
+
+ /* extract opts that should be applied only once */
+ if ((optspr = copyopts(sock->stream.opts, GROUP_PROCESS)) == NULL) {
+ return -1;
+ }
+ if ((result = applyopts(-1, optspr, PH_EARLY)) < 0)
+ return result;
+ if ((result = applyopts(-1, optspr, PH_PREOPEN)) < 0)
+ return result;
+
+ /* here we copy opts, because most have to be applied twice! */
+ if ((opts1 = copyopts(sock->stream.opts, GROUP_FD|GROUP_APPL|(groups1&~GROUP_PROCESS))) == NULL) {
+ return -1;
+ }
+
+ /* apply options to first FD */
+ if ((result = applyopts(sock->dual.stream[0]->fd, opts1, PH_ALL)) < 0) {
+ return result;
+ }
+ if ((result = _xio_openlate(sock->dual.stream[0], opts1)) < 0) {
+ return result;
+ }
+
+ if ((opts2 = copyopts(sock->stream.opts, GROUP_FD|GROUP_APPL|(groups2&~GROUP_PROCESS))) == NULL) {
+ return -1;
+ }
+ /* apply options to second FD */
+ if ((result = applyopts(sock->dual.stream[1]->fd, opts2, PH_ALL)) < 0) {
+ return result;
+ }
+ if ((result = _xio_openlate(sock->dual.stream[1], opts2)) < 0) {
+ return result;
+ }
+
+ if ((result = _xio_openlate(sock->dual.stream[1], optspr)) < 0) {
+ return result;
+ }
+
+ Notice("reading from and writing to stdio");
+ return 0;
+}
+
+
+/* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw.
+ Do not set FD_CLOEXEC flag. */
+static int xioopen_stdio(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
+ int rw = (xioflags&XIO_ACCMODE);
+
+ if (argc != 1) {
+ Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1);
+ }
+
+ if (rw == XIO_RDWR) {
+ return xioopen_stdio_bi(fd);
+ }
+
+ Notice2("using %s for %s",
+ &("stdin\0\0\0stdout"[rw<<3]),
+ ddirection[rw]);
+ return xioopen_fd(opts, rw, &fd->stream, rw, dummy2, dummy3);
+}
+
+/* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw.
+ Do not set FD_CLOEXEC flag. */
+static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int fd, int dummy2, int dummy3) {
+ int rw = (xioflags&XIO_ACCMODE);
+
+ if (argc != 1) {
+ Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1);
+ }
+ Notice2("using %s for %s",
+ &("stdin\0\0\0stdout\0\0stderr"[fd<<3]),
+ ddirection[rw]);
+ return xioopen_fd(opts, rw, &xfd->stream, fd, dummy2, dummy3);
+}
+#endif /* WITH_STDIO */
diff --git a/xio-stdio.h b/xio-stdio.h
new file mode 100644
index 0000000..b75c17b
--- /dev/null
+++ b/xio-stdio.h
@@ -0,0 +1,17 @@
+/* $Id: xio-stdio.h,v 1.5 2006/02/08 19:47:03 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_stdio_h_included
+#define __xio_stdio_h_included 1
+
+
+
+extern int xioopen_stdio_bi(xiofile_t *sock);
+
+extern const struct addrdesc addr_stdio;
+extern const struct addrdesc addr_stdin;
+extern const struct addrdesc addr_stdout;
+extern const struct addrdesc addr_stderr;
+
+#endif /* !defined(__xio_stdio_h_included) */
diff --git a/xio-system.c b/xio-system.c
new file mode 100644
index 0000000..3297870
--- /dev/null
+++ b/xio-system.c
@@ -0,0 +1,65 @@
+/* $Id: xio-system.c,v 1.13 2006/03/21 20:53:38 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of system type */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-progcall.h"
+#include "xio-system.h"
+
+
+#if WITH_SYSTEM
+
+static int xioopen_system(int arg, const char *argv[], struct opt *opts,
+ int xioflags, /* XIO_RDONLY etc. */
+ xiofile_t *fd,
+ unsigned groups,
+ int dummy1, int dummy2, int dummy3
+ );
+
+const struct addrdesc addr_system = { "system", 3, xioopen_system, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, 1, 0, 0 HELP(":<shell-command>") };
+
+
+static int xioopen_system(int argc, const char *argv[], struct opt *opts,
+ int xioflags, /* XIO_RDONLY etc. */
+ xiofile_t *fd,
+ unsigned groups,
+ int dummy1, int dummy2, int dummy3
+ ) {
+ int status;
+ char *path = NULL;
+ int result;
+ const char *string = argv[1];
+
+ status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts);
+ if (status < 0) return status;
+ if (status == 0) { /* child */
+ int numleft;
+
+ if (setopt_path(opts, &path) < 0) {
+ /* this could be dangerous, so let us abort this child... */
+ Exit(1);
+ }
+
+ if ((numleft = leftopts(opts)) > 0) {
+ Error1("%d option(s) could not be used", numleft);
+ showleft(opts);
+ return STAT_NORETRY;
+ }
+
+ Info1("executing shell command \"%s\"", string);
+ result = System(string);
+ if (result != 0) {
+ Warn2("system(\"%s\") returned with status %d", string, result);
+ }
+ Exit(0); /* this child process */
+ }
+
+ /* parent */
+ return 0;
+}
+
+#endif /* WITH_SYSTEM */
diff --git a/xio-system.h b/xio-system.h
new file mode 100644
index 0000000..31f3fce
--- /dev/null
+++ b/xio-system.h
@@ -0,0 +1,10 @@
+/* $Id: xio-system.h,v 1.4 2001/11/04 17:19:20 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_system_h_included
+#define __xio_system_h_included 1
+
+extern const struct addrdesc addr_system;
+
+#endif /* !defined(__xio_system_h_included) */
diff --git a/xio-tcp.c b/xio-tcp.c
new file mode 100644
index 0000000..24fa5ae
--- /dev/null
+++ b/xio-tcp.c
@@ -0,0 +1,119 @@
+/* $Id: xio-tcp.c,v 1.24 2006/07/13 06:48:47 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for TCP related functions and options */
+
+#include "xiosysincludes.h"
+
+#if WITH_TCP
+
+#include "xioopen.h"
+#include "xio-listen.h"
+#include "xio-ip4.h"
+#include "xio-ipapp.h"
+#include "xio-tcp.h"
+
+/****** TCP addresses ******/
+
+#if WITH_IP4 || WITH_IP6
+const struct addrdesc addr_tcp_connect = { "tcp-connect", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_UNSPEC HELP(":<host>:<port>") };
+#if WITH_LISTEN
+const struct addrdesc addr_tcp_listen = { "tcp-listen", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_UNSPEC HELP(":<port>") };
+#endif
+#endif
+
+#if WITH_IP4
+const struct addrdesc addr_tcp4_connect = { "tcp4-connect", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_INET HELP(":<host>:<port>") };
+#if WITH_LISTEN
+const struct addrdesc addr_tcp4_listen = { "tcp4-listen", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_INET HELP(":<port>") };
+#endif
+#endif /* WITH_IP4 */
+
+#if WITH_IP6
+const struct addrdesc addr_tcp6_connect = { "tcp6-connect", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_INET6 HELP(":<host>:<port>") };
+#if WITH_LISTEN
+const struct addrdesc addr_tcp6_listen = { "tcp6-listen", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_INET6 HELP(":<port>") };
+#endif
+#endif /* WITH_IP6 */
+
+/****** TCP address options ******/
+
+#ifdef TCP_NODELAY
+const struct optdesc opt_tcp_nodelay = { "tcp-nodelay", "nodelay", OPT_TCP_NODELAY, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_NODELAY };
+#endif
+#ifdef TCP_MAXSEG
+const struct optdesc opt_tcp_maxseg = { "tcp-maxseg", "mss", OPT_TCP_MAXSEG, GROUP_IP_TCP, PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_MAXSEG };
+const struct optdesc opt_tcp_maxseg_late={"tcp-maxseg-late","mss-late",OPT_TCP_MAXSEG_LATE,GROUP_IP_TCP,PH_CONNECTED,TYPE_INT,OFUNC_SOCKOPT, SOL_TCP, TCP_MAXSEG};
+#endif
+#ifdef TCP_CORK
+const struct optdesc opt_tcp_cork = { "tcp-cork", "cork", OPT_TCP_CORK, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_CORK };
+#endif
+#ifdef TCP_STDURG
+const struct optdesc opt_tcp_stdurg = { "tcp-stdurg", "stdurg", OPT_TCP_STDURG, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_STDURG };
+#endif
+#ifdef TCP_RFC1323
+const struct optdesc opt_tcp_rfc1323= { "tcp-rfc1323", "rfc1323", OPT_TCP_RFC1323, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_RFC1323};
+#endif
+#ifdef TCP_KEEPIDLE
+const struct optdesc opt_tcp_keepidle={ "tcp-keepidle", "keepidle",OPT_TCP_KEEPIDLE,GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP,TCP_KEEPIDLE};
+#endif
+#ifdef TCP_KEEPINTVL
+const struct optdesc opt_tcp_keepintvl={"tcp-keepintvl","keepintvl",OPT_TCP_KEEPINTVL,GROUP_IP_TCP,PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP,TCP_KEEPINTVL};
+#endif
+#ifdef TCP_KEEPCNT
+const struct optdesc opt_tcp_keepcnt= { "tcp-keepcnt", "keepcnt", OPT_TCP_KEEPCNT, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_KEEPCNT };
+#endif
+#ifdef TCP_SYNCNT
+const struct optdesc opt_tcp_syncnt = { "tcp-syncnt", "syncnt", OPT_TCP_SYNCNT, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_SYNCNT };
+#endif
+#ifdef TCP_LINGER2
+const struct optdesc opt_tcp_linger2= { "tcp-linger2", "linger2", OPT_TCP_LINGER2, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_LINGER2 };
+#endif
+#ifdef TCP_DEFER_ACCEPT
+const struct optdesc opt_tcp_defer_accept={"tcp-defer-accept","defer-accept",OPT_TCP_DEFER_ACCEPT,GROUP_IP_TCP,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_TCP,TCP_DEFER_ACCEPT };
+#endif
+#ifdef TCP_WINDOW_CLAMP
+const struct optdesc opt_tcp_window_clamp={"tcp-window-clamp","window-clamp",OPT_TCP_WINDOW_CLAMP,GROUP_IP_TCP,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_TCP,TCP_WINDOW_CLAMP };
+#endif
+#ifdef TCP_INFO
+const struct optdesc opt_tcp_info = { "tcp-info", "info", OPT_TCP_INFO, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_INFO };
+#endif
+#ifdef TCP_QUICKACK
+const struct optdesc opt_tcp_quickack = { "tcp-quickack", "quickack", OPT_TCP_QUICKACK, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_QUICKACK };
+#endif
+#ifdef TCP_NOOPT
+const struct optdesc opt_tcp_noopt = { "tcp-noopt", "noopt", OPT_TCP_NOOPT, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_NOOPT };
+#endif
+#ifdef TCP_NOPUSH
+const struct optdesc opt_tcp_nopush = { "tcp-nopush", "nopush", OPT_TCP_NOPUSH, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_NOPUSH };
+#endif
+#ifdef TCP_MD5SIG
+const struct optdesc opt_tcp_md5sig = { "tcp-md5sig", "md5sig", OPT_TCP_MD5SIG, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_MD5SIG };
+#endif
+#ifdef TCP_SACK_DISABLE
+const struct optdesc opt_tcp_sack_disable = { "tcp-sack-disable", "sack-disable", OPT_TCP_SACK_DISABLE, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_SACK_DISABLE };
+#endif
+#ifdef TCP_SIGNATURE_ENABLE
+const struct optdesc opt_tcp_signature_enable = { "tcp-signature-enable", "signature-enable", OPT_TCP_SIGNATURE_ENABLE, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_SIGNATURE_ENABLE };
+#endif
+#ifdef TCP_ABORT_THRESHOLD /* HP-UX */
+const struct optdesc opt_tcp_abort_threshold = { "tcp-abort-threshold", "abort-threshold", OPT_TCP_ABORT_THRESHOLD, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_ABORT_THRESHOLD };
+#endif
+#ifdef TCP_CONN_ABORT_THRESHOLD /* HP-UX */
+const struct optdesc opt_tcp_conn_abort_threshold = { "tcp-conn-abort-threshold", "conn-abort-threshold", OPT_TCP_CONN_ABORT_THRESHOLD, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_CONN_ABORT_THRESHOLD };
+#endif
+#ifdef TCP_KEEPINIT /* OSF1 aka Tru64 */
+const struct optdesc opt_tcp_keepinit = { "tcp-keepinit", "keepinit", OPT_TCP_KEEPINIT, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_TCP, TCP_KEEPINIT };
+#endif
+#ifdef TCP_PAWS /* OSF1 aka Tru64 */
+const struct optdesc opt_tcp_paws = { "tcp-paws", "paws", OPT_TCP_PAWS, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_TCP, TCP_PAWS };
+#endif
+#ifdef TCP_SACKENA /* OSF1 aka Tru64 */
+const struct optdesc opt_tcp_sackena = { "tcp-sackena", "sackena", OPT_TCP_SACKENA, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_TCP, TCP_SACKENA };
+#endif
+#ifdef TCP_TSOPTENA /* OSF1 aka Tru64 */
+const struct optdesc opt_tcp_tsoptena = { "tcp-tsoptena", "tsoptena", OPT_TCP_TSOPTENA, GROUP_IP_TCP, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_TCP, TCP_TSOPTENA };
+#endif
+
+#endif /* WITH_TCP */
diff --git a/xio-tcp.h b/xio-tcp.h
new file mode 100644
index 0000000..041c601
--- /dev/null
+++ b/xio-tcp.h
@@ -0,0 +1,42 @@
+/* $Id: xio-tcp.h,v 1.12 2006/03/21 20:59:34 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_tcp_h_included
+#define __xio_tcp_h_included 1
+
+extern const struct addrdesc addr_tcp_connect;
+extern const struct addrdesc addr_tcp_listen;
+extern const struct addrdesc addr_tcp4_connect;
+extern const struct addrdesc addr_tcp4_listen;
+extern const struct addrdesc addr_tcp6_connect;
+extern const struct addrdesc addr_tcp6_listen;
+
+extern const struct optdesc opt_tcp_nodelay;
+extern const struct optdesc opt_tcp_maxseg;
+extern const struct optdesc opt_tcp_maxseg_late;
+extern const struct optdesc opt_tcp_cork;
+extern const struct optdesc opt_tcp_stdurg;
+extern const struct optdesc opt_tcp_rfc1323;
+extern const struct optdesc opt_tcp_keepidle;
+extern const struct optdesc opt_tcp_keepintvl;
+extern const struct optdesc opt_tcp_keepcnt;
+extern const struct optdesc opt_tcp_syncnt;
+extern const struct optdesc opt_tcp_linger2;
+extern const struct optdesc opt_tcp_defer_accept;
+extern const struct optdesc opt_tcp_window_clamp;
+extern const struct optdesc opt_tcp_info;
+extern const struct optdesc opt_tcp_quickack;
+extern const struct optdesc opt_tcp_noopt;
+extern const struct optdesc opt_tcp_nopush;
+extern const struct optdesc opt_tcp_md5sig;
+extern const struct optdesc opt_tcp_sack_disable;
+extern const struct optdesc opt_tcp_signature_enable;
+extern const struct optdesc opt_tcp_abort_threshold;
+extern const struct optdesc opt_tcp_conn_abort_threshold;
+extern const struct optdesc opt_tcp_keepinit;
+extern const struct optdesc opt_tcp_paws;
+extern const struct optdesc opt_tcp_sackena;
+extern const struct optdesc opt_tcp_tsoptena;
+
+#endif /* !defined(__xio_tcp_h_included) */
diff --git a/xio-tcpwrap.c b/xio-tcpwrap.c
new file mode 100644
index 0000000..4ab19c2
--- /dev/null
+++ b/xio-tcpwrap.c
@@ -0,0 +1,165 @@
+/* $Id: xio-tcpwrap.c,v 1.4 2007/02/05 19:48:00 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2006-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for tcpwrapper handling stuff */
+
+#include "xiosysincludes.h"
+#if WITH_LIBWRAP
+#include "tcpd.h"
+#endif
+#include "xioopen.h"
+
+#include "xio-tcpwrap.h"
+
+
+#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
+
+const struct optdesc opt_tcpwrappers = { "tcpwrappers", "tcpwrap", OPT_TCPWRAPPERS, GROUP_RANGE, PH_ACCEPT, TYPE_STRING_NULL, OFUNC_SPEC };
+const struct optdesc opt_tcpwrap_etc = { "tcpwrap-etc", "tcpwrap-dir", OPT_TCPWRAP_ETC, GROUP_RANGE, PH_ACCEPT, TYPE_FILENAME, OFUNC_SPEC };
+#if defined(HAVE_HOSTS_ALLOW_TABLE)
+const struct optdesc opt_tcpwrap_hosts_allow_table = { "tcpwrap-hosts-allow-table", "allow-table", OPT_TCPWRAP_HOSTS_ALLOW_TABLE, GROUP_RANGE, PH_ACCEPT, TYPE_FILENAME, OFUNC_SPEC };
+#endif
+#if defined(HAVE_HOSTS_DENY_TABLE)
+const struct optdesc opt_tcpwrap_hosts_deny_table = { "tcpwrap-hosts-deny-table", "deny-table", OPT_TCPWRAP_HOSTS_DENY_TABLE, GROUP_RANGE, PH_ACCEPT, TYPE_FILENAME, OFUNC_SPEC };
+#endif
+
+
+/* they are declared only externally with libwrap and would be unresolved
+ without these definitions */
+int allow_severity=10, deny_severity=10;
+
+/* returns 0 if option was found and could be applied
+ returns 1 if option was not found
+ returns -1 if option was found but failed */
+int xio_retropt_tcpwrap(xiosingle_t *xfd, struct opt *opts) {
+ bool dolibwrap = false;
+ dolibwrap =
+ retropt_string(opts, OPT_TCPWRAPPERS,
+ &xfd->para.socket.ip.libwrapname) >= 0 || dolibwrap;
+ dolibwrap =
+ retropt_string(opts, OPT_TCPWRAP_ETC,
+ &xfd->para.socket.ip.tcpwrap_etc) >= 0 || dolibwrap;
+#if defined(HAVE_HOSTS_ALLOW_TABLE)
+ dolibwrap =
+ retropt_string(opts, OPT_TCPWRAP_HOSTS_ALLOW_TABLE,
+ &xfd->para.socket.ip.hosts_allow_table) >= 0 || dolibwrap;
+#endif
+#if defined(HAVE_HOSTS_DENY_TABLE)
+ dolibwrap =
+ retropt_string(opts, OPT_TCPWRAP_HOSTS_DENY_TABLE,
+ &xfd->para.socket.ip.hosts_deny_table) >= 0 || dolibwrap;
+#endif
+ if (dolibwrap) {
+ xfd->para.socket.ip.dolibwrap = true;
+ if (xfd->para.socket.ip.libwrapname == NULL) {
+ xfd->para.socket.ip.libwrapname = (char *)diag_get_string('p');
+ }
+#if defined(HAVE_HOSTS_ALLOW_TABLE) || defined(HAVE_HOSTS_DENY_TABLE)
+ if (xfd->para.socket.ip.tcpwrap_etc) {
+ if (xfd->para.socket.ip.hosts_allow_table == NULL) {
+ xfd->para.socket.ip.hosts_allow_table =
+ Malloc(strlen(xfd->para.socket.ip.tcpwrap_etc)+1+11+1);
+ sprintf(xfd->para.socket.ip.hosts_allow_table, "%s/hosts.allow",
+ xfd->para.socket.ip.tcpwrap_etc);
+ }
+ if (xfd->para.socket.ip.hosts_deny_table == NULL) {
+ xfd->para.socket.ip.hosts_deny_table =
+ Malloc(strlen(xfd->para.socket.ip.tcpwrap_etc)+1+10+1);
+ sprintf(xfd->para.socket.ip.hosts_deny_table, "%s/hosts.deny",
+ xfd->para.socket.ip.tcpwrap_etc);
+ }
+ }
+#endif /* defined(HAVE_HOSTS_ALLOW_TABLE) || defined(HAVE_HOSTS_DENY_TABLE) */
+ return 0;
+ }
+ return 1;
+}
+
+
+/* returns -1 if forbidden, 0 if no tcpwrap check, or 1 if explicitely allowed
+ */
+int xio_tcpwrap_check(xiosingle_t *xfd, union sockaddr_union *us,
+ union sockaddr_union *them) {
+ char *save_hosts_allow_table, *save_hosts_deny_table;
+ struct request_info ri;
+#if WITH_IP6
+ char clientaddr[INET6_ADDRSTRLEN] = "", serveraddr[INET6_ADDRSTRLEN] = "";
+#else
+ char clientaddr[INET_ADDRSTRLEN] = "", serveraddr[INET_ADDRSTRLEN] = "";
+#endif
+ int allow;
+
+ if (!xfd->para.socket.ip.dolibwrap) {
+ return 0;
+ }
+
+#if defined(HAVE_HOSTS_ALLOW_TABLE)
+ save_hosts_allow_table = hosts_allow_table;
+ if (xfd->para.socket.ip.hosts_allow_table) {
+ Debug1("hosts_allow_table = \"%s\"",
+ xfd->para.socket.ip.hosts_allow_table);
+ hosts_allow_table = xfd->para.socket.ip.hosts_allow_table;
+ }
+#endif /* defined(HAVE_HOSTS_ALLOW_TABLE) */
+#if defined(HAVE_HOSTS_DENY_TABLE)
+ save_hosts_deny_table = hosts_deny_table;
+ if (xfd->para.socket.ip.hosts_deny_table) {
+ Debug1("hosts_deny_table = \"%s\"",
+ xfd->para.socket.ip.hosts_deny_table);
+ hosts_deny_table = xfd->para.socket.ip.hosts_deny_table;
+ }
+#endif /* defined(HAVE_HOSTS_DENY_TABLE) */
+
+ hosts_access_verbose = 32767;
+ if (inet_ntop(them->soa.sa_family,
+#if WITH_IP6
+ them->soa.sa_family==PF_INET6 ?
+ (void *)&them->ip6.sin6_addr :
+#endif
+ (void *)&them->ip4.sin_addr,
+ clientaddr, sizeof(clientaddr)) == NULL) {
+ Warn1("inet_ntop(): %s", strerror(errno));
+ }
+ if (inet_ntop(us->soa.sa_family,
+#if WITH_IP6
+ us->soa.sa_family==PF_INET6 ?
+ (void *)&us->ip6.sin6_addr :
+#endif
+ (void *)&us->ip4.sin_addr,
+ serveraddr, sizeof(serveraddr)) == NULL) {
+ Warn1("inet_ntop(): %s", strerror(errno));
+ }
+ Debug7("request_init(%p, RQ_FILE, %d, RQ_CLIENT_SIN, {%s:%u}, RQ_SERVER_SIN, {%s:%u}, RQ_DAEMON, \"%s\", 0",
+ &ri, xfd->fd, clientaddr,
+ ntohs(((struct sockaddr_in *)them)->sin_port),
+ serveraddr, ntohs(us->ip4.sin_port),
+ xfd->para.socket.ip.libwrapname?xfd->para.socket.ip.libwrapname:(char *)diag_get_string('p'));
+ request_init(&ri, RQ_FILE, xfd->fd,
+ RQ_CLIENT_SIN, them,
+ RQ_SERVER_SIN, &us->soa,
+ RQ_DAEMON, xfd->para.socket.ip.libwrapname?xfd->para.socket.ip.libwrapname:(char *)diag_get_string('p'), 0);
+ Debug("request_init() ->");
+
+ Debug1("sock_methods(%p)", &ri);
+ sock_methods(&ri);
+ Debug("sock_methods() ->");
+
+ Debug1("hosts_access(%p)", &ri);
+ allow = hosts_access(&ri);
+ Debug1("hosts_access() -> %d", allow);
+
+#if defined(HAVE_HOSTS_ALLOW_TABLE)
+ hosts_allow_table = save_hosts_allow_table;
+#endif
+#if defined(HAVE_HOSTS_DENY_TABLE)
+ hosts_deny_table = save_hosts_deny_table;
+#endif
+ if (allow == 0) {
+ return -1;
+ }
+ return 1;
+}
+
+#endif /* (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */
+
diff --git a/xio-tcpwrap.h b/xio-tcpwrap.h
new file mode 100644
index 0000000..aaffc98
--- /dev/null
+++ b/xio-tcpwrap.h
@@ -0,0 +1,22 @@
+/* $Id: xio-tcpwrap.h,v 1.1 2006/05/12 21:00:00 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_tcpwrap_h_included
+#define __xio_tcpwrap_h_included 1
+
+#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
+
+extern const struct optdesc opt_tcpwrappers;
+extern const struct optdesc opt_tcpwrap_etc;
+extern const struct optdesc opt_tcpwrap_hosts_allow_table;
+extern const struct optdesc opt_tcpwrap_hosts_deny_table;
+
+extern int xio_retropt_tcpwrap(xiosingle_t *xfd, struct opt *opts);
+extern
+int xio_tcpwrap_check(xiosingle_t *xfd, union sockaddr_union *us,
+ union sockaddr_union *them);
+
+#endif /* (WITH_TCP || WITH_UDP) && WITH_LIBWRAP */
+
+#endif /* !defined(__xio_tcpwrap_h_included) */
diff --git a/xio-termios.c b/xio-termios.c
new file mode 100644
index 0000000..ff07001
--- /dev/null
+++ b/xio-termios.c
@@ -0,0 +1,326 @@
+/* $Id: xio-termios.c,v 1.18 2006/07/13 06:49:37 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for terminal I/O options */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-termios.h"
+
+/****** TERMIOS addresses ******/
+#if WITH_TERMIOS
+const struct optdesc opt_tiocsctty={ "tiocsctty", "ctty",OPT_TIOCSCTTY, GROUP_TERMIOS, PH_LATE2, TYPE_BOOL, OFUNC_SPEC };
+
+const struct optdesc opt_brkint = { "brkint", NULL, OPT_BRKINT, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, BRKINT };
+const struct optdesc opt_icrnl = { "icrnl", NULL, OPT_ICRNL, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, ICRNL };
+const struct optdesc opt_ignbrk = { "ignbrk", NULL, OPT_IGNBRK, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, IGNBRK };
+const struct optdesc opt_igncr = { "igncr", NULL, OPT_IGNCR, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, IGNCR };
+const struct optdesc opt_ignpar = { "ignpar", NULL, OPT_IGNPAR, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, IGNPAR };
+const struct optdesc opt_imaxbel = { "imaxbel", NULL, OPT_IMAXBEL, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, IMAXBEL };
+const struct optdesc opt_inlcr = { "inlcr", NULL, OPT_INLCR, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, INLCR };
+const struct optdesc opt_inpck = { "inpck", NULL, OPT_INPCK, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, INPCK };
+const struct optdesc opt_istrip = { "istrip", NULL, OPT_ISTRIP, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, ISTRIP };
+#ifdef IUCLC
+const struct optdesc opt_iuclc = { "iuclc", NULL, OPT_IUCLC, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, IUCLC };
+#endif
+const struct optdesc opt_ixany = { "ixany", NULL, OPT_IXANY, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, IXANY };
+const struct optdesc opt_ixoff = { "ixoff", NULL, OPT_IXOFF, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, IXOFF };
+const struct optdesc opt_ixon = { "ixon", NULL, OPT_IXON, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, IXON };
+const struct optdesc opt_parmrk = { "parmrk", NULL, OPT_PARMRK, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, PARMRK };
+
+#ifdef CRDLY
+# ifdef CR0
+const struct optdesc opt_cr0 = { "cr0", NULL, OPT_CR0, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, CR0, CRDLY };
+# endif
+# ifdef CR1
+const struct optdesc opt_cr1 = { "cr1", NULL, OPT_CR1, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, CR1, CRDLY };
+# endif
+# ifdef CR2
+const struct optdesc opt_cr2 = { "cr2", NULL, OPT_CR2, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, CR2, CRDLY };
+# 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
+const struct optdesc opt_crdly = { "crdly", NULL, OPT_CRDLY, GROUP_TERMIOS, PH_FD, TYPE_UINT, OFUNC_TERMIOS_VALUE, 1, CRDLY, CRDLY_SHIFT };
+#endif /* defined(CRDLY) */
+#ifdef NLDLY
+# ifdef NL0
+const struct optdesc opt_nl0 = { "nl0", NULL, OPT_NL0, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, NL0, NLDLY };
+# endif
+# ifdef NL1
+const struct optdesc opt_nl1 = { "nl1", NULL, OPT_NL1, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, NL1, NLDLY };
+# endif
+const struct optdesc opt_nldly = { "nldly", NULL, OPT_NLDLY, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, NLDLY };
+#endif /* defined(NLDLY) */
+#ifdef OCRNL
+const struct optdesc opt_ocrnl = { "ocrnl", NULL, OPT_OCRNL, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, OCRNL };
+#endif
+#ifdef OFDEL
+const struct optdesc opt_ofdel = { "ofdel", NULL, OPT_OFDEL, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, OFDEL };
+#endif
+#ifdef OFILL
+const struct optdesc opt_ofill = { "ofill", NULL, OPT_OFILL, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, OFILL };
+#endif
+const struct optdesc opt_opost = { "opost", NULL, OPT_OPOST, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, OPOST };
+#ifdef OLCUC
+const struct optdesc opt_olcuc = { "olcuc", NULL, OPT_OLCUC, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, OLCUC };
+#endif
+const struct optdesc opt_onlcr = { "onlcr", NULL, OPT_ONLCR, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, ONLCR };
+#ifdef ONLRET
+const struct optdesc opt_onlret = { "onlret", NULL, OPT_ONLRET, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, ONLRET };
+#endif
+#ifdef ONOCR
+const struct optdesc opt_onocr = { "onocr", NULL, OPT_ONOCR, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, ONOCR };
+#endif
+#ifdef TABDLY
+# ifdef TAB0
+const struct optdesc opt_tab0 = { "tab0", NULL, OPT_TAB0, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_FLAG, 1, TAB0, TABDLY };
+# endif
+# ifdef TAB1
+const struct optdesc opt_tab1 = { "tab1", NULL, OPT_TAB1, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_FLAG, 1, TAB1, TABDLY };
+# endif
+# ifdef TAB2
+const struct optdesc opt_tab2 = { "tab2", NULL, OPT_TAB2, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_FLAG, 1, TAB2, TABDLY };
+# endif
+# ifdef TAB3
+const struct optdesc opt_tab3 = { "tab3", NULL, OPT_TAB3, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_FLAG, 1, TAB3, TABDLY };
+# endif
+# ifdef XTABS
+const struct optdesc opt_xtabs = { "xtabs", NULL, OPT_XTABS, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_FLAG, 1, XTABS, TABDLY };
+# endif
+const struct optdesc opt_tabdly = { "tabdly", NULL, OPT_TABDLY, GROUP_TERMIOS, PH_FD, TYPE_UINT, OFUNC_TERMIOS_VALUE, 1, TABDLY, TABDLY_SHIFT };
+#endif
+#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 };
+#endif
+# ifdef BS1
+const struct optdesc opt_bs1 = { "bs1", NULL, OPT_BS1, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, BS1, BSDLY };
+# endif
+const struct optdesc opt_bsdly = { "bsdly", NULL, OPT_BSDLY, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, BSDLY };
+#endif
+#ifdef VTDLY
+# ifdef VT0
+const struct optdesc opt_vt0 = { "vt0", NULL, OPT_VT0, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, VT0, VTDLY };
+# endif
+# ifdef VT1
+const struct optdesc opt_vt1 = { "vt1", NULL, OPT_VT1, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, VT1, VTDLY };
+# endif
+const struct optdesc opt_vtdly = { "vtdly", NULL, OPT_VTDLY, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, VTDLY };
+#endif
+#ifdef FFDLY
+# ifdef FF0
+const struct optdesc opt_ff0 = { "ff0", NULL, OPT_FF0, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, FF0, FFDLY };
+# endif
+# ifdef FF1
+const struct optdesc opt_ff1 = { "ff1", NULL, OPT_FF1, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 1, FF1, FFDLY };
+# endif
+const struct optdesc opt_ffdly = { "ffdly", NULL, OPT_FFDLY, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 1, FFDLY };
+#endif
+
+#ifdef CBAUD
+const struct optdesc opt_b0 = { "b0", NULL, OPT_B0, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B0, CBAUD };
+const struct optdesc opt_b50 = { "b50", NULL, OPT_B50, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B50, CBAUD };
+const struct optdesc opt_b75 = { "b75", NULL, OPT_B75, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B75, CBAUD };
+const struct optdesc opt_b110 = { "b110", NULL, OPT_B110, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B110, CBAUD };
+const struct optdesc opt_b134 = { "b134", NULL, OPT_B134, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B134, CBAUD };
+const struct optdesc opt_b150 = { "b150", NULL, OPT_B150, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B150, CBAUD };
+const struct optdesc opt_b200 = { "b200", NULL, OPT_B200, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B200, CBAUD };
+const struct optdesc opt_b300 = { "b300", NULL, OPT_B300, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B300, CBAUD };
+const struct optdesc opt_b600 = { "b600", NULL, OPT_B600, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B600, CBAUD };
+#ifdef B900 /* HP-UX */
+const struct optdesc opt_b900 = { "b900", NULL, OPT_B900, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B900, CBAUD };
+#endif
+const struct optdesc opt_b1200 = { "b1200", NULL, OPT_B1200, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B1200, CBAUD };
+const struct optdesc opt_b1800 = { "b1800", NULL, OPT_B1800, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B1800, CBAUD };
+const struct optdesc opt_b2400 = { "b2400", NULL, OPT_B2400, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B2400, CBAUD };
+#ifdef B3600 /* HP-UX */
+const struct optdesc opt_b3600 = { "b3600", NULL, OPT_B3600, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B3600, CBAUD };
+#endif
+const struct optdesc opt_b4800 = { "b4800", NULL, OPT_B4800, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B4800, CBAUD };
+#ifdef B7200 /* HP-UX */
+const struct optdesc opt_b7200 = { "b7200", NULL, OPT_B7200, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B7200, CBAUD };
+#endif
+const struct optdesc opt_b9600 = { "b9600", NULL, OPT_B9600, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B9600, CBAUD };
+const struct optdesc opt_b19200 = { "b19200", NULL, OPT_B19200, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B19200, CBAUD };
+const struct optdesc opt_b38400 = { "b38400", NULL, OPT_B38400, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B38400, CBAUD };
+#ifdef B57600
+const struct optdesc opt_b57600 = { "b57600", NULL, OPT_B57600, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B57600, CBAUD };
+#endif
+#ifdef B115200
+const struct optdesc opt_b115200 = { "b115200", NULL, OPT_B115200, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B115200, CBAUD };
+#endif
+#ifdef B230400
+const struct optdesc opt_b230400 = { "b230400", NULL, OPT_B230400, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B230400, CBAUD };
+#endif
+#ifdef B460800
+const struct optdesc opt_b460800 = { "b460800", NULL, OPT_B460800, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B460800, CBAUD };
+#endif
+#ifdef B500000
+const struct optdesc opt_b500000 = { "b500000", NULL, OPT_B500000, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B500000, CBAUD };
+#endif
+#ifdef B576000
+const struct optdesc opt_b576000 = { "b576000", NULL, OPT_B576000, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B576000, CBAUD };
+#endif
+#ifdef B921600
+const struct optdesc opt_b921600 = { "b921600", NULL, OPT_B921600, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B921600, CBAUD };
+#endif
+#ifdef B1000000
+const struct optdesc opt_b1000000= { "b1000000",NULL, OPT_B1000000,GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B1000000, CBAUD };
+#endif
+#ifdef B1152000
+const struct optdesc opt_b1152000= { "b1152000",NULL, OPT_B1152000,GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B1152000, CBAUD };
+#endif
+#ifdef B1500000
+const struct optdesc opt_b1500000= { "b1500000",NULL, OPT_B1500000,GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B1500000, CBAUD };
+#endif
+#ifdef B2000000
+const struct optdesc opt_b2000000= { "b2000000",NULL, OPT_B2000000,GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B2000000, CBAUD };
+#endif
+#ifdef B2500000
+const struct optdesc opt_b2500000= { "b2500000",NULL, OPT_B2500000,GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B2500000, CBAUD };
+#endif
+#ifdef B3000000
+const struct optdesc opt_b3000000= { "b3000000",NULL, OPT_B3000000,GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B3000000, CBAUD };
+#endif
+#ifdef B3500000
+const struct optdesc opt_b3500000= { "b3500000",NULL, OPT_B3500000,GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B3500000, CBAUD };
+#endif
+#ifdef B4000000
+const struct optdesc opt_b4000000= { "b4000000",NULL, OPT_B4000000,GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, B4000000, CBAUD };
+#endif
+#endif /* defined(CBAUD) */
+const struct optdesc opt_cs5 = { "cs5", NULL, OPT_CS5, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_PATTERN, 2, CS5, CSIZE };
+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 };
+const struct optdesc opt_csize = { "csize", NULL, OPT_CSIZE, GROUP_TERMIOS, PH_FD, TYPE_UINT, OFUNC_TERMIOS_VALUE, 2, CSIZE, CSIZE_SHIFT };
+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 };
+const struct optdesc opt_parodd = { "parodd", NULL, OPT_PARODD, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 2, PARODD };
+const struct optdesc opt_hupcl = { "hupcl", NULL, OPT_HUPCL, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 2, HUPCL };
+const struct optdesc opt_clocal = { "clocal", NULL, OPT_CLOCAL, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 2, CLOCAL };
+/*const struct optdesc opt_cibaud = { "cibaud",NULL, OPT_CIBAUD, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 2, CIBAUD };*/
+#ifdef CRTSCTS
+const struct optdesc opt_crtscts = { "crtscts", NULL, OPT_CRTSCTS, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 2, CRTSCTS };
+#endif
+
+const struct optdesc opt_isig = { "isig", NULL, OPT_ISIG, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, ISIG };
+const struct optdesc opt_icanon = { "icanon", NULL, OPT_ICANON, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, ICANON };
+#ifdef XCASE
+const struct optdesc opt_xcase = { "xcase", NULL, OPT_XCASE, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, XCASE };
+#endif
+const struct optdesc opt_echo = { "echo", NULL, OPT_ECHO, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, ECHO };
+const struct optdesc opt_echoe = { "echoe", NULL, OPT_ECHOE, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, ECHOE };
+const struct optdesc opt_echok = { "echok", NULL, OPT_ECHOK, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, ECHOK };
+const struct optdesc opt_echonl = { "echonl", NULL, OPT_ECHONL, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, ECHONL };
+const struct optdesc opt_echoctl = { "echoctl", NULL, OPT_ECHOCTL, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, ECHOCTL };
+#ifdef ECHOPRT
+const struct optdesc opt_echoprt = { "echoprt", NULL, OPT_ECHOPRT, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, ECHOPRT };
+#endif
+const struct optdesc opt_echoke = { "echoke", NULL, OPT_ECHOKE, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, ECHOKE };
+const struct optdesc opt_flusho = { "flusho", NULL, OPT_FLUSHO, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, FLUSHO };
+const struct optdesc opt_noflsh = { "noflsh", NULL, OPT_NOFLSH, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, NOFLSH };
+const struct optdesc opt_tostop = { "tostop", NULL, OPT_TOSTOP, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, TOSTOP };
+#ifdef PENDIN
+const struct optdesc opt_pendin = { "pendin", NULL, OPT_PENDIN, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, PENDIN };
+#endif
+const struct optdesc opt_iexten = { "iexten", NULL, OPT_IEXTEN, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 3, IEXTEN };
+
+const struct optdesc opt_vintr = { "vintr", "intr", OPT_VINTR, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VINTR };
+const struct optdesc opt_vquit = { "vquit", "quit", OPT_VQUIT, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VQUIT };
+const struct optdesc opt_verase = { "verase", "erase", OPT_VERASE, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VERASE };
+const struct optdesc opt_vkill = { "vkill", "kill", OPT_VKILL, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VKILL };
+const struct optdesc opt_veof = { "veof", "eof", OPT_VEOF, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VEOF };
+const struct optdesc opt_vtime = { "vtime", "time", OPT_VTIME, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VTIME };
+const struct optdesc opt_vmin = { "vmin", "min", OPT_VMIN, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VMIN };
+#ifdef VSWTC
+const struct optdesc opt_vswtc = { "vswtc", "swtc", OPT_VSWTC, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VSWTC };
+#endif /* VSWTC */
+const struct optdesc opt_vstart = { "vstart", "start", OPT_VSTART, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VSTART };
+const struct optdesc opt_vstop = { "vstop", "stop", OPT_VSTOP, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VSTOP };
+const struct optdesc opt_vsusp = { "vsusp", "susp", OPT_VSUSP, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VSUSP };
+#ifdef VDSUSP /* HP-UX */
+const struct optdesc opt_vdsusp = { "vdsusp", "dsusp", OPT_VDSUSP, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VDSUSP };
+#endif
+const struct optdesc opt_veol = { "veol", "eol", OPT_VEOL, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VEOL };
+#ifdef VREPRINT
+const struct optdesc opt_vreprint = { "vreprint","reprint",OPT_VREPRINT,GROUP_TERMIOS,PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VREPRINT };
+#endif
+#ifdef VDISCARD
+const struct optdesc opt_vdiscard = { "vdiscard","discard",OPT_VDISCARD,GROUP_TERMIOS,PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VDISCARD };
+#endif
+#ifdef VWERASE
+const struct optdesc opt_vwerase = { "vwerase","werase",OPT_VWERASE, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VWERASE };
+#endif
+const struct optdesc opt_vlnext = { "vlnext", "lnext", OPT_VLNEXT, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VLNEXT };
+const struct optdesc opt_veol2 = { "veol2", "eol2", OPT_VEOL2, GROUP_TERMIOS, PH_FD, TYPE_BYTE, OFUNC_TERMIOS_CHAR, VEOL2 };
+
+const struct optdesc opt_raw = { "raw", NULL, OPT_RAW, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_SPEC };
+const struct optdesc opt_sane = { "sane", NULL, OPT_SANE, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_SPEC };
+
+#ifdef HAVE_TERMIOS_ISPEED
+const struct optdesc opt_ispeed = { "ispeed", NULL, OPT_ISPEED, GROUP_TERMIOS, PH_FD, TYPE_UINT, OFUNC_TERMIOS_SPEED, ISPEED_OFFSET };
+const struct optdesc opt_ospeed = { "ospeed", NULL, OPT_OSPEED, GROUP_TERMIOS, PH_FD, TYPE_UINT, OFUNC_TERMIOS_SPEED, OSPEED_OFFSET };
+#endif /* HAVE_TERMIOS_ISPEED */
+
+
+int xiotermiosflag_applyopt(int fd, struct opt *opt) {
+ int result;
+ if (opt->value.u_bool) {
+ result = xiotermios_setflag(fd, opt->desc->major, opt->desc->minor);
+ } else {
+ result = xiotermios_clrflag(fd, opt->desc->major, opt->desc->minor);
+ }
+ if (result < 0) {
+ opt->desc = ODESC_ERROR;
+ return -1;
+ }
+ return 0;
+}
+
+#endif /* WITH_TERMIOS */
+
+int xiotermios_setflag(int fd, int word, tcflag_t mask) {
+ union {
+ struct termios termarg;
+ tcflag_t flags[4];
+ } tdata;
+
+ if (Tcgetattr(fd, &tdata.termarg) < 0) {
+ Error3("tcgetattr(%d, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ return -1;
+ }
+ tdata.flags[word] |= mask;
+ if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
+ Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+int xiotermios_clrflag(int fd, int word, tcflag_t mask) {
+ union {
+ struct termios termarg;
+ tcflag_t flags[4];
+ } tdata;
+
+ if (Tcgetattr(fd, &tdata.termarg) < 0) {
+ Error3("tcgetattr(%d, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ return -1;
+ }
+ tdata.flags[word] &= ~mask;
+ if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
+ Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
diff --git a/xio-termios.h b/xio-termios.h
new file mode 100644
index 0000000..8023346
--- /dev/null
+++ b/xio-termios.h
@@ -0,0 +1,147 @@
+/* $Id: xio-termios.h,v 1.11 2006/05/31 19:23:43 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_termios_h_included
+#define __xio_termios_h_included 1
+
+extern const struct optdesc opt_tiocsctty;
+
+extern const struct optdesc opt_brkint;
+extern const struct optdesc opt_icrnl;
+extern const struct optdesc opt_ignbrk;
+extern const struct optdesc opt_igncr;
+extern const struct optdesc opt_ignpar;
+extern const struct optdesc opt_imaxbel;
+extern const struct optdesc opt_inlcr;
+extern const struct optdesc opt_inpck;
+extern const struct optdesc opt_istrip;
+extern const struct optdesc opt_iuclc;
+extern const struct optdesc opt_ixany;
+extern const struct optdesc opt_ixoff;
+extern const struct optdesc opt_ixon;
+extern const struct optdesc opt_parmrk;
+extern const struct optdesc opt_cr0;
+extern const struct optdesc opt_cr1;
+extern const struct optdesc opt_cr2;
+extern const struct optdesc opt_cr3;
+extern const struct optdesc opt_crdly;
+extern const struct optdesc opt_nl0;
+extern const struct optdesc opt_nl1;
+extern const struct optdesc opt_nldly;
+extern const struct optdesc opt_ocrnl;
+extern const struct optdesc opt_ofdel;
+extern const struct optdesc opt_ofill;
+extern const struct optdesc opt_opost;
+extern const struct optdesc opt_olcuc;
+extern const struct optdesc opt_onlcr;
+extern const struct optdesc opt_onlret;
+extern const struct optdesc opt_onocr;
+extern const struct optdesc opt_tab0;
+extern const struct optdesc opt_tab1;
+extern const struct optdesc opt_tab2;
+extern const struct optdesc opt_tab3;
+extern const struct optdesc opt_xtabs;
+extern const struct optdesc opt_tabdly;
+extern const struct optdesc opt_bs0;
+extern const struct optdesc opt_bs1;
+extern const struct optdesc opt_bsdly;
+extern const struct optdesc opt_vt0;
+extern const struct optdesc opt_vt1;
+extern const struct optdesc opt_vtdly;
+extern const struct optdesc opt_ff0;
+extern const struct optdesc opt_ff1;
+extern const struct optdesc opt_ffdly;
+extern const struct optdesc opt_b0;
+extern const struct optdesc opt_b50;
+extern const struct optdesc opt_b75;
+extern const struct optdesc opt_b110;
+extern const struct optdesc opt_b134;
+extern const struct optdesc opt_b150;
+extern const struct optdesc opt_b200;
+extern const struct optdesc opt_b300;
+extern const struct optdesc opt_b600;
+extern const struct optdesc opt_b900;
+extern const struct optdesc opt_b1200;
+extern const struct optdesc opt_b1800;
+extern const struct optdesc opt_b2400;
+extern const struct optdesc opt_b3600;
+extern const struct optdesc opt_b4800;
+extern const struct optdesc opt_b7200;
+extern const struct optdesc opt_b9600;
+extern const struct optdesc opt_b19200;
+extern const struct optdesc opt_b38400;
+extern const struct optdesc opt_b57600;
+extern const struct optdesc opt_b115200;
+extern const struct optdesc opt_b230400;
+extern const struct optdesc opt_b460800;
+extern const struct optdesc opt_b500000;
+extern const struct optdesc opt_b576000;
+extern const struct optdesc opt_b921600;
+extern const struct optdesc opt_b1000000;
+extern const struct optdesc opt_b1152000;
+extern const struct optdesc opt_b1500000;
+extern const struct optdesc opt_b2000000;
+extern const struct optdesc opt_b2500000;
+extern const struct optdesc opt_b3000000;
+extern const struct optdesc opt_b3500000;
+extern const struct optdesc opt_b4000000;
+extern const struct optdesc opt_cs5;
+extern const struct optdesc opt_cs6;
+extern const struct optdesc opt_cs7;
+extern const struct optdesc opt_cs8;
+extern const struct optdesc opt_csize;
+extern const struct optdesc opt_cstopb;
+extern const struct optdesc opt_cread;
+extern const struct optdesc opt_parenb;
+extern const struct optdesc opt_parodd;
+extern const struct optdesc opt_hupcl;
+extern const struct optdesc opt_clocal;
+/*extern const struct optdesc opt_cibaud*/
+extern const struct optdesc opt_crtscts;
+extern const struct optdesc opt_isig;
+extern const struct optdesc opt_icanon;
+extern const struct optdesc opt_xcase;
+extern const struct optdesc opt_echo;
+extern const struct optdesc opt_echoe;
+extern const struct optdesc opt_echok;
+extern const struct optdesc opt_echonl;
+extern const struct optdesc opt_echoctl;
+extern const struct optdesc opt_echoprt;
+extern const struct optdesc opt_echoke;
+extern const struct optdesc opt_flusho;
+extern const struct optdesc opt_noflsh;
+extern const struct optdesc opt_tostop;
+extern const struct optdesc opt_pendin;
+extern const struct optdesc opt_iexten;
+extern const struct optdesc opt_vintr;
+extern const struct optdesc opt_vquit;
+extern const struct optdesc opt_verase;
+extern const struct optdesc opt_vkill;
+extern const struct optdesc opt_veof;
+extern const struct optdesc opt_vtime;
+extern const struct optdesc opt_vmin;
+extern const struct optdesc opt_vswtc;
+extern const struct optdesc opt_vstart;
+extern const struct optdesc opt_vstop;
+extern const struct optdesc opt_vsusp;
+extern const struct optdesc opt_vdsusp;
+extern const struct optdesc opt_veol;
+extern const struct optdesc opt_vreprint;
+extern const struct optdesc opt_vdiscard;
+extern const struct optdesc opt_vwerase;
+extern const struct optdesc opt_vlnext;
+extern const struct optdesc opt_veol2;
+extern const struct optdesc opt_raw;
+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 */
+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 /* !defined(__xio_termios_h_included) */
diff --git a/xio-tun.c b/xio-tun.c
new file mode 100644
index 0000000..2ed0f87
--- /dev/null
+++ b/xio-tun.c
@@ -0,0 +1,209 @@
+/* $Id: xio-tun.c,v 1.2 2007/03/06 21:13:35 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of tun/tap type */
+
+#include "xiosysincludes.h"
+#if WITH_TUN
+#include "xioopen.h"
+
+#include "xio-named.h"
+#include "xio-socket.h"
+#include "xio-ip.h"
+
+#include "xio-tun.h"
+
+
+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 };
+const struct optdesc opt_tun_type = { "tun-type", NULL, OPT_TUN_TYPE, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };
+const struct optdesc opt_iff_no_pi = { "iff-no-pi", "no-pi", OPT_IFF_NO_PI, GROUP_TUN, PH_FD, TYPE_BOOL, OFUNC_SPEC };
+/*0 const struct optdesc opt_interface_addr = { "interface-addr", "address", OPT_INTERFACE_ADDR, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/
+/*0 const struct optdesc opt_interface_netmask = { "interface-netmask", "netmask", OPT_INTERFACE_NETMASK, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/
+const struct optdesc opt_iff_up = { "iff-up", "up", OPT_IFF_UP, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_UP };
+const struct optdesc opt_iff_broadcast = { "iff-broadcast", NULL, OPT_IFF_BROADCAST, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_BROADCAST };
+const struct optdesc opt_iff_debug = { "iff-debug" , NULL, OPT_IFF_DEBUG, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_DEBUG };
+const struct optdesc opt_iff_loopback = { "iff-loopback" , "loopback", OPT_IFF_LOOPBACK, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_LOOPBACK };
+const struct optdesc opt_iff_pointopoint = { "iff-pointopoint", "pointopoint",OPT_IFF_POINTOPOINT, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_POINTOPOINT };
+const struct optdesc opt_iff_notrailers = { "iff-notrailers", "notrailers", OPT_IFF_NOTRAILERS, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_NOTRAILERS };
+const struct optdesc opt_iff_running = { "iff-running", "running", OPT_IFF_RUNNING, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_RUNNING };
+const struct optdesc opt_iff_noarp = { "iff-noarp", "noarp", OPT_IFF_NOARP, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_NOARP };
+const struct optdesc opt_iff_promisc = { "iff-promisc", "promisc", OPT_IFF_PROMISC, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_PROMISC };
+const struct optdesc opt_iff_allmulti = { "iff-allmulti", "allmulti", OPT_IFF_ALLMULTI, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_ALLMULTI };
+const struct optdesc opt_iff_master = { "iff-master", "master", OPT_IFF_MASTER, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_MASTER };
+const struct optdesc opt_iff_slave = { "iff-slave", "slave", OPT_IFF_SLAVE, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_SLAVE };
+const struct optdesc opt_iff_multicast = { "iff-multicast", NULL, OPT_IFF_MULTICAST, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_MULTICAST };
+const struct optdesc opt_iff_portsel = { "iff-portsel", "portsel", OPT_IFF_PORTSEL, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_PORTSEL };
+const struct optdesc opt_iff_automedia = { "iff-automedia", "automedia", OPT_IFF_AUTOMEDIA, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_AUTOMEDIA };
+/*const struct optdesc opt_iff_dynamic = { "iff-dynamic", "dynamic", OPT_IFF_DYNAMIC, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), sizeof(short), IFF_DYNAMIC };*/
+#if LATER
+const struct optdesc opt_route = { "route", NULL, OPT_ROUTE, GROUP_INTERFACE, PH_INIT, TYPE_STRING, OFUNC_SPEC };
+#endif
+
+const struct addrdesc xioaddr_tun = { "tun", 3, xioopen_tun, GROUP_FD|GROUP_CHR|GROUP_NAMED|GROUP_OPEN|GROUP_TUN, 0, 0, 0 HELP(":<ip-addr>/<bits>") };
+// "if-name"=tun3
+// "route"=address/netmask
+// "ip6-route"=address/netmask
+// "iff-broadcast"
+// "iff-debug"
+// "iff-promisc"
+// see .../linux/if.h
+
+
+#if LATER
+/* sub options for route option */
+#define IFOPT_ROUTE 1
+static const struct optdesc opt_route_tos = { "route", NULL, IFOPT_ROUTE, };
+static const struct optname xio_route_options[] = {
+ {"tos", &xio_route_tos }
+} ;
+#endif
+
+static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3) {
+ char *tundevice = NULL;
+ char *tunname = NULL, *tuntype = NULL;
+ int pf = /*! PF_UNSPEC*/ PF_INET;
+ union xiorange_union network;
+ bool no_pi = false;
+ const char *namedargv[] = { "tun", NULL, NULL };
+ int rw = (xioflags & XIO_ACCMODE);
+ bool exists;
+ struct ifreq ifr;
+ int sockfd;
+ char *ifaddr;
+ int result;
+
+ if (argc != 2) {
+ Error2("%s: wrong number of parameters (%d instead of 1)",
+ argv[0], argc-1);
+ }
+
+ if (retropt_string(opts, OPT_TUN_DEVICE, &tundevice) != 0) {
+ tundevice = strdup("/dev/net/tun");
+ }
+
+ /*! socket option here? */
+ retropt_socket_pf(opts, &pf);
+
+ namedargv[1] = tundevice;
+ /* open the tun cloning device */
+ if ((result = _xioopen_named_early(2, namedargv, xfd, groups, &exists, opts)) < 0) {
+ return result;
+ }
+
+ /*========================= the tunnel interface =========================*/
+ Notice("creating tunnel network interface");
+ if ((result = _xioopen_open(tundevice, rw, opts)) < 0)
+ return result;
+ xfd->stream.fd = result;
+
+ /* prepare configuration of the new network interface */
+ memset(&ifr, 0,sizeof(ifr));
+
+ if (retropt_string(opts, OPT_TUN_NAME, &tunname) == 0) {
+ strncpy(ifr.ifr_name, tunname, IFNAMSIZ);
+ free(tunname);
+ } else {
+ ifr.ifr_name[0] = '\0';
+ }
+
+ ifr.ifr_flags = IFF_TUN;
+ if (retropt_string(opts, OPT_TUN_TYPE, &tuntype) == 0) {
+ if (!strcmp(tuntype, "tap")) {
+ ifr.ifr_flags = IFF_TAP;
+ } else if (strcmp(tuntype, "tun")) {
+ Error1("unknown tun-type \"%s\"", tuntype);
+ }
+ }
+
+ if (retropt_bool(opts, OPT_IFF_NO_PI, &no_pi) == 0) {
+ if (no_pi) {
+ ifr.ifr_flags |= IFF_NO_PI;
+#if 0 /* not neccessary for now */
+ } else {
+ ifr.ifr_flags &= ~IFF_NO_PI;
+#endif
+ }
+ }
+
+ if (Ioctl(xfd->stream.fd, TUNSETIFF, &ifr) < 0) {
+ Error3("ioctl(%d, TUNSETIFF, {\"%s\"}: %s",
+ xfd->stream.fd, ifr.ifr_name, strerror(errno));
+ Close(xfd->stream.fd);
+ }
+
+ /*===================== setting interface properties =====================*/
+
+ /* we seem to need a socket for manipulating the interface */
+ if ((sockfd = Socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
+ Error1("socket(PF_INET, SOCK_DGRAM, 0): %s", strerror(errno));
+ sockfd = xfd->stream.fd; /* desparate fallback attempt */
+ }
+
+ /*--------------------- setting interface address and netmask ------------*/
+ if ((ifaddr = strdup(argv[1])) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", argv[1]);
+ return STAT_RETRYLATER;
+ }
+ if ((result = xioparsenetwork(ifaddr, pf, &network)) != STAT_OK) {
+ /*! recover */
+ return result;
+ }
+ socket_init(pf, (union sockaddr_union *)&ifr.ifr_addr);
+ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = network.ip4.netaddr;
+ 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;
+ 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,
+ ifaddr, strerror(errno));
+ }
+ free(ifaddr);
+
+ /*--------------------- setting interface flags --------------------------*/
+ applyopts_single(&xfd->stream, opts, PH_FD);
+
+ if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
+ Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s",
+ sockfd, ifr.ifr_name, strerror(errno));
+ }
+ Debug2("\"%s\": system set flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags);
+ ifr.ifr_flags |= xfd->stream.para.tun.iff_opts[0];
+ ifr.ifr_flags &= ~xfd->stream.para.tun.iff_opts[1];
+ Debug2("\"%s\": xio merged flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags);
+ if (Ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
+ Error4("ioctl(%d, SIOCSIFFLAGS, {\"%s\", %hd}: %s",
+ sockfd, ifr.ifr_name, ifr.ifr_flags, strerror(errno));
+ }
+ ifr.ifr_flags = 0;
+ if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
+ Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s",
+ sockfd, ifr.ifr_name, strerror(errno));
+ }
+ Debug2("\"%s\": resulting flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags);
+
+
+#if LATER
+ applyopts_named(tundevice, opts, PH_FD);
+#endif
+ applyopts(xfd->stream.fd, opts, PH_FD);
+ applyopts_cloexec(xfd->stream.fd, opts);
+
+ applyopts_fchown(xfd->stream.fd, opts);
+
+ if ((result = _xio_openlate(&xfd->stream, opts)) < 0)
+ return result;
+
+ return 0;
+}
+
+#endif /* WITH_TUN */
diff --git a/xio-tun.h b/xio-tun.h
new file mode 100644
index 0000000..53eb6c8
--- /dev/null
+++ b/xio-tun.h
@@ -0,0 +1,33 @@
+/* $Id: xio-tun.h,v 1.2 2007/03/06 21:19:18 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2006-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_tun_h_included
+#define __xio_tun_h_included 1
+
+extern const struct optdesc opt_tun_device;
+extern const struct optdesc opt_tun_name;
+extern const struct optdesc opt_tun_type;
+extern const struct optdesc opt_iff_no_pi;
+extern const struct optdesc opt_interface_addr;
+extern const struct optdesc opt_interface_netmask;
+extern const struct optdesc opt_iff_up;
+extern const struct optdesc opt_iff_broadcast;
+extern const struct optdesc opt_iff_debug;
+extern const struct optdesc opt_iff_loopback;
+extern const struct optdesc opt_iff_pointopoint;
+extern const struct optdesc opt_iff_notrailers;
+extern const struct optdesc opt_iff_running;
+extern const struct optdesc opt_iff_noarp;
+extern const struct optdesc opt_iff_promisc;
+extern const struct optdesc opt_iff_allmulti;
+extern const struct optdesc opt_iff_master;
+extern const struct optdesc opt_iff_slave;
+extern const struct optdesc opt_iff_multicast;
+extern const struct optdesc opt_iff_portsel;
+extern const struct optdesc opt_iff_automedia;
+/*extern const struct optdesc opt_iff_dynamic;*/
+
+extern const struct addrdesc xioaddr_tun;
+
+#endif /* !defined(__xio_tun_h_included) */
diff --git a/xio-udp.c b/xio-udp.c
new file mode 100644
index 0000000..4a23b3d
--- /dev/null
+++ b/xio-udp.c
@@ -0,0 +1,608 @@
+/* $Id: xio-udp.c,v 1.36 2007/02/08 18:27:00 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for handling UDP addresses */
+
+#include "xiosysincludes.h"
+
+#if WITH_UDP && (WITH_IP4 || WITH_IP6)
+
+#include "xioopen.h"
+#include "xio-socket.h"
+#include "xio-ip4.h"
+#include "xio-ip6.h"
+#include "xio-ip.h"
+#include "xio-ipapp.h"
+#include "xio-tcpwrap.h"
+
+#include "xio-udp.h"
+
+
+static
+int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xfd, unsigned groups,
+ int pf, int socktype, int ipproto);
+static
+int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xfd, unsigned groups,
+ int pf, int socktype, int ipproto);
+static
+int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xfd, unsigned groups,
+ int pf, int socktype, int ipproto);
+static
+int xioopen_udp_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_udp_sendto(const char *hostname, const char *servname,
+ struct opt *opts,
+ int xioflags, xiofile_t *xxfd, unsigned groups,
+ int pf, int socktype, int ipproto);
+
+const struct addrdesc addr_udp_connect = { "udp-connect", 3, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_UNSPEC HELP(":<host>:<port>") };
+#if WITH_LISTEN
+const struct addrdesc addr_udp_listen = { "udp-listen", 3, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, IPPROTO_UDP, PF_UNSPEC HELP(":<port>") };
+#endif /* WITH_LISTEN */
+const struct addrdesc addr_udp_sendto = { "udp-sendto", 3, xioopen_udp_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
+const struct addrdesc addr_udp_recvfrom = { "udp-recvfrom", 3, xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
+const struct addrdesc addr_udp_recv = { "udp-recv", 1, xioopen_udp_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
+const struct addrdesc addr_udp_datagram = { "udp-datagram", 3, xioopen_udp_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
+
+#if WITH_IP4
+const struct addrdesc addr_udp4_connect = { "udp4-connect", 3, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_INET HELP(":<host>:<port>") };
+#if WITH_LISTEN
+const struct addrdesc addr_udp4_listen = { "udp4-listen", 3, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_INET, IPPROTO_UDP, PF_INET HELP(":<port>") };
+#endif /* WITH_LISTEN */
+const struct addrdesc addr_udp4_sendto = { "udp4-sendto", 3, xioopen_udp_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
+const struct addrdesc addr_udp4_datagram = { "udp4-datagram",3, xioopen_udp_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<remote-address>:<port>") };
+const struct addrdesc addr_udp4_recvfrom= { "udp4-recvfrom", 3, xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
+const struct addrdesc addr_udp4_recv = { "udp4-recv", 1, xioopen_udp_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
+#endif /* WITH_IP4 */
+
+#if WITH_IP6
+const struct addrdesc addr_udp6_connect = { "udp6-connect", 3, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_INET6 HELP(":<host>:<port>") };
+#if WITH_LISTEN
+const struct addrdesc addr_udp6_listen = { "udp6-listen", 3, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_INET6, IPPROTO_UDP, 0 HELP(":<port>") };
+#endif /* WITH_LISTEN */
+const struct addrdesc addr_udp6_sendto = { "udp6-sendto", 3, xioopen_udp_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
+const struct addrdesc addr_udp6_datagram= { "udp6-datagram", 3, xioopen_udp_datagram,GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
+const struct addrdesc addr_udp6_recvfrom= { "udp6-recvfrom", 3, xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
+const struct addrdesc addr_udp6_recv = { "udp6-recv", 1, xioopen_udp_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
+#endif /* WITH_IP6 */
+
+
+/* we expect the form: port */
+int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *fd,
+ unsigned groups, int pf, int ipproto,
+ int protname) {
+ const char *portname = argv[1];
+ union sockaddr_union us;
+ union sockaddr_union themunion;
+ union sockaddr_union *them = &themunion;
+ int socktype = SOCK_DGRAM;
+ fd_set in, out, expt;
+ bool dofork = false;
+ pid_t pid;
+ char *rangename;
+ char infobuff[256];
+ unsigned char buff1[1];
+ socklen_t uslen;
+ socklen_t themlen;
+ int result;
+
+ if (argc != 2) {
+ Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
+ }
+
+ if (pf == PF_UNSPEC) {
+#if WITH_IP4 && WITH_IP6
+ pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
+#elif WITH_IP6
+ pf = PF_INET6;
+#else
+ pf = PF_INET;
+#endif
+ }
+
+ retropt_socket_pf(opts, &pf);
+
+ if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ 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],
+ fd->stream.para.socket.ip.res_opts[0]);
+
+ if (false) {
+ ;
+#if WITH_IP4
+ } else if (pf == PF_INET) {
+ us.ip4.sin_port = parseport(portname, ipproto);
+#endif
+#if WITH_IP6
+ } else if (pf == PF_INET6) {
+ us.ip6.sin6_port = parseport(portname, ipproto);
+#endif
+ } else {
+ Error1("xioopen_ipdgram_listen(): unknown address family %d", pf);
+ }
+
+ retropt_bool(opts, OPT_FORK, &dofork);
+
+ if (dofork) {
+ if (!(xioflags & XIO_MAYFORK)) {
+ Error("option fork not allowed here");
+ return STAT_NORETRY;
+ }
+ }
+
+#if WITH_IP4 /*|| WITH_IP6*/
+ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
+ if (parserange(rangename, pf, &fd->stream.para.socket.range) < 0) {
+ free(rangename);
+ return STAT_NORETRY;
+ }
+ free(rangename);
+ fd->stream.para.socket.dorange = true;
+ }
+#endif
+
+#if WITH_LIBWRAP
+ xio_retropt_tcpwrap(&fd->stream, opts);
+#endif /* WITH_LIBWRAP */
+
+ if (retropt_ushort(opts, OPT_SOURCEPORT, &fd->stream.para.socket.ip.sourceport)
+ >= 0) {
+ fd->stream.para.socket.ip.dosourceport = true;
+ }
+ retropt_bool(opts, OPT_LOWPORT, &fd->stream.para.socket.ip.lowport);
+
+ while (true) { /* we loop with fork or prohibited packets */
+ /* now wait for some packet on this datagram socket, get its sender
+ address, connect there, and return */
+ int one = 1;
+ char infobuff[256];
+ union sockaddr_union _sockname;
+ union sockaddr_union *la = &_sockname; /* local address */
+
+ if ((fd->stream.fd = Socket(pf, socktype, ipproto)) < 0) {
+ Error4("socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
+ if (Setsockopt(fd->stream.fd, opt_so_reuseaddr.major,
+ opt_so_reuseaddr.minor, &one, sizeof(one)) < 0) {
+ Warn6("setsockopt(%d, %d, %d, {%d}, "F_Zd"): %s",
+ fd->stream.fd, opt_so_reuseaddr.major,
+ opt_so_reuseaddr.minor, one, sizeof(one), strerror(errno));
+ }
+ applyopts_cloexec(fd->stream.fd, opts);
+ applyopts(fd->stream.fd, opts, PH_PREBIND);
+ applyopts(fd->stream.fd, opts, PH_BIND);
+ if (Bind(fd->stream.fd, &us.soa, uslen) < 0) {
+ Error4("bind(%d, {%s}, "F_Zd"): %s", fd->stream.fd,
+ sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)),
+ uslen, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ /* under some circumstances bind() fills sockaddr with interesting info. */
+ if (Getsockname(fd->stream.fd, &us.soa, &uslen) < 0) {
+ Error4("getsockname(%d, %p, {%d}): %s",
+ fd->stream.fd, &us.soa, uslen, strerror(errno));
+ }
+ applyopts(fd->stream.fd, opts, PH_PASTBIND);
+
+ 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.fd, &in);
+ while (Select(fd->stream.fd+1, &in, &out, &expt, NULL) < 0) {
+ if (errno != EINTR) break;
+ }
+
+ themlen = socket_init(pf, them);
+ do {
+ result = Recvfrom(fd->stream.fd, buff1, 1, MSG_PEEK,
+ &them->soa, &themlen);
+ } while (result < 0 && errno == EINTR);
+ if (result < 0) {
+ Error5("recvfrom(%d, %p, 1, MSG_PEEK, {%s}, {"F_Zu"}): %s",
+ fd->stream.fd, buff1,
+ sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)),
+ themlen, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+
+ Notice1("accepting UDP connection from %s",
+ sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)));
+
+ if (xiocheckpeer(&fd->stream, them, la) < 0) {
+ /* drop packet */
+ char buff[512];
+ Recv(fd->stream.fd, buff, sizeof(buff), 0);
+ continue;
+ }
+ Info1("permitting UDP connection from %s",
+ sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)));
+
+ if (dofork) {
+ pid = Fork();
+ 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);
+ }
+ break;
+ }
+ /* server: continue loop with select */
+ /* 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.fd) < 0) {
+ Info2("close(%d): %s", fd->stream.fd, strerror(errno));
+ }
+ Notice1("forked off child process "F_pid, pid);
+ Sleep(1); /*! give child a chance to consume the old packet */
+
+ continue;
+ }
+ break;
+ }
+
+ applyopts(fd->stream.fd, opts, PH_CONNECT);
+ if ((result = Connect(fd->stream.fd, &them->soa, themlen)) < 0) {
+ Error4("connect(%d, {%s}, "F_Zd"): %s",
+ fd->stream.fd,
+ sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)),
+ themlen, strerror(errno));
+ return STAT_RETRYLATER;
+ }
+
+ fd->stream.howtoend = END_SHUTDOWN;
+ applyopts_fchown(fd->stream.fd, opts);
+ applyopts(fd->stream.fd, opts, PH_LATE);
+
+ if ((result = _xio_openlate(&fd->stream, opts)) < 0)
+ return result;
+
+ return 0;
+}
+
+
+static
+int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xxfd, unsigned groups,
+ int pf, int socktype, int ipproto) {
+ int result;
+
+ if (argc != 3) {
+ Error2("%s: wrong number of parameters (%d instead of 2)",
+ argv[0], argc-1);
+ return STAT_NORETRY;
+ }
+ if ((result = _xioopen_udp_sendto(argv[1], argv[2], opts, xioflags, xxfd,
+ groups, pf, socktype, ipproto))
+ != STAT_OK) {
+ return result;
+ }
+ _xio_openlate(&xxfd->stream, opts);
+ return STAT_OK;
+}
+
+static
+int _xioopen_udp_sendto(const char *hostname, const char *servname,
+ struct opt *opts,
+ int xioflags, xiofile_t *xxfd, unsigned groups,
+ int pf, int socktype, int ipproto) {
+ xiosingle_t *xfd = &xxfd->stream;
+ union sockaddr_union us;
+ socklen_t uslen;
+ int feats = 3; /* option bind supports address and port */
+ bool needbind = false;
+ int result;
+
+ xfd->howtoend = END_SHUTDOWN;
+ retropt_int(opts, OPT_SO_TYPE, &socktype);
+
+ /* ...res_opts[] */
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
+ applyopts(-1, opts, PH_INIT);
+
+ xfd->salen = sizeof(xfd->peersa);
+ if ((result =
+ xiogetaddrinfo(hostname, servname, 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;
+ }
+ uslen = socket_init(pf, &us);
+ 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;
+ }
+
+ if (retropt_ushort(opts, OPT_SOURCEPORT,
+ &xfd->para.socket.ip.sourceport) >= 0) {
+ switch (pf) {
+#if WITH_IP4
+ case PF_INET:
+ us.ip4.sin_port = htons(xfd->para.socket.ip.sourceport);
+ break;
+#endif
+#if WITH_IP6
+ case PF_INET6:
+ us.ip6.sin6_port = htons(xfd->para.socket.ip.sourceport);
+ break;
+#endif
+ }
+ needbind = true;
+ }
+
+ retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport);
+ if (xfd->para.socket.ip.lowport) {
+ switch (pf) {
+#if WITH_IP4
+ case PF_INET:
+ /*!!! this is buggy */
+ us.ip4.sin_port = htons(xfd->para.socket.ip.lowport); break;
+#endif
+#if WITH_IP6
+ case PF_INET6:
+ /*!!! this is buggy */
+ us.ip6.sin6_port = htons(xfd->para.socket.ip.lowport); break;
+#endif
+ }
+ needbind = true;
+ }
+
+ xfd->dtype = XIODATA_RECVFROM;
+ return _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
+ opts, xioflags, xfd, groups,
+ pf, socktype, ipproto);
+}
+
+
+static
+int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xxfd, unsigned groups,
+ int pf, int socktype, int ipproto) {
+ xiosingle_t *xfd = &xxfd->stream;
+ char *rangename;
+ char *hostname;
+ int result;
+
+ if (argc != 3) {
+ Error2("%s: wrong number of parameters (%d instead of 2)",
+ argv[0], argc-1);
+ return STAT_NORETRY;
+ }
+
+ if ((hostname = strdup(argv[1])) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", argv[1]);
+ return STAT_RETRYLATER;
+ }
+
+ result =
+ _xioopen_udp_sendto(hostname, argv[2], opts, xioflags, xxfd, groups,
+ pf, socktype, ipproto);
+ free(hostname);
+ if (result != STAT_OK) {
+ return result;
+ }
+
+ xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
+
+ xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family;
+
+ /* only accept packets with correct remote ports */
+ xfd->para.socket.ip.sourceport = ntohs(xfd->peersa.ip4.sin_port);
+ xfd->para.socket.ip.dosourceport = true;
+
+ /* 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) {
+ free(rangename);
+ return STAT_NORETRY;
+ }
+ xfd->para.socket.dorange = true;
+ xfd->dtype |= XIOREAD_RECV_CHECKRANGE;
+ free(rangename);
+ }
+
+#if WITH_LIBWRAP
+ xio_retropt_tcpwrap(xfd, opts);
+#endif /* WITH_LIBWRAP */
+
+ _xio_openlate(xfd, opts);
+ return STAT_OK;
+}
+
+
+static
+int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xfd, unsigned groups,
+ int pf, int socktype, int ipproto) {
+ union sockaddr_union us;
+ socklen_t uslen = sizeof(us);
+ 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;
+ }
+
+ xfd->stream.howtoend = END_NONE;
+ retropt_socket_pf(opts, &pf);
+ if (pf == PF_UNSPEC) {
+#if WITH_IP4 && WITH_IP6
+ pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
+#elif WITH_IP6
+ pf = PF_INET6;
+#else
+ pf = PF_INET;
+#endif
+ }
+
+ if ((result =
+ xiogetaddrinfo(NULL, argv[1], pf, socktype, ipproto,
+ &us, &uslen, xfd->stream.para.socket.ip.res_opts[0],
+ xfd->stream.para.socket.ip.res_opts[1]))
+ != STAT_OK) {
+ return result;
+ }
+ if (pf == PF_UNSPEC) {
+ pf = us.soa.sa_family;
+ }
+
+ {
+ union sockaddr_union la;
+ socklen_t lalen = sizeof(la);
+
+ if (retropt_bind(opts, pf, socktype, ipproto, &la.soa, &lalen, 1,
+ xfd->stream.para.socket.ip.res_opts[0],
+ xfd->stream.para.socket.ip.res_opts[1])
+ != STAT_NOACTION) {
+ switch (pf) {
+#if WITH_IP4
+ case PF_INET: us.ip4.sin_addr = la.ip4.sin_addr; break;
+#endif
+#if WITH_IP6
+ case PF_INET6: us.ip6.sin6_addr = la.ip6.sin6_addr; break;
+#endif
+ }
+ needbind = true;
+ }
+ }
+
+ if (retropt_ushort(opts, OPT_SOURCEPORT, &xfd->stream.para.socket.ip.sourceport) >= 0) {
+ xfd->stream.para.socket.ip.dosourceport = true;
+ }
+ retropt_bool(opts, OPT_LOWPORT, &xfd->stream.para.socket.ip.lowport);
+
+ xfd->stream.dtype = XIODATA_RECVFROM_ONE;
+ if ((result =
+ _xioopen_dgram_recvfrom(&xfd->stream, xioflags, &us.soa, uslen,
+ opts, pf, socktype, ipproto, E_ERROR))
+ != STAT_OK) {
+ return result;
+ }
+ _xio_openlate(&xfd->stream, opts);
+ return STAT_OK;
+}
+
+
+static
+int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
+ int xioflags, xiofile_t *xfd, unsigned groups,
+ int pf, int socktype, int ipproto) {
+ union sockaddr_union us;
+ socklen_t uslen = sizeof(us);
+ char *rangename;
+ int result;
+
+ if (argc != 2) {
+ Error2("%s: wrong number of parameters (%d instead of 1)",
+ argv[0], argc-1);
+ return STAT_NORETRY;
+ }
+
+ retropt_socket_pf(opts, &pf);
+ if (pf == PF_UNSPEC) {
+#if WITH_IP4 && WITH_IP6
+ pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
+#elif WITH_IP6
+ pf = PF_INET6;
+#else
+ pf = PF_INET;
+#endif
+ }
+
+ if ((result =
+ xiogetaddrinfo(NULL, argv[1], pf, socktype, ipproto,
+ &us, &uslen, xfd->stream.para.socket.ip.res_opts[0],
+ xfd->stream.para.socket.ip.res_opts[1]))
+ != STAT_OK) {
+ return result;
+ }
+ if (pf == PF_UNSPEC) {
+ pf = us.soa.sa_family;
+ }
+
+#if 1
+ {
+ union sockaddr_union la;
+ socklen_t lalen = sizeof(la);
+
+ if (retropt_bind(opts, pf, socktype, ipproto,
+ &xfd->stream.para.socket.la.soa, &lalen, 1,
+ xfd->stream.para.socket.ip.res_opts[0],
+ xfd->stream.para.socket.ip.res_opts[1])
+ != STAT_NOACTION) {
+ switch (pf) {
+#if WITH_IP4
+ case PF_INET:
+ us.ip4.sin_addr = xfd->stream.para.socket.la.ip4.sin_addr; break;
+#endif
+#if WITH_IP6
+ case PF_INET6:
+ us.ip6.sin6_addr = xfd->stream.para.socket.la.ip6.sin6_addr; break;
+#endif
+ }
+ } else {
+ xfd->stream.para.socket.la.soa.sa_family = pf;
+ }
+ }
+#endif
+
+#if WITH_IP4 /*|| WITH_IP6*/
+ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
+ if (parserange(rangename, pf, &xfd->stream.para.socket.range) < 0) {
+ return STAT_NORETRY;
+ }
+ xfd->stream.para.socket.dorange = true;
+ }
+#endif
+
+#if WITH_LIBWRAP
+ xio_retropt_tcpwrap(&xfd->stream, opts);
+#endif /* WITH_LIBWRAP */
+
+ if (retropt_ushort(opts, OPT_SOURCEPORT,
+ &xfd->stream.para.socket.ip.sourceport)
+ >= 0) {
+ xfd->stream.para.socket.ip.dosourceport = true;
+ }
+ retropt_bool(opts, OPT_LOWPORT, &xfd->stream.para.socket.ip.lowport);
+
+ xfd->stream.dtype = XIODATA_RECV;
+ if ((result = _xioopen_dgram_recv(&xfd->stream, xioflags, &us.soa, uslen,
+ opts, pf, socktype, ipproto, E_ERROR))
+ != STAT_OK) {
+ return result;
+ }
+ _xio_openlate(&xfd->stream, opts);
+ return result;
+}
+
+#endif /* WITH_UDP && (WITH_IP4 || WITH_IP6) */
diff --git a/xio-udp.h b/xio-udp.h
new file mode 100644
index 0000000..3ccf0dd
--- /dev/null
+++ b/xio-udp.h
@@ -0,0 +1,32 @@
+/* $Id: xio-udp.h,v 1.12 2007/02/05 19:57:09 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_udp_h_included
+#define __xio_udp_h_included 1
+
+extern const struct addrdesc addr_udp_connect;
+extern const struct addrdesc addr_udp_listen;
+extern const struct addrdesc addr_udp_sendto;
+extern const struct addrdesc addr_udp_datagram;
+extern const struct addrdesc addr_udp_recvfrom;
+extern const struct addrdesc addr_udp_recv;
+extern const struct addrdesc addr_udp4_connect;
+extern const struct addrdesc addr_udp4_listen;
+extern const struct addrdesc addr_udp4_sendto;
+extern const struct addrdesc addr_udp4_datagram;
+extern const struct addrdesc addr_udp4_recvfrom;
+extern const struct addrdesc addr_udp4_recv;
+extern const struct addrdesc addr_udp6_connect;
+extern const struct addrdesc addr_udp6_listen;
+extern const struct addrdesc addr_udp6_sendto;
+extern const struct addrdesc addr_udp6_datagram;
+extern const struct addrdesc addr_udp6_recvfrom;
+extern const struct addrdesc addr_udp6_recv;
+
+extern int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
+ int rw, xiofile_t *fd,
+ unsigned groups, int af, int ipproto,
+ int protname);
+
+#endif /* !defined(__xio_udp_h_included) */
diff --git a/xio-unix.c b/xio-unix.c
new file mode 100644
index 0000000..c0d9ecb
--- /dev/null
+++ b/xio-unix.c
@@ -0,0 +1,738 @@
+/* $Id: xio-unix.c,v 1.34 2007/03/06 21:25:12 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of UNIX socket type */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-socket.h"
+#include "xio-listen.h"
+#include "xio-unix.h"
+#include "xio-named.h"
+
+
+#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);
+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);
+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 */
+
+const struct addrdesc addr_unix_connect = { "unix-connect", 3, xioopen_unix_connect, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
+#if WITH_LISTEN
+const struct addrdesc addr_unix_listen = { "unix-listen", 3, xioopen_unix_listen, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
+#endif /* WITH_LISTEN */
+const struct addrdesc addr_unix_sendto = { "unix-sendto", 3, xioopen_unix_sendto, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_DGRAM, 0 HELP(":<filename>") };
+const struct addrdesc addr_unix_recvfrom= { "unix-recvfrom", 3, xioopen_unix_recvfrom, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
+const struct addrdesc addr_unix_recv = { "unix-recv", 1, xioopen_unix_recv, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
+const struct addrdesc addr_unix_client = { "unix-client", 3, xioopen_unix_client, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, 0, 0 HELP(":<filename>") };
+#if WITH_ABSTRACT_UNIXSOCKET
+const struct addrdesc xioaddr_abstract_connect = { "abstract-connect", 3, xioopen_abstract_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
+#if WITH_LISTEN
+const struct addrdesc xioaddr_abstract_listen = { "abstract-listen", 3, xioopen_abstract_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
+#endif /* WITH_LISTEN */
+const struct addrdesc xioaddr_abstract_sendto = { "abstract-sendto", 3, xioopen_abstract_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_DGRAM, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_abstract_recvfrom= { "abstract-recvfrom", 3, xioopen_abstract_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_abstract_recv = { "abstract-recv", 1, xioopen_abstract_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_abstract_client = { "abstract-client", 3, xioopen_abstract_client, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, 0, 0 HELP(":<filename>") };
+#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 };
+
+
+socklen_t
+xiosetunix(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 {
+ 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));
+ }
+ saun->sun_path[0] = '\0'; /* so it's abstract */
+ strncpy(saun->sun_path+1, path, sizeof(saun->sun_path)-1);
+ if (tight) {
+ len = sizeof(struct sockaddr_un)-sizeof(saun->sun_path)+
+ MIN(pathlen+1, sizeof(saun->sun_path));
+ } 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) {
+ /* we expect the form: filename */
+ const char *name;
+ xiosingle_t *xfd = &xxfd->stream;
+ struct sockaddr_un us;
+ socklen_t uslen;
+ bool tight = true;
+ struct opt *opts0 = NULL;
+ bool opt_unlink_early = false;
+ bool opt_unlink_close = true;
+ 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);
+
+ retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
+ name = argv[1];
+ uslen = xiosetunix(&us, name, false, 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);
+ }
+ xfd->opt_unlink_close = true;
+ }
+
+ xfd->howtoend = END_SHUTDOWN;
+
+ 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));
+ }
+ }
+ }
+
+ /* 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))
+ != 0)
+ return result;
+ return 0;
+}
+#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) {
+ /* we expect the form: filename */
+ const char *name;
+ struct single *xfd = &xxfd->stream;
+ struct sockaddr_un them, us;
+ socklen_t themlen, uslen;
+ bool tight = true;
+ bool needbind = false;
+ bool opt_unlink_close = 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, 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)
+ != STAT_NOACTION) {
+ needbind = true;
+ }
+
+ if (opt_unlink_close) {
+ if ((xfd->unlink_close = strdup(name)) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", name);
+ }
+ 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 ((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_unix_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;
+ bool opt_unlink_close = 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);
+
+ xfd->howtoend = END_SHUTDOWN;
+
+ retropt_int(opts, OPT_SO_TYPE, &socktype);
+
+ retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
+ name = argv[1];
+ xfd->salen = xiosetunix(&xfd->peersa.un, name, false, tight);
+
+ 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)
+ != STAT_NOACTION) {
+ needbind = true;
+ }
+
+ if (opt_unlink_close) {
+ if ((xfd->unlink_close = strdup(name)) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", name);
+ }
+ xfd->opt_unlink_close = 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_unix_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;
+ bool opt_unlink_early = false;
+ bool opt_unlink_close = 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, false, tight);
+
+ xfd->stream.howtoend = END_NONE;
+ retropt_int(opts, OPT_SO_TYPE, &socktype);
+ retropt_bind(opts, pf, socktype, 0, (struct sockaddr *)&us, &uslen, 1, 0, 0);
+ retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
+ retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
+
+ if (opt_unlink_close) {
+ if ((xfd->stream.unlink_close = strdup(name)) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", name);
+ }
+ 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));
+ }
+ }
+ }
+
+ 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_unix_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;
+ bool opt_unlink_early = false;
+ bool opt_unlink_close = 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, false, tight);
+
+#if 1 /*!!! why bind option? */
+ retropt_bind(opts, pf, socktype, ipproto, &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));
+ }
+ }
+ }
+
+ 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);
+ }
+ xfd->stream.opt_unlink_close = true;
+ }
+
+ 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_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;
+
+ if (argc != 2) {
+ Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
+ }
+
+ xfd->howtoend = END_SHUTDOWN;
+ retropt_int(opts, OPT_SO_TYPE, &socktype);
+
+ 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, false, tight);
+
+ retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
+
+ if (retropt_bind(opts, pf, socktype, 0, &us.soa, &uslen, 0, 0, 0)
+ != STAT_NOACTION) {
+ needbind = true;
+ }
+
+ if (opt_unlink_close) {
+ if ((xfd->unlink_close = strdup(name)) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", name);
+ }
+ xfd->opt_unlink_close = 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);
+ }
+
+ applyopts(-1, opts, PH_INIT);
+ if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
+
+ 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))
+ != 0) {
+ return result;
+ }
+ xfd->dtype = XIODATA_RECVFROM;
+ }
+ }
+ if ((result = _xio_openlate(xfd, opts)) < 0) {
+ return result;
+ }
+ return 0;
+}
+
+
+#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;
+ }
+
+ socket_un_init(&us);
+
+ retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
+ name = argv[1];
+ uslen = xiosetunix(&us, name, true, tight);
+
+ xfd->howtoend = END_SHUTDOWN;
+
+ 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;
+ 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);
+
+ xfd->howtoend = END_SHUTDOWN;
+
+ 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);
+
+ xfd->stream.howtoend = END_NONE;
+ 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);
+ }
+
+ xfd->howtoend = END_SHUTDOWN;
+ 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
new file mode 100644
index 0000000..3cea77e
--- /dev/null
+++ b/xio-unix.h
@@ -0,0 +1,29 @@
+/* $Id: xio-unix.h,v 1.6 2007/02/08 18:30:08 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_unix_h_included
+#define __xio_unix_h_included 1
+
+extern const struct addrdesc addr_unix_connect;
+extern const struct addrdesc addr_unix_listen;
+extern const struct addrdesc addr_unix_sendto;
+extern const struct addrdesc addr_unix_recvfrom;
+extern const struct addrdesc addr_unix_recv;
+extern const struct addrdesc addr_unix_client;
+extern const struct addrdesc xioaddr_abstract_connect;
+extern const struct addrdesc xioaddr_abstract_listen;
+extern const struct addrdesc xioaddr_abstract_sendto;
+extern const struct addrdesc xioaddr_abstract_recvfrom;
+extern const struct addrdesc xioaddr_abstract_recv;
+extern const struct addrdesc xioaddr_abstract_client;
+
+extern const struct optdesc opt_unix_tightsocklen;
+
+extern socklen_t
+xiosetunix(struct sockaddr_un *saun,
+ const char *path,
+ bool abstract,
+ bool tight);
+
+#endif /* !defined(__xio_unix_h_included) */
diff --git a/xio.h b/xio.h
new file mode 100644
index 0000000..649f854
--- /dev/null
+++ b/xio.h
@@ -0,0 +1,404 @@
+/* $Id: xio.h,v 1.66 2007/03/06 21:25:51 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_h_included
+#define __xio_h_included 1
+
+#if 1 /*!*/
+#include "mytypes.h"
+#include "sysutils.h"
+#endif
+
+#define XIO_MAXSOCK 2
+
+/* Linux 2.2.10 */
+#define HAVE_STRUCT_LINGER 1
+
+#define LINETERM_RAW 0
+#define LINETERM_CR 1
+#define LINETERM_CRNL 2
+
+struct addrdesc;
+struct opt;
+
+/* the flags argument of xioopen */
+#define XIO_RDONLY O_RDONLY /* asserted to be 0 */
+#define XIO_WRONLY O_WRONLY /* asserted to be 1 */
+#define XIO_RDWR O_RDWR /* asserted to be 2 */
+#define XIO_ACCMODE O_ACCMODE /* must be 3 */
+#define XIO_MAYFORK 4 /* address is allowed to fork the program (fork) */
+#define XIO_MAYCHILD 8 /* address is allowed to fork off a child (exec)*/
+#define XIO_MAYEXEC 16 /* address is allowed to exec a prog (exec+nofork) */
+#define XIO_MAYCONVERT 32 /* address is allowed to perform modifications on the
+ stream data, e.g. SSL, REALDINE; CRLF */
+
+/* the status flags of xiofile_t */
+#define XIO_DOESFORK XIO_MAYFORK
+#define XIO_DOESCHILD XIO_MAYCHILD
+#define XIO_DOESEXEC XIO_MAYEXEC
+#define XIO_DOESCONVERT XIO_MAYCONVERT
+
+
+/* methods for reading and writing, and for related checks */
+#define XIODATA_READMASK 0xf000 /* mask for basic r/w method */
+#define XIOREAD_STREAM 0x1000 /* read() (default) */
+#define XIOREAD_RECV 0x2000 /* recvfrom() */
+#define XIOREAD_PTY 0x4000 /* handle EIO */
+#define XIOREAD_READLINE 0x5000 /* ... */
+#define XIOREAD_OPENSSL 0x6000 /* SSL_read() */
+#define XIODATA_WRITEMASK 0x0f00 /* mask for basic r/w method */
+#define XIOWRITE_STREAM 0x0100 /* write() (default) */
+#define XIOWRITE_SENDTO 0x0200 /* sendto() */
+#define XIOWRITE_PIPE 0x0300 /* write() to alternate (pipe) Fd */
+#define XIOWRITE_2PIPE 0x0400 /* write() to alternate (2pipe) Fd */
+#define XIOWRITE_READLINE 0x0500 /* check for prompt */
+#define XIOWRITE_OPENSSL 0x0600 /* SSL_write() */
+/* modifiers to XIODATA_READ_RECV */
+#define XIOREAD_RECV_CHECKPORT 0x0001 /* recv, check peer port */
+#define XIOREAD_RECV_CHECKADDR 0x0002 /* recv, check peer address */
+#define XIOREAD_RECV_CHECKRANGE 0x0004 /* recv, check if peer addr in range */
+#define XIOREAD_RECV_ONESHOT 0x0008 /* give EOF after first packet */
+#define XIOREAD_RECV_SKIPIP 0x0010 /* recv, skip IPv4 header */
+#define XIOREAD_RECV_FROM 0x0020 /* remember peer for replying */
+
+/* combinations */
+#define XIODATA_MASK (XIODATA_READMASK|XIODATA_WRITEMASK)
+#define XIODATA_STREAM (XIOREAD_STREAM|XIOWRITE_STREAM)
+#define XIODATA_RECVFROM (XIOREAD_RECV|XIOWRITE_SENDTO|XIOREAD_RECV_CHECKPORT|XIOREAD_RECV_CHECKADDR|XIOREAD_RECV_FROM)
+#define XIODATA_RECVFROM_SKIPIP (XIODATA_RECVFROM|XIOREAD_RECV_SKIPIP)
+#define XIODATA_RECVFROM_ONE (XIODATA_RECVFROM|XIOREAD_RECV_ONESHOT)
+#define XIODATA_RECVFROM_SKIPIP_ONE (XIODATA_RECVFROM_SKIPIP|XIOREAD_RECV_ONESHOT)
+#define XIODATA_RECV (XIOREAD_RECV|XIOWRITE_SENDTO|XIOREAD_RECV_CHECKRANGE)
+#define XIODATA_RECV_SKIPIP (XIODATA_RECV|XIOREAD_RECV_SKIPIP)
+#define XIODATA_PIPE (XIOREAD_STREAM|XIOWRITE_PIPE)
+#define XIODATA_2PIPE (XIOREAD_STREAM|XIOWRITE_2PIPE)
+#define XIODATA_PTY (XIOREAD_PTY|XIOWRITE_STREAM)
+#define XIODATA_READLINE (XIOREAD_READLINE|XIOWRITE_STREAM)
+#define XIODATA_OPENSSL (XIOREAD_OPENSSL|XIOWRITE_OPENSSL)
+
+
+/* these are the values allowed for the "enum xiotag tag" flag of the "struct
+ single" and "union bipipe" (xiofile_t) structures. */
+enum xiotag {
+ XIO_TAG_INVALID, /* the record is not in use */
+ XIO_TAG_RDONLY, /* this is a single read-only stream */
+ XIO_TAG_WRONLY, /* this is a single write-only stream */
+ XIO_TAG_RDWR, /* this is a single read-write stream */
+ XIO_TAG_DUAL /* this is a dual stream, consisting of two single
+ streams */
+} ;
+
+/* global XIO options/parameters */
+typedef struct {
+ bool strictopts;
+ const char *pipesep;
+ const char *paramsep;
+ const char *optionsep;
+ char ip4portsep;
+ char ip6portsep; /* do not change, might be hardcoded somewhere! */
+ char logopt; /* 'm' means "switch to syslog when entering daemon mode" */
+ const char *syslogfac; /* syslog facility (only with mixed mode) */
+ char default_ip; /* default prot.fam for IP based listen ('4' or '6') */
+ char preferred_ip; /* preferred prot.fam. for name resolution ('0' for
+ unspecified, '4', or '6') */
+} xioopts_t;
+
+/* pack the description of a lock file */
+typedef struct {
+ const char *lockfile; /* name of lockfile; NULL if no locking */
+ bool waitlock; /* dont't exit when already locked */
+ struct timespec intervall; /* polling intervall */
+} xiolock_t;
+
+extern xioopts_t xioopts;
+
+#define MAXARGV 8
+
+/* a non-dual file descriptor */
+typedef struct single {
+ enum xiotag tag; /* see enum xiotag */
+ const struct addrdesc *addr;
+ int flags;
+ /* until here, keep consistent with bipipe.common !!! */
+#if WITH_RETRY
+ unsigned int retry; /* retry opening this many times */
+ bool forever; /* retry opening forever */
+ struct timespec intervall; /* wait so long between retries */
+#endif /* WITH_RETRY */
+ bool ignoreeof; /* option ignoreeof; do not pass eof condition to app*/
+ int eof; /* 1..exec'd child has died, but no explicit eof
+ occurred
+ 2..fd0 has reached EOF (definitely; never with
+ ignoreeof! */
+ size_t wsize; /* write always this size; 0..all available */
+ size_t readbytes; /* read only so many bytes; 0...unlimited */
+ size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/
+ xiolock_t lock; /* parameters of lockfile */
+ bool havelock; /* we are happy owner of the above lock */
+ bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */
+ /* until here, keep consistent with bipipe.dual ! */
+ int argc; /* number of fields in argv */
+ const char *argv[MAXARGV]; /* address keyword, required args */
+ struct opt *opts; /* the options of this address */
+ int lineterm; /* 0..dont touch; 1..CR; 2..CRNL on extern data */
+ int fd;
+ bool opt_unlink_close; /* option unlink_close */
+ char *unlink_close; /* name of a symlink or unix socket to be removed */
+ int dtype;
+ enum {
+ END_UNSPEC, /* after init, when no end-close... option */
+ END_NONE, /* no action */
+ END_CLOSE, /* close() */
+ END_SHUTDOWN, /* shutdown() */
+ END_UNLINK, /* unlink() */
+ END_KILL, /* has subprocess */
+ END_CLOSE_KILL, /* first close fd, then kill subprocess */
+ END_SHUTDOWN_KILL /* first shutdown fd, then kill subprocess */
+ } howtoend;
+#if _WITH_SOCKET
+ union sockaddr_union peersa;
+ socklen_t salen;
+#endif /* _WITH_SOCKET */
+#if WITH_TERMIOS
+ bool ttyvalid; /* the following struct is valid */
+ struct termios savetty; /* save orig tty settings for later restore */
+#endif /* WITH_TERMIOS */
+ const char *name; /* only with END_UNLINK */
+ int (*sigchild)(struct single *); /* callback after sigchild */
+ pid_t ppid; /* parent pid, only if we send it signals */
+ union {
+ struct {
+ int fdout; /* use fd for output */
+ } bipipe;
+#if _WITH_SOCKET
+ struct {
+ struct timeval connect_timeout; /* how long to hang in connect() */
+ union sockaddr_union la; /* local socket address */
+ bool emptyiseof; /* with dgram: empty packet means EOF */
+ bool dorange;
+ union xiorange_union range; /* restrictions for peer address */
+#if _WITH_IP4 || _WITH_IP6
+ struct {
+ unsigned int res_opts[2]; /* bits to be set in _res.options are
+ at [0], bits to be cleared are at [1] */
+ bool dosourceport;
+ uint16_t sourceport; /* host byte order */
+ bool lowport;
+#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
+ bool dolibwrap;
+ char *libwrapname;
+ char *tcpwrap_etc;
+ char *hosts_allow_table;
+ char *hosts_deny_table;
+#endif
+ } ip;
+#endif /* _WITH_IP4 || _WITH_IP6 */
+ } socket;
+#endif /* _WITH_SOCKET */
+ struct {
+ pid_t pid; /* child PID, with EXEC: */
+ int fdout; /* use fd for output if two pipes */
+ } exec;
+#if WITH_READLINE
+ struct {
+ char *history_file;
+ char *prompt; /* static prompt, passed to readline() */
+ size_t dynbytes; /* length of buffer for dynamic prompt */
+ char *dynprompt; /* the dynamic prompt */
+ char *dynend; /* current end of dynamic prompt */
+#if HAVE_REGEX_H
+ bool hasnoecho; /* following regex is set */
+ regex_t noecho; /* if it matches the prompt, input is silent */
+#endif
+ } readline;
+#endif /* WITH_READLINE */
+#if WITH_OPENSSL
+ struct {
+ struct timeval connect_timeout; /* how long to hang in connect() */
+ SSL *ssl;
+ SSL_CTX* ctx;
+ } openssl;
+#endif /* WITH_OPENSSL */
+#if WITH_TUN
+ struct {
+ short iff_opts[2]; /* ifr flags, using OFUNC_OFFSET_MASKS */
+ } tun;
+#endif /* WITH_TUN */
+ } para;
+} xiosingle_t;
+
+/* rw: 0..read, 1..write, 2..r/w */
+/* when implementing a new address type take care of following topics:
+ . be aware that xioopen_single is used for O_RDONLY, O_WRONLY, and O_RDWR data
+ . which options are allowed (option groups)
+ . implement application of all these options
+ . set FD_CLOEXEC on new file descriptors BEFORE the cloexec option might be
+ applied
+ .
+*/
+
+typedef union bipipe {
+ enum xiotag tag;
+ struct {
+ enum xiotag tag;
+ const struct addrdesc *addr;
+ int flags;
+ } common;
+ struct single stream;
+ struct {
+ enum xiotag tag;
+ const struct addrdesc *addr;
+ int flags; /* compatible to fcntl(.., F_GETFL, ..) */
+#if WITH_RETRY
+ unsigned retry; /* retry opening this many times */
+ bool forever; /* retry opening forever */
+ struct timespec intervall; /* wait so long between retries */
+#endif /* WITH_RETRY */
+ bool ignoreeof;
+ int eof; /* fd0 has reached EOF */
+ size_t wsize; /* write always this size; 0..all available */
+ size_t readbytes; /* read only so many bytes; 0...unlimited */
+ size_t actbytes; /* so many bytes still to be read */
+ xiolock_t lock; /* parameters of lockfile */
+ bool havelock; /* we are happy owner of the above lock */
+ xiosingle_t *stream[2]; /* input stream, output stream */
+ } dual;
+} xiofile_t;
+
+
+struct addrdesc {
+ const char *defname; /* main (canonical) name of address */
+ int directions; /* 1..read, 2..write, 3..both */
+ int (*func)(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *fd, unsigned groups,
+ int arg1, int arg2, int arg3);
+ unsigned groups;
+ int arg1;
+ int arg2;
+ int arg3;
+#if WITH_HELP
+ const char *syntax;
+#endif
+} ;
+
+#define XIO_WRITABLE(s) (((s)->common.flags+1)&2)
+#define XIO_READABLE(s) (((s)->common.flags+1)&1)
+#define XIO_RDSTREAM(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[0]:&(s)->stream)
+#define XIO_WRSTREAM(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[1]:&(s)->stream)
+#define XIO_GETRDFD(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[0]->fd:(s)->stream.fd)
+#define XIO_GETWRFD(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[1]->fd:(((s)->stream.dtype&XIODATA_WRITEMASK)==XIOWRITE_2PIPE)?(s)->stream.para.exec.fdout:(((s)->stream.dtype&XIODATA_WRITEMASK)==XIOWRITE_PIPE)?(s)->stream.para.bipipe.fdout:(s)->stream.fd)
+#define XIO_EOF(s) (XIO_RDSTREAM(s)->eof && !XIO_RDSTREAM(s)->ignoreeof)
+
+typedef unsigned long flags_t;
+
+union integral {
+ int u_bool;
+ uint8_t u_byte;
+ gid_t u_gidt;
+ int u_int;
+ long u_long;
+#if HAVE_TYPE_LONGLONG
+ long long u_longlong;
+#endif
+ double u_double;
+ mode_t u_modet;
+ short u_short;
+ size_t u_sizet;
+ char *u_string;
+ uid_t u_uidt;
+ unsigned int u_uint;
+ unsigned long u_ulong;
+ unsigned short u_ushort;
+ uint16_t u_2bytes;
+ void *u_ptr;
+ flags_t u_flag;
+ struct {
+ uint8_t *b_data;
+ size_t b_len;
+ } u_bin;
+ struct timeval u_timeval;
+#if HAVE_STRUCT_LINGER
+ struct linger u_linger;
+#endif /* HAVE_STRUCT_LINGER */
+#if HAVE_STRUCT_TIMESPEC
+ struct timespec u_timespec;
+#endif /* HAVE_STRUCT_TIMESPEC */
+#if HAVE_STRUCT_IP_MREQ || HAVE_STRUCT_IP_MREQN
+ struct {
+ char *multiaddr;
+ char *param2; /* address, interface */
+#if HAVE_STRUCT_IP_MREQN
+ char ifindex[IF_NAMESIZE+1];
+#endif
+ } u_ip_mreq;
+#endif
+#if WITH_IP4
+ in_addr_t u_ip4addr;
+#endif
+} ;
+
+/* some aliases */
+#define u_off u_long /* please report when this causes problems */
+
+#if defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T
+# if HAVE_BASIC_OFF64_T==5
+# define u_off64 u_long
+# elif HAVE_BASIC_OFF64_T==7
+# define u_off64 u_longlong
+# else
+# error "unexpected size of off64_t, please report this as bug"
+# endif
+#endif /* defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T */
+
+
+/* this handles option instances, for communication between subroutines */
+struct opt {
+ const struct optdesc *desc;
+ union integral value;
+} ;
+
+extern const char *PIPESEP;
+extern xiofile_t *sock[XIO_MAXSOCK];
+
+/* return values of xioopensingle */
+#define STAT_OK 0
+#define STAT_WARNING 1
+#define STAT_EXIT 2
+#define STAT_NOACTION 3 /* by retropt_* when option not applied */
+#define STAT_RETRYNOW -1 /* only after timeouts useful ? */
+#define STAT_RETRYLATER -2 /* address cannot be opened, but user might
+ change something in the filesystem etc. to
+ make this process succeed later. */
+#define STAT_NORETRY -3 /* address syntax error, not implemented etc;
+ not even by external changes correctable */
+
+extern int xioinitialize(void);
+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 flags);
+extern int xioopensingle(char *addr, struct single *xfd, int xioflags);
+extern int xioopenhelp(FILE *of, int level);
+
+/* must be outside function for use by childdied handler */
+extern xiofile_t *sock1, *sock2;
+extern pid_t diedunknown1; /* child died before it is registered */
+extern pid_t diedunknown2;
+extern pid_t diedunknown3;
+extern pid_t diedunknown4;
+
+extern int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *));
+extern int xio_opt_signal(pid_t pid, int signum);
+extern void childdied(int signum);
+
+extern ssize_t xioread(xiofile_t *sock1, void *buff, size_t bufsiz);
+extern ssize_t xiopending(xiofile_t *sock1);
+extern ssize_t xiowrite(xiofile_t *sock1, const void *buff, size_t bufsiz);
+extern int xioshutdown(xiofile_t *sock, int how);
+
+extern int xioclose(xiofile_t *sock);
+extern void xioexit(void);
+
+extern int (*xiohook_newchild)(void); /* xio calls this function from a new child process */
+
+#endif /* !defined(__xio_h_included) */
diff --git a/xioclose.c b/xioclose.c
new file mode 100644
index 0000000..026e55c
--- /dev/null
+++ b/xioclose.c
@@ -0,0 +1,118 @@
+/* $Id: xioclose.c,v 1.26 2007/01/25 21:36:11 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this is the source of the extended close function */
+
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+#include "xiolockfile.h"
+
+#include "xio-termios.h"
+
+
+/* close the xio fd; must be valid and "simple" */
+int xioclose1(struct single *pipe) {
+
+ if (pipe->tag == XIO_TAG_INVALID) {
+ Notice("xioclose1(): invalid file descriptor");
+ errno = EINVAL;
+ return -1;
+ }
+
+#if WITH_READLINE
+ if ((pipe->dtype & XIODATA_MASK) == XIODATA_READLINE) {
+ Write_history(pipe->para.readline.history_file);
+ /*xiotermios_setflag(pipe->fd, 3, ECHO|ICANON);*/ /* error when pty closed */
+ }
+#endif /* WITH_READLINE */
+#if WITH_OPENSSL
+ if ((pipe->dtype & XIODATA_MASK) == XIODATA_OPENSSL) {
+ if (pipe->para.openssl.ssl) {
+ /* e.g. on TCP connection refused, we do not yet have this set */
+ sycSSL_shutdown(pipe->para.openssl.ssl);
+ sycSSL_free(pipe->para.openssl.ssl);
+ pipe->para.openssl.ssl = NULL;
+ }
+ Close(pipe->fd); pipe->fd = -1;
+ if (pipe->para.openssl.ctx) {
+ sycSSL_CTX_free(pipe->para.openssl.ctx);
+ pipe->para.openssl.ctx = NULL;
+ }
+ } else
+#endif /* WITH_OPENSSL */
+#if WITH_TERMIOS
+ if (pipe->ttyvalid) {
+ if (Tcsetattr(pipe->fd, 0, &pipe->savetty) < 0) {
+ Warn2("cannot restore terminal settings on fd %d: %s",
+ pipe->fd, strerror(errno));
+ }
+ }
+#endif /* WITH_TERMIOS */
+ if (pipe->fd >= 0) {
+ switch (pipe->howtoend) {
+ case END_KILL: case END_SHUTDOWN_KILL: case END_CLOSE_KILL:
+ if (pipe->para.exec.pid > 0) {
+ if (Kill(pipe->para.exec.pid, SIGTERM) < 0) {
+ Msg2(errno==ESRCH?E_INFO:E_WARN, "kill(%d, SIGTERM): %s",
+ pipe->para.exec.pid, strerror(errno));
+ }
+ }
+ default:
+ break;
+ }
+ switch (pipe->howtoend) {
+ case END_CLOSE: case END_CLOSE_KILL:
+ if (Close(pipe->fd) < 0) {
+ Info2("close(%d): %s", pipe->fd, strerror(errno)); } break;
+#if WITH_SOCKET
+ case END_SHUTDOWN: case END_SHUTDOWN_KILL:
+ if (Shutdown(pipe->fd, 2) < 0) {
+ Info3("shutdown(%d, %d): %s", pipe->fd, 2, strerror(errno)); }
+ break;
+#endif /* WITH_SOCKET */
+ case END_UNLINK: if (Unlink((const char *)pipe->name) < 0) {
+ Warn2("unlink(\"%s\"): %s", pipe->name, strerror(errno)); }
+ break;
+ case END_NONE: default: break;
+ }
+ }
+
+ /* unlock */
+ if (pipe->havelock) {
+ xiounlock(pipe->lock.lockfile);
+ pipe->havelock = false;
+ }
+ if (pipe->opt_unlink_close && pipe->unlink_close) {
+ if (Unlink(pipe->unlink_close) < 0) {
+ Info2("unlink(\"%s\"): %s", pipe->unlink_close, strerror(errno));
+ }
+ free(pipe->unlink_close);
+ }
+
+ pipe->tag = XIO_TAG_INVALID;
+ return 0; /*! */
+}
+
+
+/* close the xio fd */
+int xioclose(xiofile_t *file) {
+ int result;
+
+ if (file->tag == XIO_TAG_INVALID) {
+ Error("xioclose(): invalid file descriptor");
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (file->tag == XIO_TAG_DUAL) {
+ result = xioclose1(file->dual.stream[0]);
+ result |= xioclose1(file->dual.stream[1]);
+ file->tag = XIO_TAG_INVALID;
+ } else {
+ result = xioclose1(&file->stream);
+ }
+ return result;
+}
+
diff --git a/xioconfig.h b/xioconfig.h
new file mode 100644
index 0000000..4da8c5d
--- /dev/null
+++ b/xioconfig.h
@@ -0,0 +1,119 @@
+/* $Id: xioconfig.h,v 1.27 2007/03/06 21:26:23 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xioconfig_h_included
+#define __xioconfig_h_included 1
+
+/* ensure some dependencies between configure WITH defines. must be included
+ past config.h */
+
+#if WITH_STDIO || WITH_FDNUM
+# define WITH_FD 1
+#endif
+
+#if WITH_FILE || WITH_GOPEN || WITH_CREAT || WITH_PIPE
+# define WITH_OPEN 1
+#endif
+
+#if WITH_OPEN || WITH_PIPE || WITH_UNIX || WITH_PTY
+# define WITH_NAMED 1
+#endif
+
+#if WITH_SOCKS4A
+# define WITH_SOCKS4 1
+#endif
+
+#if WITH_SOCKS4 || WITH_PROXY
+# define WITH_TCP 1
+# define WITH_IP4 1 /* currently this socks implementation does not work
+ with IP6 */
+#endif
+
+#if WITH_OPENSSL
+# define WITH_TCP 1
+# define WITH_IP4 1
+#endif
+
+#if WITH_IP6
+# if !defined(HAVE_NETINET_IP6_H)
+# undef WITH_IP6
+# endif
+#endif
+
+#if !WITH_IP4 && !WITH_IP6
+# if WITH_TCP || WITH_UDP || WITH_RAWIP
+# define WITH_IP4 1
+# endif
+#endif
+
+#if WITH_UNIX || WITH_IP4 || WITH_IP6 || WITH_SOCKS4 || WITH_RAWIP
+# define WITH_SOCKET 1
+#else
+# undef WITH_SOCKET
+#endif
+
+#if !WITH_SOCKET
+# undef WITH_LISTEN
+#endif
+
+#if !WITH_LISTEN
+# undef WITH_LIBWRAP
+#endif
+
+#if WITH_SOCKET || WITH_TUN
+# define _WITH_SOCKET 1
+#endif
+
+#if WITH_IP4 || WITH_TUN
+# define _WITH_IP4 1
+#endif
+
+#if WITH_IP6 || WITH_TUN
+# define _WITH_IP6 1
+#endif
+
+#if WITH_NAMED || WITH_TUN
+# define _WITH_NAMED 1
+#endif
+
+#if WITH_FILE || WITH_TUN
+# define _WITH_FILE 1
+#endif
+
+
+#if HAVE_DEV_PTMX && HAVE_GRANTPT && HAVE_UNLOCKPT && HAVE_PTSNAME
+#else
+# undef HAVE_DEV_PTMX
+#endif
+
+#if HAVE_DEV_PTC /* && HAVE_GRANTPT && HAVE_UNLOCKPT && HAVE_PTSNAME */
+#else
+# undef HAVE_DEV_PTC
+#endif
+
+
+/* MacOS does not seem to have any pty implementation */
+#if WITH_PTY && (HAVE_DEV_PTC || HAVE_DEV_PTMX || HAVE_OPENPTY)
+# define HAVE_PTY 1
+#else
+# undef HAVE_PTY
+#endif
+
+#ifndef HAVE_TYPE_SOCKLEN
+ typedef int socklen_t;
+#endif /* !defined(HAVE_TYPE_SOCKLEN) */
+
+#ifndef HAVE_TYPE_UINT8
+ typedef unsigned char uint8_t;
+#endif
+
+#ifndef HAVE_TYPE_UINT16
+ typedef unsigned short uint16_t;
+#endif
+
+#ifndef HAVE_TYPE_UINT32
+ typedef unsigned int uint32_t;
+#endif
+
+#endif /* !defined(__xioconfig_h_included) */
diff --git a/xiodiag.c b/xiodiag.c
new file mode 100644
index 0000000..5f60133
--- /dev/null
+++ b/xiodiag.c
@@ -0,0 +1,21 @@
+/* $Id: xiodiag.c,v 1.3 2003/05/21 05:16:38 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001, 2003 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains source for some diagnostics */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xiodiag.h"
+
+
+const char *ddirection[] = {
+ "reading", "writing", "reading and writing" } ;
+
+/* compliant with S_ macros (sys/stat.h) */
+const char *filetypenames[] = {
+ "undef", "named pipe", "character device", "undef",
+ "block device", "undef", "directory", "undef",
+ "regular file", "undef", "symbolic link", "undef",
+ "local socket", "undef", "undef", "\"MT\"?"} ;
diff --git a/xiodiag.h b/xiodiag.h
new file mode 100644
index 0000000..802798b
--- /dev/null
+++ b/xiodiag.h
@@ -0,0 +1,11 @@
+/* $Id: xiodiag.h,v 1.2 2001/11/04 17:13:22 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xiodiag_h_included
+#define __xiodiag_h_included 1
+
+extern const char *ddirection[];
+extern const char *filetypenames[];
+
+#endif /* !defined(__xiodiag_h_included) */
diff --git a/xioexit.c b/xioexit.c
new file mode 100644
index 0000000..fe99a42
--- /dev/null
+++ b/xioexit.c
@@ -0,0 +1,21 @@
+/* $Id: xioexit.c,v 1.10 2005/03/13 12:19:11 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2005 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for the extended exit function */
+
+#include "xiosysincludes.h"
+#include "xio.h"
+
+
+/* this function closes all open xio sockets on exit, if they are still open.
+ It must be registered with atexit(). */
+void xioexit(void) {
+ int i;
+
+ for (i = 0; i < XIO_MAXSOCK; ++i) {
+ if (sock[i] != NULL && sock[i]->tag != XIO_TAG_INVALID) {
+ xioclose(sock[i]);
+ }
+ }
+}
diff --git a/xiohelp.c b/xiohelp.c
new file mode 100644
index 0000000..508e596
--- /dev/null
+++ b/xiohelp.c
@@ -0,0 +1,168 @@
+/* $Id: xiohelp.c,v 1.19 2007/02/05 21:07:07 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for the help function */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xiohelp.h"
+
+#if WITH_HELP
+
+/* keep consistent with xioopts.h:enum e_types ! */
+static const char *optiontypenames[] = {
+ "CONST", "BIN", "BOOL", "BYTE",
+ "INT", "LONG", "STRING", "PTRDIFF",
+ "SHORT", "SIZE_T", "SOCKADDR", "UNSIGNED-INT",
+ "UNSIGNED-LONG","UNSIGNED-SHORT","MODE_T", "GID_T",
+ "UID_T", "INT[3]", "STRUCT-TIMEVAL", "STRUCT-TIMESPEC",
+#if HAVE_STRUCT_LINGER
+ "STRUCT-LINGER",
+#endif
+ "DOUBLE", "STRING-NULL", "LONG-LONG",
+ "OFF_T", "OFF64_T",
+#if HAVE_STRUCT_IP_MREQN
+ "STRUCT-IP_MREQN",
+#elif HAVE_STRUCT_IP_MREQN
+ "STRUCT-IP_MREQ",
+#endif
+ "IP4NAME",
+} ;
+
+
+/* keep consistent with xioopts.h:#define GROUP_* ! */
+static const char *addressgroupnames[] = {
+ "FD", "FIFO", "CHR", "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", "undef"
+} ;
+
+
+/* keep consistent with xioopts.h:enum ephase ! */
+static char *optionphasenames[] = {
+ "ALL", "INIT", "EARLY",
+ "PREOPEN", "OPEN", "PASTOPEN",
+ "PRESOCKET", "SOCKET", "PASTSOCKET",
+ "PREBIGEN", "BIGEN", "PASTBIGEN",
+ "FD",
+ "PREBIND", "BIND", "PASTBIND",
+ "PRELISTEN", "LISTEN", "PASTLISTEN",
+ "PRECONNECT", "CONNECT", "PASTCONNECT",
+ "PREACCEPT", "ACCEPT", "PASTACCEPT",
+ "CONNECTED",
+ "PREFORK", "FORK", "PASTFORK",
+ "LATE", "LATE2",
+ "PREEXEC", "EXEC", "SPECIFIC",
+ NULL
+} ;
+
+
+/* print a line about a single option */
+static int xiohelp_option(FILE *of, const struct optname *on, const char *name) {
+ int j;
+ unsigned int groups;
+ bool occurred;
+
+ fprintf(of, " %s\tgroups=", name);
+ groups = on->desc->group; occurred = false;
+ for (j = 0; j < 32; ++j) {
+ if (groups & 1) {
+ if (occurred) { fputc(',', of); }
+ fprintf(of, "%s", addressgroupnames[j]);
+ occurred = true;
+ }
+ groups >>= 1;
+ }
+ fprintf(of, "\tphase=%s", optionphasenames[on->desc->phase]);
+ fprintf(of, "\ttype=%s", optiontypenames[on->desc->type]);
+ fputc('\n', of);
+ return 0;
+}
+
+int xioopenhelp(FILE *of,
+ int level /* 0..only addresses, 1..and options */
+ ) {
+ const struct addrname *an;
+ const struct optname *on;
+ int i, j;
+ unsigned int groups;
+ bool occurred;
+
+ fputs(" bi-address:\n", of);
+ fputs(" pipe[,<opts>]\tgroups=FD,FIFO\n", of);
+ if (level == 2) {
+ fputs(" echo is an alias for pipe\n", of);
+ fputs(" fifo is an alias for pipe\n", of);
+ }
+ fputs(" <single-address>!!<single-address>\n", of);
+ fputs(" <single-address>\n", of);
+ fputs(" single-address:\n", of);
+ fputs(" <address-head>[,<opts>]\n", of);
+ fputs(" address-head:\n", of);
+ an = &addressnames[0];
+ i = 0;
+ while (addressnames[i].name) {
+ if (!strcmp(an->name, an->desc->defname)) {
+ /* it is a canonical address name */
+ fprintf(of, " %s", an->name);
+ if (an->desc->syntax) {
+ fputs(an->desc->syntax, of); }
+ fputs("\tgroups=", of);
+ groups = an->desc->groups; occurred = false;
+ for (j = 0; j < 32; ++j) {
+ if (groups & 1) {
+ if (occurred) { fputc(',', of); }
+ fprintf(of, "%s", addressgroupnames[j]);
+ occurred = true;
+ }
+ groups >>= 1;
+ }
+ fputc('\n', of);
+ } else if (level == 2) {
+ fprintf(of, " %s is an alias name for %s\n", an->name, an->desc->defname);
+ }
+ ++an; ++i;
+ }
+ if (level == 2) {
+ fputs(" <num> is a short form for fd:<num>\n", of);
+ fputs(" <filename> is a short form for gopen:<filename>\n", of);
+ }
+
+ if (level <= 0) return 0;
+
+ fputs(" opts:\n", of);
+ fputs(" <opt>{,<opts>}:\n", of);
+ fputs(" opt:\n", of);
+ on = optionnames;
+ while (on->name != NULL) {
+ if (on->desc->nickname!= NULL
+ && !strcmp(on->name, on->desc->nickname)) {
+ if (level == 2) {
+ fprintf(of, " %s is an alias for %s\n", on->name, on->desc->defname);
+ } else {
+ xiohelp_option(of, on, on->name);
+ }
+ } else if (on->desc->nickname == NULL &&
+ !strcmp(on->name, on->desc->defname)) {
+ xiohelp_option(of, on, on->name);
+ } else if (level == 2) {
+ if (!strcmp(on->name, on->desc->defname)) {
+ xiohelp_option(of, on, on->name);
+ } else {
+ fprintf(of, " %s is an alias for %s\n", on->name, on->desc->defname);
+ }
+ }
+ ++on;
+ }
+ fflush(of);
+ return 0;
+}
+
+#endif /* WITH_HELP */
diff --git a/xiohelp.h b/xiohelp.h
new file mode 100644
index 0000000..7953ac8
--- /dev/null
+++ b/xiohelp.h
@@ -0,0 +1,12 @@
+/* $Id: xiohelp.h,v 1.2 2001/11/04 17:19:21 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xiohelp_h_included
+#define __xiohelp_h_included 1
+
+extern int xioopenhelp(FILE *of,
+ int level /* 0..only addresses, 1..and options */
+ );
+
+#endif /* !defined(__xiohelp_h_included) */
diff --git a/xioinitialize.c b/xioinitialize.c
new file mode 100644
index 0000000..84e4e3c
--- /dev/null
+++ b/xioinitialize.c
@@ -0,0 +1,187 @@
+/* $Id: xioinitialize.c,v 1.17 2006/12/28 14:21:41 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for the initialize function */
+
+#include "xiosysincludes.h"
+
+#include "xioopen.h"
+#include "xiolockfile.h"
+
+#include "xio-openssl.h" /* xio_reset_fips_mode() */
+
+static int xioinitialized;
+xiofile_t *sock[XIO_MAXSOCK];
+int (*xiohook_newchild)(void); /* xio calls this function from a new child
+ process */
+
+
+/* returns 0 on success or != if an error occurred */
+int xioinitialize(void) {
+ if (xioinitialized) return 0;
+
+ /* configure and .h's cannot guarantee this */
+ assert(sizeof(uint8_t)==1);
+ assert(sizeof(uint16_t)==2);
+ assert(sizeof(uint32_t)==4);
+
+ /* assertions regarding O_ flags - important for XIO_READABLE() etc. */
+ assert(O_RDONLY==0);
+ assert(O_WRONLY==1);
+ assert(O_RDWR==2);
+
+ assert(SHUT_RD==0);
+ assert(SHUT_WR==1);
+ assert(SHUT_RDWR==2);
+
+ /* some assertions about termios */
+#if WITH_TERMIOS
+#ifdef CRDLY
+ assert(3 << opt_crdly.arg3 == CRDLY);
+#endif
+#ifdef TABDLY
+ assert(3 << opt_tabdly.arg3 == TABDLY);
+#endif
+ assert(3 << opt_csize.arg3 == CSIZE);
+ {
+ union {
+ struct termios termarg;
+ tcflag_t flags[4];
+#if HAVE_TERMIOS_ISPEED
+ speed_t speeds[sizeof(struct termios)/sizeof(speed_t)];
+#endif
+ } tdata;
+ tdata.termarg.c_iflag = 0x12345678;
+ tdata.termarg.c_oflag = 0x23456789;
+ tdata.termarg.c_cflag = 0x3456789a;
+ tdata.termarg.c_lflag = 0x456789ab;
+ assert(tdata.termarg.c_iflag == tdata.flags[0]);
+ assert(tdata.termarg.c_oflag == tdata.flags[1]);
+ assert(tdata.termarg.c_cflag == tdata.flags[2]);
+ assert(tdata.termarg.c_lflag == tdata.flags[3]);
+#if HAVE_TERMIOS_ISPEED
+ tdata.termarg.c_ispeed = 0x56789abc;
+ tdata.termarg.c_ospeed = 0x6789abcd;
+ assert(tdata.termarg.c_ispeed == tdata.speeds[ISPEED_OFFSET]);
+ assert(tdata.termarg.c_ospeed == tdata.speeds[OSPEED_OFFSET]);
+#endif
+ }
+#endif
+
+ /* these dependencies required in applyopts() for OFUNC_FCNTL */
+ assert(F_GETFD == F_SETFD-1);
+ assert(F_GETFL == F_SETFL-1);
+
+ {
+ const char *default_ip;
+ default_ip = getenv("SOCAT_DEFAULT_LISTEN_IP");
+ if (default_ip != NULL) {
+ switch (default_ip[0]) {
+ case '4':
+ case '6':
+ xioopts.default_ip = default_ip[0]; break;
+ }
+ }
+ }
+ {
+ const char *preferred_ip;
+ preferred_ip = getenv("SOCAT_PREFERRED_RESOLVE_IP");
+ if (preferred_ip != NULL) {
+ switch (preferred_ip[0]) {
+ case '4':
+ case '6':
+ xioopts.preferred_ip = preferred_ip[0]; break;
+ default:
+ xioopts.preferred_ip = '0'; break;
+ }
+ }
+ }
+
+ if (Atexit(xioexit) < 0) {
+ Error("atexit(xioexit) failed");
+ return -1;
+ }
+
+ xioinitialized = 1;
+ return 0;
+}
+
+
+/* well, this function is not for initialization, but I could not find a better
+ place for it
+ it is called in the child process after fork
+ it drops the locks of the xiofile's so only the parent owns them
+ */
+void xiodroplocks(void) {
+ int i;
+
+ for (i = 0; i < XIO_MAXSOCK; ++i) {
+ if (sock[i] != NULL && sock[i]->tag != XIO_TAG_INVALID) {
+ xiofiledroplock(sock[i]);
+ }
+ }
+}
+
+
+/* consider an invokation like this:
+ socat -u exec:'some program that accepts data' tcp-l:...,fork
+ we do not want the program to be killed by the first tcp-l sub process, it's
+ better if it survives all sub processes. Thus, it must not be killed if the
+ sub process delivers EOF. Also, a socket that is reused in sub processes
+ should not be shut down (affects the connection), but closed (affects only
+ sub processes copy of file descriptor) */
+static int xio_nokill(xiofile_t *sock) {
+ int result = 0;
+ switch (sock->tag) {
+ case XIO_TAG_INVALID:
+ default:
+ return -1;
+ case XIO_TAG_DUAL:
+ if ((result = xio_nokill((xiofile_t *)sock->dual.stream[0])) != 0)
+ return result;
+ result = xio_nokill((xiofile_t *)sock->dual.stream[1]);
+ break;
+ case XIO_TAG_RDONLY:
+ case XIO_TAG_WRONLY:
+ case XIO_TAG_RDWR:
+ /* here is the core of this function */
+ switch (sock->stream.howtoend) {
+ case END_SHUTDOWN_KILL: sock->stream.howtoend = END_CLOSE; break;
+ case END_CLOSE_KILL: sock->stream.howtoend = END_CLOSE; break;
+ case END_SHUTDOWN: sock->stream.howtoend = END_CLOSE; break;
+ default: break;
+ }
+ break;
+ }
+ return result;
+}
+
+/* call this function immediately after fork() in child process */
+/* it performs some neccessary actions
+ 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) {
+ result = 1;
+ }
+#endif /* WITH_FIPS */
+ /* some locks belong to parent process, so "drop" them now */
+ if (xiohook_newchild) {
+ if ((*xiohook_newchild)() != 0) {
+ Exit(1);
+ }
+ }
+
+ /* change XIO_SHUTDOWN_KILL to XIO_SHUTDOWN */
+ if (sock1 != NULL) {
+ int result2;
+ result2 = xio_nokill(sock1);
+ if (result2 < 0) Exit(1);
+ result |= result2;
+ }
+
+ return result;
+}
diff --git a/xiolayer.c b/xiolayer.c
new file mode 100644
index 0000000..2e0bc18
--- /dev/null
+++ b/xiolayer.c
@@ -0,0 +1,25 @@
+/* $Id: xiolayer.c,v 1.7 2005/08/18 19:56:05 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2005 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for common options */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xiolayer.h"
+
+/****** for ALL addresses - by application ******/
+const struct optdesc opt_ignoreeof = { "ignoreeof", NULL, OPT_IGNOREEOF, GROUP_APPL, PH_LATE, TYPE_BOOL, OFUNC_EXT, (int)(&((struct single *)0)->ignoreeof), sizeof(((struct single *)0)->ignoreeof) };
+const struct optdesc opt_cr = { "cr", NULL, OPT_CR, GROUP_APPL, PH_LATE, TYPE_CONST, OFUNC_EXT, (int)(&((struct single *)0)->lineterm), sizeof(((struct single *)0)->lineterm), LINETERM_CR };
+const struct optdesc opt_crnl = { "crnl", NULL, OPT_CRNL, GROUP_APPL, PH_LATE, TYPE_CONST, OFUNC_EXT, (int)(&((struct single *)0)->lineterm), sizeof(((struct single *)0)->lineterm), LINETERM_CRNL };
+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 };
+/****** APPL addresses ******/
+#if WITH_RETRY
+const struct optdesc opt_forever = { "forever", NULL, OPT_FOREVER, GROUP_RETRY, PH_INIT, TYPE_BOOL, OFUNC_EXT, (int)(&((struct single *)0)->forever), sizeof(((struct single *)0)->forever) };
+const struct optdesc opt_intervall = { "intervall", NULL, OPT_INTERVALL, GROUP_RETRY, PH_INIT, TYPE_TIMESPEC, OFUNC_EXT, (int)(&((struct single *)0)->intervall), sizeof(((struct single *)0)->intervall) };
+const struct optdesc opt_retry = { "retry", NULL, OPT_RETRY, GROUP_RETRY, PH_INIT, TYPE_UINT, OFUNC_EXT, (int)(&((struct single *)0)->retry), sizeof(((struct single *)0)->retry) };
+#endif
+
diff --git a/xiolayer.h b/xiolayer.h
new file mode 100644
index 0000000..743cbc7
--- /dev/null
+++ b/xiolayer.h
@@ -0,0 +1,18 @@
+/* $Id: xiolayer.h,v 1.5 2005/08/18 19:56:05 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2005 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xiolayer_h_included
+#define __xiolayer_h_included 1
+
+extern const struct optdesc opt_ignoreeof;
+extern const struct optdesc opt_cr;
+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_forever;
+extern const struct optdesc opt_intervall;
+extern const struct optdesc opt_retry;
+
+#endif /* !defined(__xiolayer_h_included) */
diff --git a/xiolockfile.c b/xiolockfile.c
new file mode 100644
index 0000000..c297394
--- /dev/null
+++ b/xiolockfile.c
@@ -0,0 +1,118 @@
+/* $Id: xiolockfile.c,v 1.2 2006/02/08 19:51:24 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2005-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains socats explicit locking mechanisms */
+
+#include "xiosysincludes.h"
+
+#include "compat.h"
+#include "mytypes.h"
+#include "error.h"
+#include "utils.h"
+#include "sysutils.h"
+
+#include "sycls.h"
+
+#include "xio.h"
+#include "xiolockfile.h"
+
+
+/* returns 0 if it could create lock; 1 if the lock exists; -1 on error */
+int xiogetlock(const char *lockfile) {
+ char *s;
+ struct stat strat;
+ int fd;
+ pid_t pid;
+ char pidbuf[3*sizeof(pid_t)+1];
+ size_t bytes;
+
+ if (Lstat(lockfile, &strat) == 0) {
+ return 1;
+ }
+ switch (errno) {
+ case ENOENT: break;
+ default:
+ Error3("Lstat(\"%s\", %p): %s", lockfile, &strat, strerror(errno));
+ return -1;
+ }
+ /* in this moment, the file did not exist */
+
+ if ((s = Malloc(strlen(lockfile)+8)) == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ strcpy(s, lockfile);
+ strcat(s, ".XXXXXX");
+
+ if ((fd = Mkstemp(s)) < 0) {
+ Error2("mkstemp(\"%s\"): %s", s, strerror(errno));
+ return -1;
+ }
+
+ pid = Getpid();
+ bytes = sprintf(pidbuf, F_pid, pid);
+ Write(fd, pidbuf, bytes);
+ Close(fd);
+
+ /* Chmod(lockfile, 0600); */
+ if (Link(s, lockfile) < 0) {
+ int _errno = errno;
+ Error3("link(\"%s\", \"%s\"): %s", s, lockfile, strerror(errno));
+ Unlink(s);
+ errno = _errno;
+ return -1;
+ }
+ Unlink(s);
+
+ return 0;
+}
+
+int xiounlock(const char *lockfile) {
+ return Unlink(lockfile);
+}
+
+
+/* returns 0 when it could create lock, or -1 on error */
+int xiowaitlock(const char *lockfile, struct timespec *intervall) {
+ int rc;
+ int level = E_NOTICE; /* first print a notice */
+
+ while ((rc = xiogetlock(lockfile)) == 1) {
+ Msg1(level, "waiting for lock \"%s\"", lockfile);
+ level = E_INFO; /* afterwards only make info */
+ Nanosleep(intervall, NULL);
+ }
+ return rc;
+}
+
+
+/* returns 0 when it could obtain lock or the lock is not valid
+ (lockfile==NULL), 1 if it could not obtain the lock, or -1 on error */
+int xiolock(xiolock_t *lock) {
+ int result;
+
+ if (lock->lockfile == NULL) {
+ return 0;
+ }
+ if (lock->waitlock) {
+ result = xiowaitlock(lock->lockfile, &lock->intervall);
+ } else {
+ result = xiogetlock(lock->lockfile);
+ }
+ if (result == 0) {
+ Info1("obtained lock \"%s\"", lock->lockfile);
+ }
+ return result;
+}
+
+
+int xiofiledroplock(xiofile_t *xfd) {
+ if (xfd->tag == XIO_TAG_DUAL) {
+ xiofiledroplock((xiofile_t *)xfd->dual.stream[0]);
+ xiofiledroplock((xiofile_t *)xfd->dual.stream[1]);
+ } else {
+ xfd->stream.havelock = false;
+ }
+ return 0;
+}
diff --git a/xiolockfile.h b/xiolockfile.h
new file mode 100644
index 0000000..ff22288
--- /dev/null
+++ b/xiolockfile.h
@@ -0,0 +1,17 @@
+/* $Id: xiolockfile.h,v 1.1 2005/08/18 19:42:05 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2005 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xiolockfile_h_included
+#define __xiolockfile_h_included 1
+
+/* preferred lock handling functions */
+extern int xiolock(xiolock_t *lock);
+extern int xiounlock(const char *lockfile);
+
+/* more "internal" functions */
+extern int xiogetlock(const char *lockfile);
+extern int xiowaitlock(const char *lockfile, struct timespec *intervall);
+extern int xiofiledroplock(xiofile_t *xfd);
+
+#endif /* !defined(__xiolockfile_h_included) */
diff --git a/xiomodes.h b/xiomodes.h
new file mode 100644
index 0000000..afeae15
--- /dev/null
+++ b/xiomodes.h
@@ -0,0 +1,45 @@
+/* $Id: xiomodes.h,v 1.13 2007/03/06 21:22:29 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xiomodes_h_included
+#define __xiomodes_h_included 1
+
+#include "xiolayer.h"
+#include "xio-process.h"
+#include "xio-fd.h"
+#include "xio-fdnum.h"
+#include "xio-stdio.h"
+#include "xio-named.h"
+#include "xio-file.h"
+#include "xio-creat.h"
+#include "xio-gopen.h"
+#include "xio-pipe.h"
+#if WITH_SOCKET
+#include "xio-socket.h"
+#include "xio-listen.h"
+#include "xio-unix.h"
+#include "xio-rawip.h"
+#include "xio-ip.h"
+#if WITH_IP4
+#include "xio-ip4.h"
+#endif /* WITH_IP4 */
+#include "xio-ip6.h"
+#include "xio-ipapp.h"
+#include "xio-tcp.h"
+#include "xio-udp.h"
+#include "xio-socks.h"
+#include "xio-proxy.h"
+#endif /* WITH_SOCKET */
+#include "xio-progcall.h"
+#include "xio-exec.h"
+#include "xio-system.h"
+#include "xio-termios.h"
+#include "xio-readline.h"
+#include "xio-pty.h"
+#include "xio-openssl.h"
+#include "xio-tcpwrap.h"
+#include "xio-ext2.h"
+#include "xio-tun.h"
+
+#endif /* !defined(__xiomodes_h_included) */
diff --git a/xioopen.c b/xioopen.c
new file mode 100644
index 0000000..59d8e7f
--- /dev/null
+++ b/xioopen.c
@@ -0,0 +1,533 @@
+/* $Id: xioopen.c,v 1.119 2007/03/06 21:20:28 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this is the source file of the extended open function */
+
+#include "xiosysincludes.h"
+
+#include "xioopen.h"
+#include "xiomodes.h"
+#include "nestlex.h"
+
+static xiofile_t *xioallocfd(void);
+
+xiosingle_t hugo;
+static xiosingle_t *xioparse_single(const char **addr);
+static xiofile_t *xioparse_dual(const char **addr);
+static int xioopen_dual(xiofile_t *xfd, int xioflags);
+
+const struct addrname addressnames[] = {
+#if 1
+#if WITH_STDIO
+ { "-", &addr_stdio },
+#endif
+#if defined(WITH_UNIX) && defined(WITH_ABSTRACT_UNIXSOCKET)
+ { "abstract", &xioaddr_abstract_client },
+ { "abstract-client", &xioaddr_abstract_client },
+ { "abstract-connect", &xioaddr_abstract_connect },
+#if WITH_LISTEN
+ { "abstract-listen", &xioaddr_abstract_listen },
+#endif
+ { "abstract-recv", &xioaddr_abstract_recv },
+ { "abstract-recvfrom", &xioaddr_abstract_recvfrom },
+ { "abstract-sendto", &xioaddr_abstract_sendto },
+#endif /* defined(WITH_UNIX) && defined(WITH_ABSTRACT_UNIXSOCKET) */
+#if WITH_CREAT
+ { "creat", &addr_creat },
+ { "create", &addr_creat },
+#endif
+#if WITH_PIPE
+ { "echo", &addr_pipe },
+#endif
+#if WITH_EXEC
+ { "exec", &addr_exec },
+#endif
+#if WITH_FDNUM
+ { "fd", &addr_fd },
+#endif
+#if WITH_PIPE
+ { "fifo", &addr_pipe },
+#endif
+#if WITH_FILE
+ { "file", &addr_open },
+#endif
+#if WITH_GOPEN
+ { "gopen", &addr_gopen },
+#endif
+#if (WITH_IP4 || WITH_IP6) && WITH_TCP
+ { "inet", &addr_tcp_connect },
+#endif
+#if (WITH_IP4 || WITH_IP6) && WITH_TCP && WITH_LISTEN
+ { "inet-l", &addr_tcp_listen },
+ { "inet-listen", &addr_tcp_listen },
+#endif
+#if WITH_IP4 && WITH_TCP
+ { "inet4", &addr_tcp4_connect },
+#endif
+#if WITH_IP4 && WITH_TCP && WITH_LISTEN
+ { "inet4-l", &addr_tcp4_listen },
+ { "inet4-listen", &addr_tcp4_listen },
+#endif
+#if WITH_IP6 && WITH_TCP
+ { "inet6", &addr_tcp6_connect },
+#endif
+#if WITH_IP6 && WITH_TCP && WITH_LISTEN
+ { "inet6-l", &addr_tcp6_listen },
+ { "inet6-listen", &addr_tcp6_listen },
+#endif
+#if WITH_RAWIP
+#if (WITH_IP4 || WITH_IP6)
+ { "ip", &addr_rawip_sendto },
+ { "ip-datagram", &addr_rawip_datagram },
+ { "ip-dgram", &addr_rawip_datagram },
+ { "ip-recv", &addr_rawip_recv },
+ { "ip-recvfrom", &addr_rawip_recvfrom },
+ { "ip-send", &addr_rawip_sendto },
+ { "ip-sendto", &addr_rawip_sendto },
+#endif
+#if WITH_IP4
+ { "ip4", &addr_rawip4_sendto },
+ { "ip4-datagram", &addr_rawip4_datagram },
+ { "ip4-dgram", &addr_rawip4_datagram },
+ { "ip4-recv", &addr_rawip4_recv },
+ { "ip4-recvfrom", &addr_rawip4_recvfrom },
+ { "ip4-send", &addr_rawip4_sendto },
+ { "ip4-sendto", &addr_rawip4_sendto },
+#endif
+#if WITH_IP6
+ { "ip6", &addr_rawip6_sendto },
+ { "ip6-datagram", &addr_rawip6_datagram },
+ { "ip6-dgram", &addr_rawip6_datagram },
+ { "ip6-recv", &addr_rawip6_recv },
+ { "ip6-recvfrom", &addr_rawip6_recvfrom },
+ { "ip6-send", &addr_rawip6_sendto },
+ { "ip6-sendto", &addr_rawip6_sendto },
+#endif
+#endif /* WITH_RAWIP */
+#if WITH_UNIX
+ { "local", &addr_unix_connect },
+#endif
+#if WITH_FILE
+ { "open", &addr_open },
+#endif
+#if WITH_OPENSSL
+ { "openssl", &addr_openssl },
+ { "openssl-connect", &addr_openssl },
+#if WITH_LISTEN
+ { "openssl-listen", &addr_openssl_listen },
+#endif
+#endif
+#if WITH_PIPE
+ { "pipe", &addr_pipe },
+#endif
+#if WITH_PROXY
+ { "proxy", &addr_proxy_connect },
+ { "proxy-connect", &addr_proxy_connect },
+#endif
+#if WITH_PTY
+ { "pty", &addr_pty },
+#endif
+#if WITH_READLINE
+ { "readline", &addr_readline },
+#endif
+#if WITH_SOCKS4
+ { "socks", &addr_socks4_connect },
+ { "socks4", &addr_socks4_connect },
+#endif
+#if WITH_SOCKS4A
+ { "socks4a", &addr_socks4a_connect },
+#endif
+#if WITH_OPENSSL
+ { "ssl", &addr_openssl },
+#if WITH_LISTEN
+ { "ssl-l", &addr_openssl_listen },
+#endif
+#endif
+#if WITH_STDIO
+ { "stderr", &addr_stderr },
+ { "stdin", &addr_stdin },
+ { "stdio", &addr_stdio },
+ { "stdout", &addr_stdout },
+#endif
+#if WITH_SYSTEM
+ { "system", &addr_system },
+#endif
+#if (WITH_IP4 || WITH_IP6) && WITH_TCP
+ { "tcp", &addr_tcp_connect },
+ { "tcp-connect", &addr_tcp_connect },
+#endif
+#if (WITH_IP4 || WITH_IP6) && WITH_TCP && WITH_LISTEN
+ { "tcp-l", &addr_tcp_listen },
+ { "tcp-listen", &addr_tcp_listen },
+#endif
+#if WITH_IP4 && WITH_TCP
+ { "tcp4", &addr_tcp4_connect },
+ { "tcp4-connect", &addr_tcp4_connect },
+#endif
+#if WITH_IP4 && WITH_TCP && WITH_LISTEN
+ { "tcp4-l", &addr_tcp4_listen },
+ { "tcp4-listen", &addr_tcp4_listen },
+#endif
+#if WITH_IP6 && WITH_TCP
+ { "tcp6", &addr_tcp6_connect },
+ { "tcp6-connect", &addr_tcp6_connect },
+#endif
+#if WITH_IP6 && WITH_TCP && WITH_LISTEN
+ { "tcp6-l", &addr_tcp6_listen },
+ { "tcp6-listen", &addr_tcp6_listen },
+#endif
+#if WITH_TUN
+ { "tun", &xioaddr_tun },
+#endif
+#if (WITH_IP4 || WITH_IP6) && WITH_UDP
+ { "udp", &addr_udp_connect },
+#endif
+#if (WITH_IP4 || WITH_IP6) && WITH_UDP
+ { "udp-connect", &addr_udp_connect },
+ { "udp-datagram", &addr_udp_datagram },
+ { "udp-dgram", &addr_udp_datagram },
+#endif
+#if (WITH_IP4 || WITH_IP6) && WITH_UDP && WITH_LISTEN
+ { "udp-l", &addr_udp_listen },
+ { "udp-listen", &addr_udp_listen },
+#endif
+#if (WITH_IP4 || WITH_IP6) && WITH_UDP
+ { "udp-recv", &addr_udp_recv },
+ { "udp-recvfrom", &addr_udp_recvfrom },
+ { "udp-send", &addr_udp_sendto },
+ { "udp-sendto", &addr_udp_sendto },
+#endif
+#if WITH_IP4 && WITH_UDP
+ { "udp4", &addr_udp4_connect },
+ { "udp4-connect", &addr_udp4_connect },
+ { "udp4-datagram", &addr_udp4_datagram },
+ { "udp4-dgram", &addr_udp4_datagram },
+#endif
+#if WITH_IP4 && WITH_UDP && WITH_LISTEN
+ { "udp4-l", &addr_udp4_listen },
+ { "udp4-listen", &addr_udp4_listen },
+#endif
+#if WITH_IP4 && WITH_UDP
+ { "udp4-recv", &addr_udp4_recv },
+ { "udp4-recvfrom", &addr_udp4_recvfrom },
+ { "udp4-send", &addr_udp4_sendto },
+ { "udp4-sendto", &addr_udp4_sendto },
+#endif
+#if WITH_IP6 && WITH_UDP
+ { "udp6", &addr_udp6_connect },
+ { "udp6-connect", &addr_udp6_connect },
+ { "udp6-datagram", &addr_udp6_datagram },
+ { "udp6-dgram", &addr_udp6_datagram },
+#endif
+#if WITH_IP6 && WITH_UDP && WITH_LISTEN
+ { "udp6-l", &addr_udp6_listen },
+ { "udp6-listen", &addr_udp6_listen },
+#endif
+#if WITH_IP6 && WITH_UDP
+ { "udp6-recv", &addr_udp6_recv },
+ { "udp6-recvfrom", &addr_udp6_recvfrom },
+ { "udp6-send", &addr_udp6_sendto },
+ { "udp6-sendto", &addr_udp6_sendto },
+#endif
+#if WITH_UNIX
+ { "unix", &addr_unix_client },
+ { "unix-client", &addr_unix_client },
+ { "unix-connect", &addr_unix_connect },
+#endif
+#if WITH_UNIX && WITH_LISTEN
+ { "unix-l", &addr_unix_listen },
+ { "unix-listen", &addr_unix_listen },
+#endif
+#if WITH_UNIX
+ { "unix-recv", &addr_unix_recv },
+ { "unix-recvfrom", &addr_unix_recvfrom },
+ { "unix-send", &addr_unix_sendto },
+ { "unix-sendto", &addr_unix_sendto },
+#endif
+#else /* !0 */
+# if WITH_INTEGRATE
+# include "xiointegrate.c"
+# else
+# include "xioaddrtab.c"
+# endif
+#endif /* !0 */
+ { NULL } /* end marker */
+} ;
+
+int xioopen_single(xiofile_t *xfd, int xioflags);
+
+
+/* prepares a xiofile_t record for dual address type:
+ sets the tag and allocates memory for the substreams.
+ returns 0 on success, or <0 if an error occurred.
+*/
+int xioopen_makedual(xiofile_t *file) {
+ file->tag = XIO_TAG_DUAL;
+ file->common.flags = XIO_RDWR;
+ if ((file->dual.stream[0] = (xiosingle_t *)xioallocfd()) == NULL)
+ return -1;
+ file->dual.stream[0]->flags = XIO_RDONLY;
+ if ((file->dual.stream[1] = (xiosingle_t *)xioallocfd()) == NULL)
+ return -1;
+ file->dual.stream[1]->flags = XIO_WRONLY;
+ return 0;
+}
+
+static xiofile_t *xioallocfd(void) {
+ xiofile_t *fd;
+
+ if ((fd = Calloc(1, sizeof(xiofile_t))) == NULL) {
+ return NULL;
+ }
+ /* some default values; 0's and NULL's need not be applied (calloc'ed) */
+ fd->common.tag = XIO_TAG_INVALID;
+/* fd->common.addr = NULL; */
+ fd->common.flags = XIO_RDWR;
+
+#if WITH_RETRY
+/* fd->stream.retry = 0; */
+/* fd->stream.forever = false; */
+ fd->stream.intervall.tv_sec = 1;
+/* fd->stream.intervall.tv_nsec = 0; */
+#endif /* WITH_RETRY */
+/* fd->common.ignoreeof = false; */
+/* fd->common.eof = 0; */
+
+ fd->stream.fd = -1;
+ fd->stream.dtype = XIODATA_STREAM;
+#if WITH_SOCKET
+/* fd->stream.salen = 0; */
+#endif /* WITH_SOCKET */
+ fd->stream.howtoend = END_UNSPEC;
+/* fd->stream.name = NULL; */
+/* fd->stream.para.exec.pid = 0; */
+ fd->stream.lineterm = LINETERM_RAW;
+
+ /*!! support n socks */
+ if (!sock[0]) {
+ sock[0] = fd;
+ } else {
+ sock[1] = fd;
+ }
+ return fd;
+}
+
+
+/* parse the argument that specifies a two-directional data stream
+ and open the resulting address
+ */
+xiofile_t *xioopen(const char *addr, /* address specification */
+ int xioflags) {
+ xiofile_t *xfd;
+
+ if (xioinitialize() < 0) {
+ return NULL;
+ }
+
+ if ((xfd = xioparse_dual(&addr)) == NULL) {
+ return NULL;
+ }
+ if (xioopen_dual(xfd, xioflags) < 0) {
+ /*!!! free something? */
+ return NULL;
+ }
+
+ return xfd;
+}
+
+static xiofile_t *xioparse_dual(const char **addr) {
+ xiofile_t *xfd;
+ xiosingle_t *sfd1;
+
+ /* we parse a single address */
+ if ((sfd1 = xioparse_single(addr)) == NULL) {
+ return NULL;
+ }
+
+ /* and now we see if we reached a dual-address separator */
+ if (!strncmp(*addr, xioopts.pipesep, strlen(xioopts.pipesep))) {
+ /* yes we reached it, so we parse the second single address */
+ *addr += strlen(xioopts.pipesep);
+
+ if ((xfd = xioallocfd()) == NULL) {
+ free(sfd1); /*! and maybe have free some if its contents */
+ return NULL;
+ }
+ xfd->tag = XIO_TAG_DUAL;
+ xfd->dual.stream[0] = sfd1;
+ if ((xfd->dual.stream[1] = xioparse_single(addr)) == NULL) {
+ return NULL;
+ }
+
+ return xfd;
+ }
+
+ /* a truly single address */
+ xfd = (xiofile_t *)sfd1; sfd1 = NULL;
+
+ return xfd;
+}
+
+static int xioopen_dual(xiofile_t *xfd, int xioflags) {
+
+ if (xfd->tag == XIO_TAG_DUAL) {
+ /* a really dual address */
+ if ((xioflags&XIO_ACCMODE) != XIO_RDWR) {
+ Warn("unidirectional open of dual address");
+ }
+ if (((xioflags&XIO_ACCMODE)+1) & (XIO_RDONLY+1)) {
+ if (xioopen_single((xiofile_t *)xfd->dual.stream[0], XIO_RDONLY|(xioflags&~XIO_ACCMODE&~XIO_MAYEXEC))
+ < 0) {
+ return -1;
+ }
+ }
+ if (((xioflags&XIO_ACCMODE)+1) & (XIO_WRONLY+1)) {
+ if (xioopen_single((xiofile_t *)xfd->dual.stream[1], XIO_WRONLY|(xioflags&~XIO_ACCMODE&~XIO_MAYEXEC))
+ < 0) {
+ xioclose((xiofile_t *)xfd->dual.stream[0]);
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ return xioopen_single(xfd, xioflags);
+}
+
+
+static xiosingle_t *xioparse_single(const char **addr) {
+ xiofile_t *xfd;
+ xiosingle_t *sfd;
+ struct addrname *ae;
+ const struct addrdesc *addrdesc = NULL;
+ const char *ends[4+1];
+ const char *hquotes[] = {
+ "'",
+ NULL
+ } ;
+ const char *squotes[] = {
+ "\"",
+ NULL
+ } ;
+ const char *nests[] = {
+ "'", "'",
+ "(", ")",
+ "[", "]",
+ "{", "}",
+ NULL
+ } ;
+ char token[512], *tokp;
+ size_t len;
+ int i;
+
+ /* init */
+ i = 0;
+ /*ends[i++] = xioopts.chainsep;*/ /* default: "|" */
+ ends[i++] = xioopts.pipesep; /* default: "!!" */
+ ends[i++] = ","/*xioopts.comma*/; /* default: "," */
+ ends[i++] = ":"/*xioopts.colon*/; /* default: ":" */
+ ends[i++] = NULL;
+
+ if ((xfd = xioallocfd()) == NULL) {
+ return NULL;
+ }
+ sfd = &xfd->stream;
+ sfd->argc = 0;
+
+ len = sizeof(token); tokp = token;
+ if (nestlex(addr, &tokp, &len, ends, hquotes, squotes, nests,
+ true, true, false) < 0) {
+ Error2("keyword too long, in address \"%s%s\"", token, *addr);
+ }
+ *tokp = '\0'; /*! len? */
+ ae = (struct addrname *)
+ keyw((struct wordent *)&addressnames, token,
+ sizeof(addressnames)/sizeof(struct addrname)-1);
+
+ if (ae) {
+ addrdesc = ae->desc;
+ /* keyword */
+ if ((sfd->argv[sfd->argc++] = strdup(token)) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", token);
+ }
+ } else {
+ if (false) {
+ ;
+#if WITH_FDNUM
+ } else if (isdigit(token[0]&0xff) && token[1] == '\0') {
+ Info1("interpreting address \"%s\" as file descriptor", token);
+ addrdesc = &addr_fd;
+ if ((sfd->argv[sfd->argc++] = strdup("FD")) == NULL) {
+ Error("strdup(\"FD\"): out of memory");
+ }
+ if ((sfd->argv[sfd->argc++] = strdup(token)) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", token);
+ }
+ /*! check argc overflow */
+#endif /* WITH_FDNUM */
+#if WITH_GOPEN
+ } else if (strchr(token, '/')) {
+ Info1("interpreting address \"%s\" as file name", token);
+ addrdesc = &addr_gopen;
+ if ((sfd->argv[sfd->argc++] = strdup("GOPEN")) == NULL) {
+ Error("strdup(\"GOPEN\"): out of memory");
+ }
+ if ((sfd->argv[sfd->argc++] = strdup(token)) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", token);
+ }
+ /*! check argc overflow */
+#endif /* WITH_GOPEN */
+ } else {
+ Error1("unknown device/address \"%s\"", token);
+ /*!!! free something*/ return NULL;
+ }
+ }
+
+ sfd->tag = XIO_TAG_RDWR;
+ sfd->addr = addrdesc;
+
+ while (!strncmp(*addr, xioopts.paramsep, strlen(xioopts.paramsep))) {
+ *addr += strlen(xioopts.paramsep);
+ len = sizeof(token); tokp = token;
+ if (nestlex(addr, &tokp, &len, ends, hquotes, squotes, nests,
+ true, true, false) != 0) {
+ Error2("syntax error in address \"%s%s\"", token, *addr);
+ }
+ *tokp = '\0';
+ if ((sfd->argv[sfd->argc++] = strdup(token)) == NULL) {
+ Error1("strdup(\"%s\"): out of memory", token);
+ }
+ }
+
+ if (parseopts(addr, addrdesc->groups, &sfd->opts) < 0) {
+ free(xfd);
+ return NULL;
+ }
+
+ return sfd;
+}
+
+int xioopen_single(xiofile_t *xfd, int xioflags) {
+ const struct addrdesc *addrdesc;
+ int result;
+
+ if ((xioflags&XIO_ACCMODE) == XIO_RDONLY) {
+ xfd->tag = XIO_TAG_RDONLY;
+ } else if ((xioflags&XIO_ACCMODE) == XIO_WRONLY) {
+ xfd->tag = XIO_TAG_WRONLY;
+ } else if ((xioflags&XIO_ACCMODE) == XIO_RDWR) {
+ xfd->tag = XIO_TAG_RDWR;
+ } else {
+ Error1("invalid mode for address \"%s\"", xfd->stream.argv[0]);
+ }
+ xfd->stream.flags &= (~XIO_ACCMODE);
+ xfd->stream.flags |= (xioflags & XIO_ACCMODE);
+ addrdesc = xfd->stream.addr;
+ result = (*addrdesc->func)(xfd->stream.argc, xfd->stream.argv,
+ xfd->stream.opts, xioflags, xfd,
+ addrdesc->groups, addrdesc->arg1,
+ addrdesc->arg2, addrdesc->arg3);
+ return result;
+}
+
diff --git a/xioopen.h b/xioopen.h
new file mode 100644
index 0000000..7578b64
--- /dev/null
+++ b/xioopen.h
@@ -0,0 +1,94 @@
+/* $Id: xioopen.h,v 1.22 2006/05/12 20:14:05 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xioopen_h_included
+#define __xioopen_h_included 1
+
+#include "compat.h" /* F_pid */
+#include "mytypes.h"
+#include "error.h"
+#include "utils.h"
+#include "sysutils.h"
+
+#include "sycls.h"
+#include "sslcls.h"
+#include "dalan.h"
+#include "filan.h"
+#include "xio.h"
+#include "xioopts.h"
+
+
+#if WITH_HELP
+#define HELP(x) , x
+#else
+#define HELP(x)
+#endif
+
+
+
+/* xioinitialize performs asserts on these records */
+extern const struct optdesc opt_crdly;
+extern const struct optdesc opt_tabdly;
+extern const struct optdesc opt_csize;
+
+
+struct addrname {
+ const char *name;
+ const struct addrdesc *desc;
+} ;
+
+extern const char *ddirection[];
+extern const char *filetypenames[];
+extern const struct addrname addressnames[];
+extern const struct optname optionnames[];
+
+extern int xioopen_makedual(xiofile_t *file);
+
+#define retropt_2bytes(o,c,r) retropt_ushort(o,c,r)
+
+/* mode_t might be unsigned short or unsigned int or what else? */
+#if HAVE_BASIC_MODE_T==1
+# define retropt_modet(x,y,z) retropt_short(x,y,z)
+#elif HAVE_BASIC_MODE_T==2
+# define retropt_modet(x,y,z) retropt_ushort(x,y,z)
+#elif HAVE_BASIC_MODE_T==3
+# define retropt_modet(x,y,z) retropt_int(x,y,z)
+#elif HAVE_BASIC_MODE_T==4
+# define retropt_modet(x,y,z) retropt_uint(x,y,z)
+#elif HAVE_BASIC_MODE_T==5
+# define retropt_modet(x,y,z) retropt_long(x,y,z)
+#elif HAVE_BASIC_MODE_T==6
+# define retropt_modet(x,y,z) retropt_ulong(x,y,z)
+#endif
+
+#if HAVE_BASIC_UID_T==1
+# define retropt_uidt(x,y,z) retropt_short(x,y,z)
+#elif HAVE_BASIC_UID_T==2
+# define retropt_uidt(x,y,z) retropt_ushort(x,y,z)
+#elif HAVE_BASIC_UID_T==3
+# define retropt_uidt(x,y,z) retropt_int(x,y,z)
+#elif HAVE_BASIC_UID_T==4
+# define retropt_uidt(x,y,z) retropt_uint(x,y,z)
+#elif HAVE_BASIC_UID_T==5
+# define retropt_uidt(x,y,z) retropt_long(x,y,z)
+#elif HAVE_BASIC_UID_T==6
+# define retropt_uidt(x,y,z) retropt_ulong(x,y,z)
+#endif
+
+#if HAVE_BASIC_GID_T==1
+# define retropt_gidt(x,y,z) retropt_short(x,y,z)
+#elif HAVE_BASIC_GID_T==2
+# define retropt_gidt(x,y,z) retropt_ushort(x,y,z)
+#elif HAVE_BASIC_GID_T==3
+# define retropt_gidt(x,y,z) retropt_int(x,y,z)
+#elif HAVE_BASIC_GID_T==4
+# define retropt_gidt(x,y,z) retropt_uint(x,y,z)
+#elif HAVE_BASIC_GID_T==5
+# define retropt_gidt(x,y,z) retropt_long(x,y,z)
+#elif HAVE_BASIC_GID_T==6
+# define retropt_gidt(x,y,z) retropt_ulong(x,y,z)
+#endif
+
+
+#endif /* !defined(__xioopen_h_included) */
diff --git a/xioopts.c b/xioopts.c
new file mode 100644
index 0000000..d84b138
--- /dev/null
+++ b/xioopts.c
@@ -0,0 +1,3732 @@
+/* $Id: xioopts.c,v 1.99 2007/03/06 21:22:04 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for address options handling */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+#include "xio-unix.h"
+
+#include "xiomodes.h"
+#include "xiolockfile.h"
+#include "nestlex.h"
+
+bool xioopts_ignoregroups;
+
+#define IF_ANY(a,b) {a,b},
+
+#if WITH_NAMED
+# define IF_NAMED(a,b) {a,b},
+#else
+# define IF_NAMED(a,b)
+#endif
+
+#if WITH_PIPE || WITH_GOPEN
+# define IF_OPEN(a,b) {a,b},
+#else
+# define IF_OPEN(a,b)
+#endif
+
+#if WITH_TERMIOS
+# define IF_TERMIOS(a,b) {a,b},
+#else
+# define IF_TERMIOS(a,b)
+#endif
+
+#if WITH_EXEC
+# define IF_EXEC(a,b) {a,b},
+#else
+# define IF_EXEC(a,b)
+#endif
+
+#if WITH_SOCKET
+# define IF_SOCKET(a,b) {a,b},
+#else
+# define IF_SOCKET(a,b)
+#endif
+
+#if WITH_LISTEN
+# define IF_LISTEN(a,b) {a,b},
+#else
+# define IF_LISTEN(a,b)
+#endif
+
+#if (WITH_UDP || WITH_TCP) && WITH_LISTEN
+# define IF_RANGE(a,b) {a,b},
+#else
+# define IF_RANGE(a,b)
+#endif
+
+#if WITH_IP4 || WITH_IP6
+# define IF_IP(a,b) {a,b},
+#else
+# define IF_IP(a,b)
+#endif
+
+#if WITH_IP6
+# define IF_IP6(a,b) {a,b},
+#else
+# define IF_IP6(a,b)
+#endif
+
+#if WITH_TCP|WITH_UDP
+# define IF_IPAPP(a,b) {a,b},
+#else
+# define IF_IPAPP(a,b)
+#endif
+
+#if WITH_TCP
+# define IF_TCP(a,b) {a,b},
+#else
+# define IF_TCP(a,b)
+#endif
+
+#if WITH_SOCKS4
+# define IF_SOCKS4(a,b) {a,b},
+#else
+# define IF_SOCKS4(a,b)
+#endif
+
+#if WITH_PROXY
+# define IF_PROXY(a,b) {a,b},
+#else
+# define IF_PROXY(a,b)
+#endif
+
+#if WITH_READLINE
+# define IF_READLINE(a,b) {a,b},
+#else
+# define IF_READLINE(a,b)
+#endif
+
+#if WITH_PTY
+# define IF_PTY(a,b) {a,b},
+#else
+# define IF_PTY(a,b)
+#endif
+
+#if WITH_OPENSSL
+# define IF_OPENSSL(a,b) {a,b},
+#else
+# define IF_OPENSSL(a,b)
+#endif
+
+#if WITH_TUN
+# define IF_TUN(a,b) {a,b},
+#else
+# define IF_TUN(a,b)
+#endif
+
+#if WITH_UNIX
+# define IF_UNIX(a,b) {a,b},
+#else
+# define IF_UNIX(a,b)
+#endif
+
+#if WITH_RETRY
+# define IF_RETRY(a,b) {a,b},
+#else
+# define IF_RETRY(a,b)
+#endif
+
+
+static int applyopt_offset(struct single *xfd, struct opt *opt);
+
+
+/* address options - keep this array strictly alphabetically sorted for
+ binary search! */
+/* NULL terminated */
+const struct optname optionnames[] = {
+#if HAVE_RESOLV_H
+ IF_IP ("aaonly", &opt_res_aaonly)
+#endif /* HAVE_RESOLV_H */
+#ifdef TCP_ABORT_THRESHOLD /* HP_UX */
+ IF_TCP ("abort-threshold", &opt_tcp_abort_threshold)
+#endif
+#ifdef SO_ACCEPTCONN /* AIX433 */
+ IF_SOCKET ("acceptconn", &opt_so_acceptconn)
+#endif /* SO_ACCEPTCONN */
+#ifdef IP_ADD_MEMBERSHIP
+ IF_IP ("add-membership", &opt_ip_add_membership)
+#endif
+ IF_TUN ("allmulti", &opt_iff_allmulti)
+#if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
+ IF_IPAPP ("allow-table", &opt_tcpwrap_hosts_allow_table)
+#endif
+ IF_ANY ("append", &opt_append)
+#ifdef O_ASYNC
+ IF_ANY ("async", &opt_async)
+#endif
+#ifdef SO_ATTACH_FILTER
+ IF_SOCKET ("attach-filter", &opt_so_attach_filter)
+ IF_SOCKET ("attachfilter", &opt_so_attach_filter)
+#endif
+#ifdef SO_AUDIT /* AIX 4.3.3 */
+ IF_SOCKET ("audit", &opt_so_audit)
+#endif /* SO_AUDIT */
+ IF_TUN ("automedia", &opt_iff_automedia)
+#ifdef CBAUD
+ IF_TERMIOS("b0", &opt_b0)
+#ifdef B1000000
+ IF_TERMIOS("b1000000", &opt_b1000000)
+#endif
+ IF_TERMIOS("b110", &opt_b110)
+#ifdef B115200
+ IF_TERMIOS("b115200", &opt_b115200)
+#endif
+#ifdef B1152000
+ IF_TERMIOS("b1152000", &opt_b1152000)
+#endif
+ IF_TERMIOS("b1200", &opt_b1200)
+ IF_TERMIOS("b134", &opt_b134)
+ IF_TERMIOS("b150", &opt_b150)
+#ifdef B1500000
+ IF_TERMIOS("b1500000", &opt_b1500000)
+#endif
+ IF_TERMIOS("b1800", &opt_b1800)
+ IF_TERMIOS("b19200", &opt_b19200)
+ IF_TERMIOS("b200", &opt_b200)
+#ifdef B2000000
+ IF_TERMIOS("b2000000", &opt_b2000000)
+#endif
+#ifdef B230400
+ IF_TERMIOS("b230400", &opt_b230400)
+#endif
+ IF_TERMIOS("b2400", &opt_b2400)
+#ifdef B2500000
+ IF_TERMIOS("b2500000", &opt_b2500000)
+#endif
+ IF_TERMIOS("b300", &opt_b300)
+#ifdef B3000000
+ IF_TERMIOS("b3000000", &opt_b3000000)
+#endif
+#ifdef B3500000
+ IF_TERMIOS("b3500000", &opt_b3500000)
+#endif
+#ifdef B3600 /* HP-UX */
+ IF_TERMIOS("b3600", &opt_b3600)
+#endif
+ IF_TERMIOS("b38400", &opt_b38400)
+#ifdef B4000000
+ IF_TERMIOS("b4000000", &opt_b4000000)
+#endif
+#ifdef B460800
+ IF_TERMIOS("b460800", &opt_b460800)
+#endif
+ IF_TERMIOS("b4800", &opt_b4800)
+ IF_TERMIOS("b50", &opt_b50)
+#ifdef B500000
+ IF_TERMIOS("b500000", &opt_b500000)
+#endif
+#ifdef B57600
+ IF_TERMIOS("b57600", &opt_b57600)
+#endif
+#ifdef B576000
+ IF_TERMIOS("b576000", &opt_b576000)
+#endif
+ IF_TERMIOS("b600", &opt_b600)
+#ifdef B7200 /* HP-UX */
+ IF_TERMIOS("b7200", &opt_b7200)
+#endif
+ IF_TERMIOS("b75", &opt_b75)
+#ifdef B900 /* HP-UX */
+ IF_TERMIOS("b900", &opt_b900)
+#endif
+#ifdef B921600
+ IF_TERMIOS("b921600", &opt_b921600)
+#endif
+ IF_TERMIOS("b9600", &opt_b9600)
+#endif /* defined(CBAUD) */
+ IF_LISTEN ("backlog", &opt_backlog)
+#ifdef O_BINARY
+ IF_OPEN ("bin", &opt_o_binary)
+ IF_OPEN ("binary", &opt_o_binary)
+#endif
+ IF_SOCKET ("bind", &opt_bind)
+#ifdef SO_BINDTODEVICE
+ IF_SOCKET ("bindtodevice", &opt_so_bindtodevice)
+#endif
+ IF_TERMIOS("brkint", &opt_brkint)
+ IF_SOCKET ("broadcast", &opt_so_broadcast)
+#ifdef BSDLY
+# ifdef BS0
+ IF_TERMIOS("bs0", &opt_bs0)
+# endif
+# ifdef BS1
+ IF_TERMIOS("bs1", &opt_bs1)
+# endif
+#endif
+#ifdef SO_BSDCOMPAT
+ IF_SOCKET ("bsdcompat", &opt_so_bsdcompat)
+#endif
+#ifdef BSDLY
+ IF_TERMIOS("bsdly", &opt_bsdly)
+#endif
+ IF_ANY ("bytes", &opt_readbytes)
+ IF_OPENSSL("cafile", &opt_openssl_cafile)
+ IF_OPENSSL("capath", &opt_openssl_capath)
+ IF_OPENSSL("cert", &opt_openssl_certificate)
+ IF_OPENSSL("certificate", &opt_openssl_certificate)
+ IF_ANY ("chroot", &opt_chroot)
+ IF_ANY ("chroot-early", &opt_chroot_early)
+ /*IF_TERMIOS("cibaud", &opt_cibaud)*/
+ IF_OPENSSL("cipher", &opt_openssl_cipherlist)
+ IF_OPENSSL("cipherlist", &opt_openssl_cipherlist)
+ IF_OPENSSL("ciphers", &opt_openssl_cipherlist)
+#ifdef SO_CKSUMRECV
+ IF_SOCKET ("cksumrecv", &opt_so_cksumrecv)
+#endif /* SO_CKSUMRECV */
+ /*IF_NAMED ("cleanup", &opt_cleanup)*/
+ IF_TERMIOS("clocal", &opt_clocal)
+ IF_ANY ("cloexec", &opt_cloexec)
+ IF_ANY ("close", &opt_end_close)
+#if WITH_EXT2 && defined(EXT2_COMPR_FL)
+ IF_ANY ("compr", &opt_ext2_compr)
+#endif
+#ifdef TCP_CONN_ABORT_THRESHOLD /* HP_UX */
+ IF_TCP ("conn-abort-threshold", &opt_tcp_conn_abort_threshold)
+#endif
+ IF_SOCKET ("connect-timeout", &opt_connect_timeout)
+ IF_LISTEN ("cool-write", &opt_cool_write)
+ IF_LISTEN ("coolwrite", &opt_cool_write)
+#ifdef TCP_CORK
+ IF_TCP ("cork", &opt_tcp_cork)
+#endif
+ IF_ANY ("cr", &opt_cr)
+#ifdef CRDLY
+# ifdef CR0
+ IF_TERMIOS("cr0", &opt_cr0)
+# endif
+# ifdef CR1
+ IF_TERMIOS("cr1", &opt_cr1)
+# endif
+# ifdef CR2
+ IF_TERMIOS("cr2", &opt_cr2)
+# endif
+# ifdef CR3
+ IF_TERMIOS("cr3", &opt_cr3)
+# endif
+ IF_TERMIOS("crdly", &opt_crdly)
+#endif /* defined(CRDLY) */
+ IF_TERMIOS("cread", &opt_cread)
+ IF_OPEN ("creat", &opt_o_create)
+ IF_OPEN ("create", &opt_o_create)
+ IF_ANY ("crlf", &opt_crnl)
+ IF_ANY ("crnl", &opt_crnl)
+ IF_TERMIOS("crterase", &opt_echoe)
+ IF_TERMIOS("crtkill", &opt_echoke)
+#ifdef CRTSCTS
+ IF_TERMIOS("crtscts", &opt_crtscts)
+#endif
+ IF_TERMIOS("cs5", &opt_cs5)
+ IF_TERMIOS("cs6", &opt_cs6)
+ IF_TERMIOS("cs7", &opt_cs7)
+ IF_TERMIOS("cs8", &opt_cs8)
+ IF_TERMIOS("csize", &opt_csize)
+ IF_TERMIOS("cstopb", &opt_cstopb)
+ IF_TERMIOS("ctlecho", &opt_echoctl)
+ IF_TERMIOS("ctty", &opt_tiocsctty)
+ IF_EXEC ("dash", &opt_dash)
+ IF_SOCKET ("debug", &opt_so_debug)
+ /*IF_IP ("debug", &opt_res_debug)*/
+#ifdef O_DEFER
+ IF_OPEN ("defer", &opt_o_defer)
+#endif
+#ifdef TCP_DEFER_ACCEPT /* Linux 2.4.0 */
+ IF_TCP ("defer-accept", &opt_tcp_defer_accept)
+#endif
+#if HAVE_RESOLV_H
+ IF_IP ("defnames", &opt_res_defnames)
+#endif /* HAVE_RESOLV_H */
+#ifdef O_DELAY
+ IF_OPEN ("delay", &opt_o_delay)
+#endif
+ IF_NAMED ("delete", &opt_unlink)
+#if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
+ IF_IPAPP ("deny-table", &opt_tcpwrap_hosts_deny_table)
+#endif
+#ifdef SO_DETACH_FILTER
+ IF_SOCKET ("detach-filter", &opt_so_detach_filter)
+ IF_SOCKET ("detachfilter", &opt_so_detach_filter)
+#endif
+#ifdef SO_DGRAM_ERRIND
+ IF_SOCKET ("dgram-errind", &opt_so_dgram_errind)
+ IF_SOCKET ("dgramerrind", &opt_so_dgram_errind)
+#endif
+ IF_OPENSSL("dh", &opt_openssl_dhparam)
+ IF_OPENSSL("dhparam", &opt_openssl_dhparam)
+#ifdef O_DIRECT
+ IF_OPEN ("direct", &opt_o_direct)
+#endif
+#ifdef O_DIRECTORY
+ IF_OPEN ("directory", &opt_o_directory)
+#endif
+#if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
+ IF_ANY ("dirsync", &opt_ext2_dirsync)
+#endif
+#ifdef VDISCARD
+ IF_TERMIOS("discard", &opt_vdiscard)
+#endif
+#if HAVE_RESOLV_H
+ IF_IP ("dnsrch", &opt_res_dnsrch)
+#endif /* HAVE_RESOLV_H */
+#ifdef SO_DONTLINGER
+ IF_SOCKET ("dontlinger", &opt_so_dontlinger)
+#endif
+ IF_SOCKET ("dontroute", &opt_so_dontroute)
+#ifdef VDSUSP /* HP-UX */
+ IF_TERMIOS("dsusp", &opt_vdsusp)
+#endif
+#ifdef O_DSYNC
+ IF_OPEN ("dsync", &opt_o_dsync)
+#endif
+ IF_TERMIOS("echo", &opt_echo)
+ IF_TERMIOS("echoctl", &opt_echoctl)
+ IF_TERMIOS("echoe", &opt_echoe)
+ IF_TERMIOS("echok", &opt_echok)
+ IF_TERMIOS("echoke", &opt_echoke)
+ IF_TERMIOS("echonl", &opt_echonl)
+#ifdef ECHOPRT
+ IF_TERMIOS("echoprt", &opt_echoprt)
+#endif
+ IF_OPENSSL("egd", &opt_openssl_egd)
+ IF_ANY ("end-close", &opt_end_close)
+ IF_TERMIOS("eof", &opt_veof)
+ IF_TERMIOS("eol", &opt_veol)
+ IF_TERMIOS("eol2", &opt_veol2)
+ IF_TERMIOS("erase", &opt_verase)
+ IF_SOCKET ("error", &opt_so_error)
+ IF_OPEN ("excl", &opt_o_excl)
+#if WITH_EXT2 && defined(EXT2_APPEND_FL)
+ IF_ANY ("ext2-append", &opt_ext2_append)
+#endif
+#if WITH_EXT2 && defined(EXT2_COMPR_FL)
+ IF_ANY ("ext2-compr", &opt_ext2_compr)
+#endif
+#if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
+ IF_ANY ("ext2-dirsync", &opt_ext2_dirsync)
+#endif
+#if WITH_EXT2 && defined(EXT2_IMMUTABLE_FL)
+ IF_ANY ("ext2-immutable", &opt_ext2_immutable)
+#endif
+#if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
+ IF_ANY ("ext2-journal-data", &opt_ext2_journal_data)
+#endif
+#if WITH_EXT2 && defined(EXT2_NOATIME_FL)
+ IF_ANY ("ext2-noatime", &opt_ext2_noatime)
+#endif
+#if WITH_EXT2 && defined(EXT2_NODUMP_FL)
+ IF_ANY ("ext2-nodump", &opt_ext2_nodump)
+#endif
+#if WITH_EXT2 && defined(EXT2_NOTAIL_FL)
+ IF_ANY ("ext2-notail", &opt_ext2_notail)
+#endif
+#if WITH_EXT2 && defined(EXT2_SECRM_FL)
+ IF_ANY ("ext2-secrm", &opt_ext2_secrm)
+#endif
+#if WITH_EXT2 && defined(EXT2_SYNC_FL)
+ IF_ANY ("ext2-sync", &opt_ext2_sync)
+#endif
+#if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
+ IF_ANY ("ext2-topdir", &opt_ext2_topdir)
+#endif
+#if WITH_EXT2 && defined(EXT2_UNRM_FL)
+ IF_ANY ("ext2-unrm", &opt_ext2_unrm)
+#endif
+#if WITH_EXT2 && defined(EXT2_APPEND_FL)
+ IF_ANY ("ext3-append", &opt_ext2_append)
+#endif
+#if WITH_EXT2 && defined(EXT2_COMPR_FL)
+ IF_ANY ("ext3-compr", &opt_ext2_compr)
+#endif
+#if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
+ IF_ANY ("ext3-dirsync", &opt_ext2_dirsync)
+#endif
+#if WITH_EXT2 && defined(EXT2_IMMUTABLE_FL)
+ IF_ANY ("ext3-immutable", &opt_ext2_immutable)
+#endif
+#if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
+ IF_ANY ("ext3-journal-data", &opt_ext2_journal_data)
+#endif
+#if WITH_EXT2 && defined(EXT2_NOATIME_FL)
+ IF_ANY ("ext3-noatime", &opt_ext2_noatime)
+#endif
+#if WITH_EXT2 && defined(EXT2_NODUMP_FL)
+ IF_ANY ("ext3-nodump", &opt_ext2_nodump)
+#endif
+#if WITH_EXT2 && defined(EXT2_NOTAIL_FL)
+ IF_ANY ("ext3-notail", &opt_ext2_notail)
+#endif
+#if WITH_EXT2 && defined(EXT2_SECRM_FL)
+ IF_ANY ("ext3-secrm", &opt_ext2_secrm)
+#endif
+#if WITH_EXT2 && defined(EXT2_SYNC_FL)
+ IF_ANY ("ext3-sync", &opt_ext2_sync)
+#endif
+#if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
+ IF_ANY ("ext3-topdir", &opt_ext2_topdir)
+#endif
+#if WITH_EXT2 && defined(EXT2_UNRM_FL)
+ IF_ANY ("ext3-unrm", &opt_ext2_unrm)
+#endif
+ IF_ANY ("f-setlk", &opt_f_setlk_wr)
+ IF_ANY ("f-setlk-rd", &opt_f_setlk_rd)
+ IF_ANY ("f-setlk-wr", &opt_f_setlk_wr)
+ IF_ANY ("f-setlkw", &opt_f_setlkw_wr)
+ IF_ANY ("f-setlkw-rd", &opt_f_setlkw_rd)
+ IF_ANY ("f-setlkw-wr", &opt_f_setlkw_wr)
+ IF_EXEC ("fdin", &opt_fdin)
+ IF_EXEC ("fdout", &opt_fdout)
+#ifdef FFDLY
+# ifdef FF0
+ IF_TERMIOS("ff0", &opt_ff0)
+# endif
+# ifdef FF1
+ IF_TERMIOS("ff1", &opt_ff1)
+# endif
+ IF_TERMIOS("ffdly", &opt_ffdly)
+#endif
+#ifdef FIOSETOWN
+ IF_SOCKET ("fiosetown", &opt_fiosetown)
+#endif
+#if WITH_FIPS
+ IF_OPENSSL("fips", &opt_openssl_fips)
+#endif
+#if HAVE_FLOCK
+ IF_ANY ("flock", &opt_flock_ex)
+ IF_ANY ("flock-ex", &opt_flock_ex)
+ IF_ANY ("flock-ex-nb", &opt_flock_ex_nb)
+ 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
+ IF_TERMIOS("flusho", &opt_flusho)
+ IF_RETRY ("forever", &opt_forever)
+ IF_LISTEN ("fork", &opt_fork)
+#ifdef IP_FREEBIND
+ IF_IP ("freebind", &opt_ip_freebind)
+#endif
+#if HAVE_FTRUNCATE64
+ IF_ANY ("ftruncate", &opt_ftruncate64)
+#else
+ IF_ANY ("ftruncate", &opt_ftruncate32)
+#endif
+ IF_ANY ("ftruncate32", &opt_ftruncate32)
+#if HAVE_FTRUNCATE64
+ IF_ANY ("ftruncate64", &opt_ftruncate64)
+#endif
+ IF_ANY ("gid", &opt_group)
+ IF_NAMED ("gid-e", &opt_group_early)
+ IF_ANY ("gid-l", &opt_group_late)
+ IF_ANY ("group", &opt_group)
+ IF_NAMED ("group-early", &opt_group_early)
+ IF_ANY ("group-late", &opt_group_late)
+#ifdef IP_HDRINCL
+ IF_IP ("hdrincl", &opt_ip_hdrincl)
+#endif
+ IF_READLINE("history", &opt_history_file)
+ IF_READLINE("history-file", &opt_history_file)
+#if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
+ IF_IPAPP ("hosts-allow", &opt_tcpwrap_hosts_allow_table)
+#endif
+#if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
+ IF_IPAPP ("hosts-deny", &opt_tcpwrap_hosts_deny_table)
+#endif
+ IF_TERMIOS("hup", &opt_hupcl)
+ IF_TERMIOS("hupcl", &opt_hupcl)
+ IF_TERMIOS("icanon", &opt_icanon)
+ IF_TERMIOS("icrnl", &opt_icrnl)
+ IF_TERMIOS("iexten", &opt_iexten)
+#ifdef SO_BINDTODEVICE
+ IF_SOCKET ("if", &opt_so_bindtodevice)
+#endif
+ IF_TUN ("iff-allmulti", &opt_iff_allmulti)
+ IF_TUN ("iff-automedia", &opt_iff_automedia)
+ IF_TUN ("iff-broadcast", &opt_iff_broadcast)
+ IF_TUN ("iff-debug", &opt_iff_debug)
+ /*IF_TUN ("iff-dynamic", &opt_iff_dynamic)*/
+ IF_TUN ("iff-loopback", &opt_iff_loopback)
+ IF_TUN ("iff-master", &opt_iff_master)
+ IF_TUN ("iff-multicast", &opt_iff_multicast)
+ IF_TUN ("iff-no-pi", &opt_iff_no_pi)
+ IF_TUN ("iff-noarp", &opt_iff_noarp)
+ IF_TUN ("iff-notrailers", &opt_iff_notrailers)
+ IF_TUN ("iff-pointopoint", &opt_iff_pointopoint)
+ IF_TUN ("iff-portsel", &opt_iff_portsel)
+ IF_TUN ("iff-promisc", &opt_iff_promisc)
+ IF_TUN ("iff-running", &opt_iff_running)
+ IF_TUN ("iff-slave", &opt_iff_slave)
+ IF_TUN ("iff-up", &opt_iff_up)
+ IF_TERMIOS("ignbrk", &opt_ignbrk)
+ IF_TERMIOS("igncr", &opt_igncr)
+ /* you might need to terminate socat manually if you use this option: */
+ IF_PROXY ("ignorecr", &opt_ignorecr)
+ IF_ANY ("ignoreeof", &opt_ignoreeof)
+ IF_ANY ("ignoreof", &opt_ignoreeof)
+ IF_TERMIOS("ignpar", &opt_ignpar)
+#if HAVE_RESOLV_H
+ IF_IP ("igntc", &opt_res_igntc)
+#endif /* HAVE_RESOLV_H */
+ IF_TERMIOS("imaxbel", &opt_imaxbel)
+#if WITH_EXT2 && defined(EXT2_IMMUTABLE_FL)
+ IF_ANY ("immutable", &opt_ext2_immutable)
+#endif
+#ifdef TCP_INFO /* Linux 2.4.0 */
+ IF_TCP ("info", &opt_tcp_info)
+#endif
+ IF_TERMIOS("inlcr", &opt_inlcr)
+ IF_TERMIOS("inpck", &opt_inpck)
+#ifdef SO_BINDTODEVICE
+ IF_SOCKET ("interface", &opt_so_bindtodevice)
+#endif
+ IF_RETRY ("intervall", &opt_intervall)
+ IF_TERMIOS("intr", &opt_vintr)
+#ifdef IP_ADD_MEMBERSHIP
+ IF_IP ("ip-add-membership", &opt_ip_add_membership)
+#endif
+#ifdef IP_FREEBIND
+ IF_IP ("ip-freebind", &opt_ip_freebind)
+#endif
+#ifdef IP_HDRINCL
+ IF_IP ("ip-hdrincl", &opt_ip_hdrincl)
+#endif
+#ifdef IP_ADD_MEMBERSHIP
+ IF_IP ("ip-membership", &opt_ip_add_membership)
+#endif
+#ifdef IP_MTU
+ IF_IP ("ip-mtu", &opt_ip_mtu)
+#endif
+#ifdef IP_MTU_DISCOVER
+ IF_IP ("ip-mtu-discover", &opt_ip_mtu_discover)
+#endif
+ IF_IP ("ip-multicast-if", &opt_ip_multicast_if)
+ IF_IP ("ip-multicast-loop", &opt_ip_multicast_loop)
+ IF_IP ("ip-multicast-ttl", &opt_ip_multicast_ttl)
+#ifdef IP_OPTIONS
+ IF_IP ("ip-options", &opt_ip_options)
+#endif
+#ifdef IP_PKTINFO
+ IF_IP ("ip-pktinfo", &opt_ip_pktinfo)
+#endif
+#ifdef IP_PKTOPTIONS
+ IF_IP ("ip-pktoptions", &opt_ip_pktoptions)
+#endif
+#ifdef IP_RECVERR
+ IF_IP ("ip-recverr", &opt_ip_recverr)
+#endif
+#ifdef IP_RECVOPTS
+ IF_IP ("ip-recvopts", &opt_ip_recvopts)
+#endif
+#ifdef IP_RECVTOS
+ IF_IP ("ip-recvtos", &opt_ip_recvtos)
+#endif
+#ifdef IP_RECVTTL
+ IF_IP ("ip-recvttl", &opt_ip_recvttl)
+#endif
+#ifdef IP_RETOPTS
+ IF_IP ("ip-retopts", &opt_ip_retopts)
+#endif
+#ifdef IP_ROUTER_ALERT
+ IF_IP ("ip-router-alert", &opt_ip_router_alert)
+#endif
+ IF_IP ("ip-tos", &opt_ip_tos)
+ IF_IP ("ip-ttl", &opt_ip_ttl)
+#ifdef IP_FREEBIND
+ IF_IP ("ipfreebind", &opt_ip_freebind)
+#endif
+#ifdef IP_HDRINCL
+ IF_IP ("iphdrincl", &opt_ip_hdrincl)
+#endif
+#ifdef IP_MTU
+ IF_IP ("ipmtu", &opt_ip_mtu)
+#endif
+#ifdef IP_MTU_DISCOVER
+ IF_IP ("ipmtudiscover", &opt_ip_mtu_discover)
+#endif
+ IF_IP ("ipmulticastloop", &opt_ip_multicast_loop)
+ IF_IP ("ipmulticastttl", &opt_ip_multicast_ttl)
+#ifdef IP_OPTIONS
+ IF_IP ("ipoptions", &opt_ip_options)
+#endif
+#ifdef IP_PKTINFO
+ IF_IP ("ippktinfo", &opt_ip_pktinfo)
+#endif
+#ifdef IP_PKTOPTIONS
+ IF_IP ("ippktoptions", &opt_ip_pktoptions)
+#endif
+#ifdef IP_RECVERR
+ IF_IP ("iprecverr", &opt_ip_recverr)
+#endif
+#ifdef IP_RECVOPTS
+ IF_IP ("iprecvopts", &opt_ip_recvopts)
+#endif
+#ifdef IP_RECVTOS
+ IF_IP ("iprecvtos", &opt_ip_recvtos)
+#endif
+#ifdef IP_RECVTTL
+ IF_IP ("iprecvttl", &opt_ip_recvttl)
+#endif
+#ifdef IP_RETOPTS
+ IF_IP ("ipretopts", &opt_ip_retopts)
+#endif
+#ifdef IP_ROUTER_ALERT
+ IF_IP ("iprouteralert", &opt_ip_router_alert)
+#endif
+ IF_IP ("iptos", &opt_ip_tos)
+ IF_IP ("ipttl", &opt_ip_ttl)
+ IF_IP6 ("ipv6-add-membership", &opt_ipv6_join_group)
+ IF_IP6 ("ipv6-join-group", &opt_ipv6_join_group)
+#ifdef IPV6_V6ONLY
+ IF_IP6 ("ipv6-v6only", &opt_ipv6_v6only)
+ IF_IP6 ("ipv6only", &opt_ipv6_v6only)
+#endif
+ IF_TERMIOS("isig", &opt_isig)
+#ifdef HAVE_TERMIOS_ISPEED
+ IF_TERMIOS("ispeed", &opt_ispeed)
+#endif
+ IF_TERMIOS("istrip", &opt_istrip)
+#ifdef IUCLC
+ IF_TERMIOS("iuclc", &opt_iuclc)
+#endif
+ IF_TERMIOS("ixany", &opt_ixany)
+ IF_TERMIOS("ixoff", &opt_ixoff)
+ IF_TERMIOS("ixon", &opt_ixon)
+ IF_IP6 ("join-group", &opt_ipv6_join_group)
+#if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
+ IF_ANY ("journal", &opt_ext2_journal_data)
+ IF_ANY ("journal-data", &opt_ext2_journal_data)
+#endif
+ IF_SOCKET ("keepalive", &opt_so_keepalive)
+#ifdef TCP_KEEPCNT /* Linux 2.4.0 */
+ IF_TCP ("keepcnt", &opt_tcp_keepcnt)
+#endif
+#ifdef TCP_KEEPIDLE /* Linux 2.4.0 */
+ IF_TCP ("keepidle", &opt_tcp_keepidle)
+#endif
+#ifdef TCP_KEEPINIT /* OSF1 */
+ IF_TCP ("keepinit", &opt_tcp_keepinit)
+#endif
+#ifdef TCP_KEEPINTVL /* Linux 2.4.0 */
+ IF_TCP ("keepintvl", &opt_tcp_keepintvl)
+#endif
+#ifdef SO_KERNACCEPT /* AIX 4.3.3 */
+ IF_SOCKET ("kernaccept", &opt_so_kernaccept)
+#endif /* SO_KERNACCEPT */
+ IF_OPENSSL("key", &opt_openssl_key)
+ IF_TERMIOS("kill", &opt_vkill)
+#ifdef O_LARGEFILE
+ IF_OPEN ("largefile", &opt_o_largefile)
+#endif
+#if WITH_LIBWRAP
+ IF_IPAPP ("libwrap", &opt_tcpwrappers)
+#endif
+ IF_SOCKET ("linger", &opt_so_linger)
+#ifdef TCP_LINGER2 /* Linux 2.4.0 */
+ IF_TCP ("linger2", &opt_tcp_linger2)
+#endif
+ IF_PTY ("link", &opt_symbolic_link)
+ IF_TERMIOS("lnext", &opt_vlnext)
+#if defined(F_SETLKW)
+ IF_ANY ("lock", &opt_f_setlkw_wr) /* POSIX, first choice */
+#elif defined(HAVE_FLOCK)
+ IF_ANY ("lock", &opt_flock_ex) /* BSD, fallback */
+#endif
+ IF_ANY ("lockfile", &opt_lockfile)
+#if defined(F_SETLKW)
+ IF_ANY ("lockw", &opt_f_setlkw_wr) /* POSIX, first choice */
+#elif defined(HAVE_FLOCK)
+ IF_ANY ("lockw", &opt_flock_ex_nb) /* BSD, fallback */
+#endif
+ IF_EXEC ("login", &opt_dash)
+ IF_TUN ("loopback", &opt_iff_loopback)
+ IF_IPAPP ("lowport", &opt_lowport)
+#if HAVE_LSEEK64
+ IF_ANY ("lseek", &opt_lseek64_set)
+#else
+ IF_ANY ("lseek", &opt_lseek32_set)
+#endif
+ IF_ANY ("lseek32", &opt_lseek32_set)
+ IF_ANY ("lseek32-cur", &opt_lseek32_cur)
+ IF_ANY ("lseek32-end", &opt_lseek32_end)
+ IF_ANY ("lseek32-set", &opt_lseek32_set)
+#if HAVE_LSEEK64
+ IF_ANY ("lseek64", &opt_lseek64_set)
+ IF_ANY ("lseek64-cur", &opt_lseek64_cur)
+ IF_ANY ("lseek64-end", &opt_lseek64_end)
+ IF_ANY ("lseek64-set", &opt_lseek64_set)
+#endif
+ IF_TUN ("master", &opt_iff_master)
+#ifdef TCP_MAXSEG
+ IF_TCP ("maxseg", &opt_tcp_maxseg)
+ IF_TCP ("maxseg-late", &opt_tcp_maxseg_late)
+#endif
+#ifdef TCP_MD5SUM
+ IF_TCP ("md5sig", &opt_tcp_md5sig)
+#endif
+#ifdef IP_ADD_MEMBERSHIP
+ IF_IP ("membership", &opt_ip_add_membership)
+#endif
+ IF_OPENSSL("method", &opt_openssl_method)
+ IF_TERMIOS("min", &opt_vmin)
+ IF_ANY ("mode", &opt_perm)
+#ifdef TCP_MAXSEG
+ IF_TCP ("mss", &opt_tcp_maxseg)
+ IF_TCP ("mss-late", &opt_tcp_maxseg_late)
+#endif
+#ifdef IP_MTU
+ IF_IP ("mtu", &opt_ip_mtu)
+#endif
+#ifdef IP_MTU_DISCOVER
+ IF_IP ("mtudiscover", &opt_ip_mtu_discover)
+#endif
+ IF_TUN ("multicast", &opt_iff_multicast)
+ IF_IP ("multicast-if", &opt_ip_multicast_if)
+ IF_IP ("multicast-loop", &opt_ip_multicast_loop)
+ IF_IP ("multicast-ttl", &opt_ip_multicast_ttl)
+ IF_IP ("multicastloop", &opt_ip_multicast_loop)
+ IF_IP ("multicastttl", &opt_ip_multicast_ttl)
+#if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
+ IF_ANY ("ndelay", &opt_o_ndelay)
+#else
+ IF_ANY ("ndelay", &opt_nonblock)
+#endif
+ IF_NAMED ("new", &opt_unlink_early)
+#ifdef NLDLY
+# ifdef NL0
+ IF_TERMIOS("nl0", &opt_nl0)
+# endif
+# ifdef NL1
+ IF_TERMIOS("nl1", &opt_nl1)
+# endif
+ IF_TERMIOS("nldly", &opt_nldly)
+#endif /* defined(NLDLY) */
+#ifdef SO_NO_CHECK
+ IF_SOCKET ("no-check", &opt_so_no_check)
+#endif
+ IF_TUN ("no-pi", &opt_iff_no_pi)
+ IF_TUN ("noarp", &opt_iff_noarp)
+#ifdef O_NOATIME
+ IF_OPEN ("noatime", &opt_o_noatime)
+#endif
+#ifdef SO_NO_CHECK
+ IF_SOCKET ("nocheck", &opt_so_no_check)
+#endif
+ IF_OPEN ("noctty", &opt_o_noctty)
+#ifdef TCP_NODELAY
+ IF_TCP ("nodelay", &opt_tcp_nodelay)
+#endif
+#if WITH_EXT2 && defined(EXT2_NODUMP_FL)
+ IF_ANY ("nodump", &opt_ext2_nodump)
+#endif
+#if HAVE_REGEX_H
+ IF_READLINE("noecho", &opt_noecho)
+#endif /* HAVE_REGEX_H */
+ IF_TERMIOS("noflsh", &opt_noflsh)
+#ifdef O_NOFOLLOW
+ IF_OPEN ("nofollow", &opt_o_nofollow)
+#endif
+ IF_EXEC ("nofork", &opt_nofork)
+#ifdef O_NOINHERIT
+ IF_ANY ("noinherit", &opt_o_noinherit)
+#endif
+ IF_ANY ("nonblock", &opt_nonblock)
+#ifdef TCP_NOOPT
+ IF_TCP ("noopt", &opt_tcp_noopt)
+#endif
+ IF_READLINE("noprompt", &opt_noprompt)
+#ifdef TCP_NOPUSH
+ IF_TCP ("nopush", &opt_tcp_nopush)
+#endif
+#ifdef SO_NOREUSEADDR /* AIX 4.3.3 */
+ IF_SOCKET ("noreuseaddr", &opt_so_noreuseaddr)
+#endif /* SO_NOREUSEADDR */
+ IF_TUN ("notrailers", &opt_iff_notrailers)
+#ifdef O_NSHARE
+ IF_OPEN ("nshare", &opt_o_nshare)
+#endif
+#ifdef O_ASYNC
+ IF_ANY ("o-async", &opt_async)
+#endif
+#ifdef O_BINARY
+ IF_OPEN ("o-binary", &opt_o_binary)
+#endif
+ IF_OPEN ("o-creat", &opt_o_create)
+ 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
+#ifdef O_NOATIME
+ IF_OPEN ("o-noatime", &opt_o_noatime)
+#endif
+ IF_OPEN ("o-noctty", &opt_o_noctty)
+#ifdef O_NOFOLLOW
+ IF_OPEN ("o-nofollow", &opt_o_nofollow)
+#endif
+#ifdef O_NOINHERIT
+ IF_ANY ("o-noinherit", &opt_o_noinherit)
+#endif
+ IF_ANY ("o-nonblock", &opt_nonblock)
+#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
+#ifdef O_TEXT
+ IF_ANY ("o-text", &opt_o_text)
+#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
+#ifdef OFDEL
+ IF_TERMIOS("ofdel", &opt_ofdel)
+#endif
+#ifdef OFILL
+ IF_TERMIOS("ofill", &opt_ofill)
+#endif
+#ifdef OLCUC
+ IF_TERMIOS("olcuc", &opt_olcuc)
+#endif
+ IF_TERMIOS("onlcr", &opt_onlcr)
+#ifdef ONLRET
+ IF_TERMIOS("onlret", &opt_onlret)
+#endif
+#ifdef ONOCR
+ IF_TERMIOS("onocr", &opt_onocr)
+#endif
+ IF_SOCKET ("oobinline", &opt_so_oobinline)
+#if HAVE_OPENPTY
+ IF_EXEC ("openpty", &opt_openpty)
+#endif /* HAVE_OPENPTY */
+ IF_OPENSSL("openssl-cafile", &opt_openssl_cafile)
+ IF_OPENSSL("openssl-capath", &opt_openssl_capath)
+ IF_OPENSSL("openssl-certificate", &opt_openssl_certificate)
+ IF_OPENSSL("openssl-cipherlist", &opt_openssl_cipherlist)
+ IF_OPENSSL("openssl-dhparam", &opt_openssl_dhparam)
+ IF_OPENSSL("openssl-egd", &opt_openssl_egd)
+#if WITH_FIPS
+ IF_OPENSSL("openssl-fips", &opt_openssl_fips)
+#endif
+ IF_OPENSSL("openssl-key", &opt_openssl_key)
+ IF_OPENSSL("openssl-method", &opt_openssl_method)
+ IF_OPENSSL("openssl-pseudo", &opt_openssl_pseudo)
+ IF_OPENSSL("openssl-verify", &opt_openssl_verify)
+ IF_TERMIOS("opost", &opt_opost)
+#ifdef HAVE_TERMIOS_ISPEED
+ IF_TERMIOS("ospeed", &opt_ospeed)
+#endif
+ IF_ANY ("owner", &opt_user)
+ IF_TERMIOS("parenb", &opt_parenb)
+ IF_TERMIOS("parmrk", &opt_parmrk)
+ IF_TERMIOS("parodd", &opt_parodd)
+#ifdef SO_PASSCRED
+ IF_SOCKET ("passcred", &opt_so_passcred)
+#endif
+ IF_EXEC ("path", &opt_path)
+#ifdef TCP_PAWS /* OSF1 */
+ IF_TCP ("paws", &opt_tcp_paws)
+#endif
+#ifdef SO_PEERCRED
+ IF_SOCKET ("peercred", &opt_so_peercred)
+#endif
+#ifdef PENDIN
+ IF_TERMIOS("pendin", &opt_pendin)
+#endif
+ IF_ANY ("perm", &opt_perm)
+ IF_NAMED ("perm-early", &opt_perm_early)
+ IF_ANY ("perm-late", &opt_perm_late)
+ IF_SOCKET ("pf", &opt_protocol_family)
+ IF_EXEC ("pgid", &opt_setpgid)
+ IF_EXEC ("pipes", &opt_pipes)
+#ifdef IP_PKTINFO
+ IF_IP ("pktinfo", &opt_ip_pktinfo)
+#endif
+#ifdef IP_PKTOPTIONS
+ IF_IP ("pktoptions", &opt_ip_pktoptions)
+ IF_IP ("pktopts", &opt_ip_pktoptions)
+#endif
+ IF_TUN ("pointopoint", &opt_iff_pointopoint)
+ /*IF_IPAPP("port", &opt_port)*/
+ IF_TUN ("portsel", &opt_iff_portsel)
+#if HAVE_RESOLV_H
+ IF_IP ("primary", &opt_res_primary)
+#endif /* HAVE_RESOLV_H */
+#ifdef SO_PRIORITY
+ IF_SOCKET ("priority", &opt_so_priority)
+#endif
+#ifdef O_PRIV
+ IF_OPEN ("priv", &opt_o_priv)
+#endif
+ IF_TUN ("promisc", &opt_iff_promisc)
+ IF_READLINE("prompt", &opt_prompt)
+ 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-resolve", &opt_proxy_resolve)
+ IF_PROXY ("proxyauth", &opt_proxy_authorization)
+ IF_PROXY ("proxyport", &opt_proxyport)
+#ifdef ECHOPRT
+ IF_TERMIOS("prterase", &opt_echoprt)
+#endif
+ IF_OPENSSL("pseudo", &opt_openssl_pseudo)
+#if HAVE_DEV_PTMX || HAVE_DEV_PTC
+ IF_EXEC ("ptmx", &opt_ptmx)
+#endif
+#if HAVE_PTY
+ IF_EXEC ("pty", &opt_pty)
+#endif
+#if HAVE_PTY && HAVE_POLL
+ IF_PTY ("pty-intervall", &opt_pty_intervall)
+ IF_PTY ("pty-wait-slave", &opt_pty_wait_slave)
+#endif /* HAVE_PTY && HAVE_POLL */
+#ifdef TCP_QUICKACK
+ IF_TCP ("quickack", &opt_tcp_quickack)
+#endif
+ IF_TERMIOS("quit", &opt_vquit)
+ IF_RANGE ("range", &opt_range)
+ IF_TERMIOS("raw", &opt_raw)
+ IF_SOCKET ("rcvbuf", &opt_so_rcvbuf)
+ IF_SOCKET ("rcvbuf-late", &opt_so_rcvbuf_late)
+#ifdef SO_RCVLOWAT
+ IF_SOCKET ("rcvlowat", &opt_so_rcvlowat)
+#endif
+#ifdef SO_RCVTIMEO
+ IF_SOCKET ("rcvtimeo", &opt_so_rcvtimeo)
+#endif
+ IF_OPEN ("rdonly", &opt_o_rdonly)
+ IF_OPEN ("rdwr", &opt_o_rdwr)
+ IF_ANY ("readbytes", &opt_readbytes)
+#if HAVE_RESOLV_H
+ IF_IP ("recurse", &opt_res_recurse)
+#endif /* HAVE_RESOLV_H */
+#ifdef IP_RECVERR
+ IF_IP ("recverr", &opt_ip_recverr)
+#endif
+#ifdef IP_RECVOPTS
+ IF_IP ("recvopts", &opt_ip_recvopts)
+#endif
+#ifdef IP_RECVTOS
+ IF_IP ("recvtos", &opt_ip_recvtos)
+#endif
+#ifdef IP_RECVTTL
+ IF_IP ("recvttl", &opt_ip_recvttl)
+#endif
+ IF_NAMED ("remove", &opt_unlink)
+#ifdef VREPRINT
+ IF_TERMIOS("reprint", &opt_vreprint)
+#endif
+#if HAVE_RESOLV_H
+ IF_IP ("res-aaonly", &opt_res_aaonly)
+ IF_IP ("res-debug", &opt_res_debug)
+ IF_IP ("res-defnames", &opt_res_defnames)
+ IF_IP ("res-dnsrch", &opt_res_dnsrch)
+ IF_IP ("res-igntc", &opt_res_igntc)
+ IF_IP ("res-primary", &opt_res_primary)
+ IF_IP ("res-recurse", &opt_res_recurse)
+ IF_IP ("res-stayopen", &opt_res_stayopen)
+ IF_IP ("res-usevc", &opt_res_usevc)
+#endif /* HAVE_RESOLV_H */
+ IF_PROXY ("resolv", &opt_proxy_resolve)
+ IF_PROXY ("resolve", &opt_proxy_resolve)
+#ifdef IP_RETOPTS
+ IF_IP ("retopts", &opt_ip_retopts)
+#endif
+ IF_RETRY ("retry", &opt_retry)
+ IF_SOCKET ("reuseaddr", &opt_so_reuseaddr)
+#ifdef SO_REUSEPORT /* AIX 4.3.3 */
+ IF_SOCKET ("reuseport", &opt_so_reuseport)
+#endif /* defined(SO_REUSEPORT) */
+#ifdef TCP_RFC1323
+ IF_TCP ("rfc1323", &opt_tcp_rfc1323)
+#endif
+#ifdef IP_ROUTER_ALERT
+ IF_IP ("routeralert", &opt_ip_router_alert)
+#endif
+#ifdef VREPRINT
+ IF_TERMIOS("rprnt", &opt_vreprint)
+#endif
+#ifdef O_RSHARE
+ IF_OPEN ("rshare", &opt_o_rshare)
+#endif
+#ifdef O_RSYNC
+ IF_OPEN ("rsync", &opt_o_rsync)
+#endif
+ IF_TUN ("running", &opt_iff_running)
+#ifdef TCP_SACK_DISABLE
+ IF_TCP ("sack-disable", &opt_tcp_sack_disable)
+#endif
+#ifdef TCP_SACKENA /* OSF1 */
+ IF_TCP ("sackena", &opt_tcp_sackena)
+#endif
+ IF_TERMIOS("sane", &opt_sane)
+#if WITH_EXT2 && defined(EXT2_SECRM_FL)
+ IF_ANY ("secrm", &opt_ext2_secrm)
+#endif
+#ifdef SO_SECURITY_AUTHENTICATION
+ IF_SOCKET ("security-authentication", &opt_so_security_authentication)
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_NETWORK
+ IF_SOCKET ("security-encryption-network", &opt_so_security_encryption_network)
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
+ IF_SOCKET ("security-encryption-transport", &opt_so_security_encryption_transport)
+#endif
+#ifdef SO_SECURITY_AUTHENTICATION
+ IF_SOCKET ("securityauthentication", &opt_so_security_authentication)
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_NETWORK
+ IF_SOCKET ("securityencryptionnetwork", &opt_so_security_encryption_network)
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
+ IF_SOCKET ("securityencryptiontransport", &opt_so_security_encryption_transport)
+#endif
+#if HAVE_LSEEK64
+ IF_ANY ("seek", &opt_lseek64_set)
+ IF_ANY ("seek-cur", &opt_lseek64_cur)
+ IF_ANY ("seek-end", &opt_lseek64_end)
+ IF_ANY ("seek-set", &opt_lseek64_set)
+#else
+ IF_ANY ("seek", &opt_lseek32_set)
+ IF_ANY ("seek-cur", &opt_lseek32_cur)
+ IF_ANY ("seek-end", &opt_lseek32_end)
+ IF_ANY ("seek-set", &opt_lseek32_set)
+#endif
+ IF_ANY ("setgid", &opt_setgid)
+ IF_ANY ("setgid-early", &opt_setgid_early)
+ IF_ANY ("setlk", &opt_f_setlk_wr)
+ IF_ANY ("setlk-rd", &opt_f_setlk_rd)
+ IF_ANY ("setlk-wr", &opt_f_setlk_wr)
+ IF_ANY ("setlkw", &opt_f_setlkw_wr)
+ IF_ANY ("setlkw-rd", &opt_f_setlkw_rd)
+ IF_ANY ("setlkw-wr", &opt_f_setlkw_wr)
+ IF_EXEC ("setpgid", &opt_setpgid)
+#if WITH_EXEC || WITH_SYSTEM
+ IF_EXEC ("setsid", &opt_setsid)
+#endif
+ IF_ANY ("setuid", &opt_setuid)
+ IF_ANY ("setuid-early", &opt_setuid_early)
+#if WITH_EXEC || WITH_SYSTEM
+ IF_ANY ("sid", &opt_setsid)
+#endif
+ IF_EXEC ("sighup", &opt_sighup)
+ IF_EXEC ("sigint", &opt_sigint)
+#ifdef TCP_SIGNATURE_ENABLE
+ IF_TCP ("signature-enable", &opt_tcp_signature_enable)
+#endif
+ IF_EXEC ("sigquit", &opt_sigquit)
+#ifdef SIOCSPGRP
+ IF_SOCKET ("siocspgrp", &opt_siocspgrp)
+#endif
+ IF_TUN ("slave", &opt_iff_slave)
+ IF_SOCKET ("sndbuf", &opt_so_sndbuf)
+ IF_SOCKET ("sndbuf-late", &opt_so_sndbuf_late)
+#ifdef SO_SNDLOWAT
+ IF_SOCKET ("sndlowat", &opt_so_sndlowat)
+#endif
+#ifdef SO_SNDTIMEO
+ IF_SOCKET ("sndtimeo", &opt_so_sndtimeo)
+#endif
+#ifdef SO_ACCEPTCONN /* AIX433 */
+ IF_SOCKET ("so-acceptconn", &opt_so_acceptconn)
+#endif /* SO_ACCEPTCONN */
+#ifdef SO_ATTACH_FILTER
+ IF_SOCKET ("so-attach-filter", &opt_so_attach_filter)
+#endif
+#ifdef SO_AUDIT /* AIX 4.3.3 */
+ IF_SOCKET ("so-audit", &opt_so_audit)
+#endif /* SO_AUDIT */
+#ifdef SO_BINDTODEVICE
+ IF_SOCKET ("so-bindtodevice", &opt_so_bindtodevice)
+#endif
+ IF_SOCKET ("so-broadcast", &opt_so_broadcast)
+#ifdef SO_BSDCOMPAT
+ IF_SOCKET ("so-bsdcompat", &opt_so_bsdcompat)
+#endif
+#ifdef SO_CKSUMRECV
+ IF_SOCKET ("so-cksumrecv", &opt_so_cksumrecv)
+#endif /* SO_CKSUMRECV */
+ IF_SOCKET ("so-debug", &opt_so_debug)
+#ifdef SO_DETACH_FILTER
+ IF_SOCKET ("so-detach-filter", &opt_so_detach_filter)
+#endif
+#ifdef SO_DGRAM_ERRIND
+ IF_SOCKET ("so-dgram-errind", &opt_so_dgram_errind)
+#endif
+#ifdef SO_DONTLINGER
+ IF_SOCKET ("so-dontlinger", &opt_so_dontlinger)
+#endif
+ IF_SOCKET ("so-dontroute", &opt_so_dontroute)
+ IF_SOCKET ("so-error", &opt_so_error)
+ IF_SOCKET ("so-keepalive", &opt_so_keepalive)
+#ifdef SO_KERNACCEPT /* AIX 4.3.3 */
+ IF_SOCKET ("so-kernaccept", &opt_so_kernaccept)
+#endif /* SO_KERNACCEPT */
+ IF_SOCKET ("so-linger", &opt_so_linger)
+#ifdef SO_NO_CHECK
+ IF_SOCKET ("so-no-check", &opt_so_no_check)
+#endif
+#ifdef SO_NOREUSEADDR /* AIX 4.3.3 */
+ IF_SOCKET ("so-noreuseaddr", &opt_so_noreuseaddr)
+#endif /* SO_NOREUSEADDR */
+ IF_SOCKET ("so-oobinline", &opt_so_oobinline)
+#ifdef SO_PASSCRED
+ IF_SOCKET ("so-passcred", &opt_so_passcred)
+#endif
+#ifdef SO_PEERCRED
+ IF_SOCKET ("so-peercred", &opt_so_peercred)
+#endif
+#ifdef SO_PRIORITY
+ IF_SOCKET ("so-priority", &opt_so_priority)
+#endif
+#ifdef SO_PROTOTYPE
+ IF_SOCKET ("so-prototype", &opt_so_prototype)
+#endif
+ IF_SOCKET ("so-rcvbuf", &opt_so_rcvbuf)
+ IF_SOCKET ("so-rcvbuf-late", &opt_so_rcvbuf_late)
+#ifdef SO_RCVLOWAT
+ IF_SOCKET ("so-rcvlowat", &opt_so_rcvlowat)
+#endif
+#ifdef SO_RCVTIMEO
+ IF_SOCKET ("so-rcvtimeo", &opt_so_rcvtimeo)
+#endif
+ IF_SOCKET ("so-reuseaddr", &opt_so_reuseaddr)
+#ifdef SO_REUSEPORT /* AIX 4.3.3 */
+ IF_SOCKET ("so-reuseport", &opt_so_reuseport)
+#endif /* defined(SO_REUSEPORT) */
+#ifdef SO_SECURITY_AUTHENTICATION
+ IF_SOCKET ("so-security-authentication", &opt_so_security_authentication)
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_NETWORK
+ IF_SOCKET ("so-security-encryption-network", &opt_so_security_encryption_network)
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
+ IF_SOCKET ("so-security-encryption-transport", &opt_so_security_encryption_transport)
+#endif
+ IF_SOCKET ("so-sndbuf", &opt_so_sndbuf)
+ IF_SOCKET ("so-sndbuf-late", &opt_so_sndbuf_late)
+#ifdef SO_SNDLOWAT
+ IF_SOCKET ("so-sndlowat", &opt_so_sndlowat)
+#endif
+#ifdef SO_SNDTIMEO
+ IF_SOCKET ("so-sndtimeo", &opt_so_sndtimeo)
+#endif
+ IF_SOCKET ("so-type", &opt_so_type)
+#ifdef SO_USE_IFBUFS
+ IF_SOCKET ("so-use-ifbufs", &opt_so_use_ifbufs)
+#endif /* SO_USE_IFBUFS */
+#ifdef SO_USELOOPBACK /* AIX433, Solaris */
+ IF_SOCKET ("so-useloopback", &opt_so_useloopback)
+#endif /* SO_USELOOPBACK */
+ IF_SOCKS4 ("socksport", &opt_socksport)
+ IF_SOCKS4 ("socksuser", &opt_socksuser)
+ IF_IPAPP ("sourceport", &opt_sourceport)
+ IF_IPAPP ("sp", &opt_sourceport)
+ IF_TERMIOS("start", &opt_vstart)
+#if HAVE_RESOLV_H
+ IF_IP ("stayopen", &opt_res_stayopen)
+#endif /* HAVE_RESOLV_H */
+ IF_EXEC ("stderr", &opt_stderr)
+#ifdef TCP_STDURG
+ IF_TCP ("stdurg", &opt_tcp_stdurg)
+#endif
+ IF_TERMIOS("stop", &opt_vstop)
+ IF_ANY ("su", &opt_substuser)
+ IF_ANY ("su-d", &opt_substuser_delayed)
+ IF_ANY ("substuser", &opt_substuser)
+ IF_ANY ("substuser-delayed", &opt_substuser_delayed)
+ IF_TERMIOS("susp", &opt_vsusp)
+#ifdef VSWTC
+ IF_TERMIOS("swtc", &opt_vswtc)
+ IF_TERMIOS("swtch", &opt_vswtc)
+#endif
+ IF_PTY ("symbolic-link", &opt_symbolic_link)
+#ifdef O_SYNC
+ IF_OPEN ("sync", &opt_o_sync)
+#elif EXT2_SYNC_FL
+ IF_ANY ("sync", &opt_ext2_sync)
+#endif
+#ifdef TCP_SYNCNT
+ IF_TCP ("syncnt", &opt_tcp_syncnt)
+#endif
+#ifdef TABDLY
+# ifdef TAB0
+ IF_TERMIOS("tab0", &opt_tab0)
+# endif
+# ifdef TAB1
+ IF_TERMIOS("tab1", &opt_tab1)
+# endif
+# ifdef TAB2
+ IF_TERMIOS("tab2", &opt_tab2)
+# endif
+# ifdef TAB3
+ IF_TERMIOS("tab3", &opt_tab3)
+# endif
+ IF_TERMIOS("tabdly", &opt_tabdly)
+#endif
+ IF_TERMIOS("tandem", &opt_ixoff)
+#ifdef TCP_ABORT_THRESHOLD /* HP_UX */
+ IF_TCP ("tcp-abort-threshold", &opt_tcp_abort_threshold)
+#endif
+#ifdef TCP_CONN_ABORT_THRESHOLD /* HP_UX */
+ IF_TCP ("tcp-conn-abort-threshold", &opt_tcp_conn_abort_threshold)
+#endif
+#ifdef TCP_CORK
+ IF_TCP ("tcp-cork", &opt_tcp_cork)
+#endif
+#ifdef TCP_DEFER_ACCEPT /* Linux 2.4.0 */
+ IF_TCP ("tcp-defer-accept", &opt_tcp_defer_accept)
+#endif
+#ifdef TCP_INFO /* Linux 2.4.0 */
+ IF_TCP ("tcp-info", &opt_tcp_info)
+#endif
+#ifdef TCP_KEEPCNT /* Linux 2.4.0 */
+ IF_TCP ("tcp-keepcnt", &opt_tcp_keepcnt)
+#endif
+#ifdef TCP_KEEPIDLE /* Linux 2.4.0 */
+ IF_TCP ("tcp-keepidle", &opt_tcp_keepidle)
+#endif
+#ifdef TCP_KEEPINIT /* OSF1 */
+ IF_TCP ("tcp-keepinit", &opt_tcp_keepinit)
+#endif
+#ifdef TCP_KEEPINTVL /* Linux 2.4.0 */
+ IF_TCP ("tcp-keepintvl", &opt_tcp_keepintvl)
+#endif
+#ifdef TCP_LINGER2 /* Linux 2.4.0 */
+ IF_TCP ("tcp-linger2", &opt_tcp_linger2)
+#endif
+#ifdef TCP_MAXSEG
+ IF_TCP ("tcp-maxseg", &opt_tcp_maxseg)
+ IF_TCP ("tcp-maxseg-late", &opt_tcp_maxseg_late)
+#endif
+#ifdef TCP_MD5SIG
+ IF_TCP ("tcp-md5sig", &opt_tcp_md5sig)
+#endif
+#ifdef TCP_NODELAY
+ IF_TCP ("tcp-nodelay", &opt_tcp_nodelay)
+#endif
+#ifdef TCP_NOOPT
+ IF_TCP ("tcp-noopt", &opt_tcp_noopt)
+#endif
+#ifdef TCP_NOPUSH
+ IF_TCP ("tcp-nopush", &opt_tcp_nopush)
+#endif
+#ifdef TCP_PAWS /* OSF1 */
+ IF_TCP ("tcp-paws", &opt_tcp_paws)
+#endif
+#ifdef TCP_QUICKACK
+ IF_TCP ("tcp-quickack", &opt_tcp_quickack)
+#endif
+#ifdef TCP_RFC1323
+ IF_TCP ("tcp-rfc1323", &opt_tcp_rfc1323)
+#endif
+#ifdef TCP_SACK_DISABLE
+ IF_TCP ("tcp-sack-disable", &opt_tcp_sack_disable)
+#endif
+#ifdef TCP_SACKENA /* OSF1 */
+ IF_TCP ("tcp-sackena", &opt_tcp_sackena)
+#endif
+#ifdef TCP_SIGNATURE_ENABLE
+ IF_TCP ("tcp-signature-enable", &opt_tcp_signature_enable)
+#endif
+#ifdef TCP_STDURG
+ IF_TCP ("tcp-stdurg", &opt_tcp_stdurg)
+#endif
+#ifdef TCP_SYNCNT /* Linux 2.4.0 */
+ IF_TCP ("tcp-syncnt", &opt_tcp_syncnt)
+#endif
+#ifdef TCP_TSOPTENA /* OSF1 */
+ IF_TCP ("tcp-tsoptena", &opt_tcp_tsoptena)
+#endif
+#ifdef TCP_WINDOW_CLAMP /* Linux 2.4.0 */
+ IF_TCP ("tcp-window-clamp", &opt_tcp_window_clamp)
+#endif
+#if WITH_LIBWRAP
+ IF_IPAPP ("tcpwrap", &opt_tcpwrappers)
+ IF_IPAPP ("tcpwrap-dir", &opt_tcpwrap_etc)
+ IF_IPAPP ("tcpwrap-etc", &opt_tcpwrap_etc)
+#if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
+ IF_IPAPP ("tcpwrap-hosts-allow-table", &opt_tcpwrap_hosts_allow_table)
+#endif
+#if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
+ IF_IPAPP ("tcpwrap-hosts-deny-table", &opt_tcpwrap_hosts_deny_table)
+#endif
+ IF_IPAPP ("tcpwrapper", &opt_tcpwrappers)
+ IF_IPAPP ("tcpwrappers", &opt_tcpwrappers)
+#endif
+#ifdef O_TEXT
+ IF_ANY ("text", &opt_o_text)
+#endif
+ IF_UNIX ("tightsocklen", &opt_unix_tightsocklen)
+ IF_TERMIOS("time", &opt_vtime)
+ IF_TERMIOS("tiocsctty", &opt_tiocsctty)
+#if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
+ IF_ANY ("topdir", &opt_ext2_topdir)
+#endif
+ IF_IP ("tos", &opt_ip_tos)
+ IF_TERMIOS("tostop", &opt_tostop)
+ IF_OPEN ("trunc", &opt_o_trunc)
+#if HAVE_FTRUNCATE64
+ IF_ANY ("truncate", &opt_ftruncate64)
+#else
+ IF_ANY ("truncate", &opt_ftruncate32)
+#endif
+#ifdef TCP_TSOPTENA /* OSF1 */
+ IF_TCP ("tsoptena", &opt_tcp_tsoptena)
+#endif
+ IF_IP ("ttl", &opt_ip_ttl)
+ IF_TUN ("tun-device", &opt_tun_device)
+ IF_TUN ("tun-name", &opt_tun_name)
+ IF_TUN ("tun-no-pi", &opt_iff_no_pi)
+ IF_TUN ("tun-type", &opt_tun_type)
+ IF_SOCKET ("type", &opt_so_type)
+ IF_ANY ("uid", &opt_user)
+ 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_NAMED ("unlink", &opt_unlink)
+ IF_NAMED ("unlink-close", &opt_unlink_close)
+ IF_NAMED ("unlink-early", &opt_unlink_early)
+ IF_NAMED ("unlink-late", &opt_unlink_late)
+#if WITH_EXT2 && defined(EXT2_UNRM_FL)
+ IF_ANY ("unrm", &opt_ext2_unrm)
+#endif
+ IF_TUN ("up", &opt_iff_up)
+#ifdef SO_USE_IFBUFS
+ IF_SOCKET ("use-ifbufs", &opt_so_use_ifbufs)
+ IF_SOCKET ("useifbufs", &opt_so_use_ifbufs)
+#endif /* SO_USE_IFBUFS */
+#ifdef SO_USELOOPBACK /* AIX433, Solaris */
+ IF_SOCKET ("useloopback", &opt_so_useloopback)
+#endif /* SO_USELOOPBACK */
+ IF_ANY ("user", &opt_user)
+ IF_NAMED ("user-early", &opt_user_early)
+ IF_ANY ("user-late", &opt_user_late)
+#if HAVE_RESOLV_H
+ IF_IP ("usevc", &opt_res_usevc)
+#endif /* HAVE_RESOLV_H */
+#ifdef IPV6_V6ONLY
+ IF_IP6 ("v6only", &opt_ipv6_v6only)
+#endif
+#ifdef VDISCARD
+ IF_TERMIOS("vdiscard", &opt_vdiscard)
+#endif
+#ifdef VDSUSP /* HP-UX */
+ IF_TERMIOS("vdsusp", &opt_vdsusp)
+#endif
+ IF_TERMIOS("veof", &opt_veof)
+ IF_TERMIOS("veol", &opt_veol)
+ IF_TERMIOS("veol2", &opt_veol2)
+ IF_TERMIOS("verase", &opt_verase)
+ IF_OPENSSL("verify", &opt_openssl_verify)
+ IF_TERMIOS("vintr", &opt_vintr)
+ IF_TERMIOS("vkill", &opt_vkill)
+ IF_TERMIOS("vlnext", &opt_vlnext)
+ IF_TERMIOS("vmin", &opt_vmin)
+ IF_TERMIOS("vquit", &opt_vquit)
+#ifdef VREPRINT
+ IF_TERMIOS("vreprint", &opt_vreprint)
+#endif
+ IF_TERMIOS("vstart", &opt_vstart)
+ IF_TERMIOS("vstop", &opt_vstop)
+ IF_TERMIOS("vsusp", &opt_vsusp)
+#ifdef VSWTC
+ IF_TERMIOS("vswtc", &opt_vswtc)
+#endif
+#ifdef VTDLY
+# ifdef VT0
+ IF_TERMIOS("vt0", &opt_vt0)
+# endif
+# ifdef VT1
+ IF_TERMIOS("vt1", &opt_vt1)
+# endif
+ IF_TERMIOS("vtdly", &opt_vtdly)
+#endif
+ IF_TERMIOS("vtime", &opt_vtime)
+#ifdef VWERASE
+ IF_TERMIOS("vwerase", &opt_vwerase)
+#endif
+#if HAVE_PTY && HAVE_POLL
+ IF_PTY ("wait-slave", &opt_pty_wait_slave)
+ IF_ANY ("waitlock", &opt_waitlock)
+ IF_PTY ("waitslave", &opt_pty_wait_slave)
+#endif /* HAVE_PTY && HAVE_POLL */
+#ifdef VWERASE
+ IF_TERMIOS("werase", &opt_vwerase)
+#endif
+#ifdef TCP_WINDOW_CLAMP /* Linux 2.4.0 */
+ IF_TCP ("window-clamp", &opt_tcp_window_clamp)
+#endif
+#if WITH_LIBWRAP
+ IF_IPAPP ("wrap", &opt_tcpwrappers)
+#endif
+ IF_OPEN ("wronly", &opt_o_wronly)
+#ifdef XCASE
+ IF_TERMIOS("xcase", &opt_xcase)
+#endif
+#if defined(TABDLY) && defined(XTABS)
+ IF_TERMIOS("xtabs", &opt_xtabs)
+#endif
+ { NULL }
+} ;
+
+
+/* walks the text argument a and writes its options that conform to groups
+ to the array opts. Uses the option table 'optionnames'.
+ returns 0 on success, -1 on error, 1 on unknown/wrong option
+*/
+int parseopts(const char **a, unsigned int groups, struct opt **opts) {
+
+ return parseopts_table(a, groups, opts, optionnames,
+ sizeof(optionnames)/sizeof(struct optname)-1);
+}
+
+
+/* walks the text argument a and writes its options that conform to groups
+ to the array opts. Uses the specified option table.
+ returns 0 on success, -1 on error, 1 on unknown/wrong option
+*/
+int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
+ const struct optname optionnames[], size_t optionnum) {
+ int i=0;
+ struct opt *opt;
+ bool assign;
+ const char *a0 = *a;
+ unsigned long ulongval;
+ long slongval;
+ long long slonglongval;
+ char token[512], *tokp; size_t len;
+ int parsres;
+ int result;
+ char optbuf[256]; size_t optlen;
+ const char *endkey[6+1];
+ const char *endval[5+1];
+ const char *assign_str = "=";
+ const char *hquotes[] = {
+ "'",
+ NULL
+ } ;
+ const char *squotes[] = {
+ "\"",
+ NULL
+ } ;
+ const char *nests[] = {
+ "(", ")",
+ "[", "]",
+ "{", "}",
+ NULL
+ } ;
+
+ i = 0;
+ /*endkey[i++] = xioopts.chainsep;*/ /* default: "|" */
+ endkey[i++] = xioopts.pipesep; /* default: "!!" */
+ endkey[i++] = ","/*xioopts.comma*/; /* default: "," */
+ endkey[i++] = "=";
+ endkey[i++] = NULL;
+
+ i = 0;
+ /*endval[i++] = xioopts.chainsep;*/ /* default: "|" */
+ endval[i++] = xioopts.pipesep; /* default: "!!" */
+ endval[i++] = ","/*xioopts.comma*/; /* default: "," */
+ endval[i++] = NULL;
+
+ i = 0;
+ *opts = Malloc((i+8)*sizeof(struct opt));
+ if (*opts == NULL) {
+ return -1;
+ }
+ if (*a == NULL) {
+ (*opts)[i].desc = ODESC_END;
+ return 0;
+ }
+
+ while (true) {
+ const struct optname *ent;
+
+ if (a == NULL || *a == NULL || **a == '\0')
+ break;
+
+ while (!strncmp(*a, ",", strlen(","))) { (*a) += strlen(","); }
+ a0 = *a;
+
+ len = sizeof(token); tokp = token;
+ parsres =
+ nestlex(a, &tokp, &len, endkey, hquotes, squotes, nests,
+ true, true, false);
+ if (parsres != 0) {
+ return -1;
+ }
+ if (tokp == token) {
+ /* no option found */
+ break;
+ }
+ *tokp = '\0';
+
+ ent = (struct optname *)
+ keyw((struct wordent *)optionnames, token, optionnum);
+ if (ent == NULL) {
+ Error1("parseopts(): unknown option \"%s\"", token);
+ continue;
+ }
+
+ if (!(ent->desc->group & groups) && !(ent->desc->group & GROUP_ANY) &&
+ !xioopts_ignoregroups) {
+ Error1("parseopts(): option \"%s\" not supported with this address type",
+ token /*a0*/);
+ Info2("parseopts() groups=%08x, ent->group=%08x",
+ groups, ent->desc->group);
+#if 0
+ continue;
+#endif
+ }
+ (*opts)[i].desc = ent->desc;
+
+ if (!strncmp(*a, assign_str, strlen(assign_str))) {
+ /* there is an assignment (mostly "=") */
+ (*a) += strlen(assign_str);
+ len = sizeof(token); tokp = token;
+ parsres =
+ nestlex(a, &tokp, &len, endval, hquotes, squotes, nests,
+ true, true, false);
+ if (parsres != 0) {
+ return -1;
+ }
+ *tokp = '\0';
+ assign = true;
+
+ } else {
+ assign = false;
+ }
+ opt = &(*opts)[i];
+
+ switch (ent->desc->type) {
+ case TYPE_CONST:
+ if (assign) {
+ Error1("no value permitted for option \"%s\"",
+ ent->desc->defname);
+ continue;
+ }
+ Info1("setting option \"%s\"", ent->desc->defname);
+ break;
+ case TYPE_BIN:
+ if (!assign) { Error1("option \"%s\": value required", a0);
+ continue; }
+ optlen = 0;
+ if ((result = dalan(token, optbuf, &optlen, sizeof(optbuf))) != 0) {
+ Error1("parseopts(): problem with \"%s\" data", token);
+ continue;
+ }
+ if (((*opts)[i].value.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
+ Error1("memdup(, "F_Zu"): out of memory", optlen);
+ return -1;
+ }
+ (*opts)[i].value.u_bin.b_len = optlen;
+ break;
+ case TYPE_BYTE:
+ {
+ unsigned long ul;
+ if (token) {
+ char *rest;
+ ul = strtoul(token, &rest/*!*/, 0);
+ } else {
+ ul = 1;
+ }
+ 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;
+ }
+ }
+ break;
+ case TYPE_INT:
+ if (assign) {
+ char *rest;
+ (*opts)[i].value.u_int = strtoul(token, &rest/*!*/, 0);
+ } else {
+ (*opts)[i].value.u_int = 1;
+ }
+ Info2("setting option \"%s\" to %d", ent->desc->defname,
+ (*opts)[i].value.u_int);
+ break;
+ case TYPE_BOOL:
+ if (!assign) {
+ (*opts)[i].value.u_bool = 1;
+ } else {
+ char *rest;
+ (*opts)[i].value.u_bool = strtoul(token, &rest, 0);
+ if (rest && *rest) {
+ Error1("error in option \"%s\": \"0\" or \"1\" required", a0);
+ }
+ }
+ Info2("setting option \"%s\" to %d", ent->desc->defname,
+ (*opts)[i].value.u_bool);
+ break;
+
+#if HAVE_BASIC_SIZE_T==4
+ case TYPE_SIZE_T:
+#endif
+ case TYPE_UINT:
+ if (!assign) {
+ (*opts)[i].value.u_uint = 1;
+ } else {
+ char *rest;
+ ulongval = strtoul(token, &rest/*!*/, 0);
+ if (ulongval > UINT_MAX) {
+ Error3("parseopts(%s): unsigned int value exceeds limit (%lu vs. %u), using max",
+ a0, ulongval, UINT_MAX);
+ }
+ (*opts)[i].value.u_uint = ulongval;
+ }
+ Info2("setting option \"%s\" to %u", ent->desc->defname,
+ (*opts)[i].value.u_uint);
+ break;
+
+#if HAVE_BASIC_SIZE_T==2
+ case TYPE_SIZE_T:
+#endif
+ case TYPE_USHORT:
+ if (!assign) {
+ (*opts)[i].value.u_ushort = 1;
+ } else {
+ char *rest;
+ ulongval = strtoul(token, &rest/*!*/, 0);
+ if (ulongval > USHRT_MAX) {
+ Error3("parseopts(%s): unsigned short value exceeds limit (%lu vs. %u), using max",
+ a0, ulongval, USHRT_MAX);
+ }
+ (*opts)[i].value.u_ushort = ulongval;
+ }
+ Info2("setting option \"%s\" to %u", ent->desc->defname,
+ (*opts)[i].value.u_ushort);
+ break;
+
+ case TYPE_OFF32:
+#if HAVE_STAT64 && defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T==5
+ case TYPE_OFF64:
+#endif
+ case TYPE_LONG:
+ if (!assign) {
+ (*opts)[i].value.u_long = 1;
+ } else {
+ char *rest;
+ slongval = strtol(token, &rest, 0);
+ (*opts)[i].value.u_long = slongval;
+ }
+ Info2("setting option \"%s\" to %lu", ent->desc->defname,
+ (*opts)[i].value.u_long);
+ break;
+
+#if HAVE_BASIC_SIZE_T==6
+ case TYPE_SIZE_T:
+#endif
+ case TYPE_ULONG:
+ if (!assign) {
+ (*opts)[i].value.u_ulong = 1;
+ } else {
+ char *rest;
+ ulongval = strtoul(token, &rest, 0);
+ (*opts)[i].value.u_ulong = ulongval;
+ }
+ Info2("setting option \"%s\" to %lu", ent->desc->defname,
+ (*opts)[i].value.u_ulong);
+ break;
+
+#if HAVE_TYPE_LONGLONG
+ case TYPE_LONGLONG:
+# if HAVE_STAT64 && defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T==7
+ case TYPE_OFF64:
+# endif
+ if (!assign) {
+ (*opts)[i].value.u_longlong = 1;
+ } else {
+ char *rest;
+# if HAVE_STRTOLL
+ slonglongval = strtoll(token, &rest, 0);
+# else
+ /* in this case, input value range is limited */
+ slonglongval = strtol(token, &rest, 0);
+# endif /* HAVE_STRTOLL */
+ (*opts)[i].value.u_longlong = slonglongval;
+ }
+ Info2("setting option \"%s\" to %Lu", ent->desc->defname,
+ (*opts)[i].value.u_longlong);
+ break;
+#endif /* HAVE_TYPE_LONGLONG */
+ case TYPE_UIDT:
+ if (!assign) {
+ Error1("option \"%s\": value required", a0);
+ continue;
+ }
+ if (isdigit((*token)&0xff)) {
+ char *rest;
+ (*opts)[i].value.u_uidt = strtoul(token, &rest/*!*/, 0);
+ } else {
+ struct passwd *pwd;
+ if ((pwd = getpwnam(token)) == NULL) {
+ Error1("getpwnam(\"%s\"): no such user", token);
+ continue;
+ }
+ (*opts)[i].value.u_uidt = getpwnam(token)->pw_uid;
+ }
+ Info2("setting option \"%s\" to %u", ent->desc->defname,
+ (*opts)[i].value.u_uidt);
+ break;
+ case TYPE_GIDT:
+ if (!assign) { Error1("option \"%s\": value required", a0);
+ continue; }
+ if (isdigit((token[0])&0xff)) {
+ char *rest;
+ (*opts)[i].value.u_gidt = strtoul(token, &rest/*!*/, 0);
+ } else {
+ struct group *grp;
+ grp = getgrnam(token);
+ if (grp == NULL) {
+ Error1("getgrnam(\"%s\"): no such group", token);
+ continue;
+ }
+ (*opts)[i].value.u_gidt = grp->gr_gid;
+ }
+ Info2("setting option \"%s\" to %u", ent->desc->defname,
+ (*opts)[i].value.u_gidt);
+ break;
+ case TYPE_MODET:
+ if (!assign) { Error1("option \"%s\": value required", a0);
+ continue;
+ }
+ {
+ char *rest;
+ (*opts)[i].value.u_modet = strtoul(token, &rest/*!*/, 8);
+ }
+ Info2("setting option \"%s\" to %u", ent->desc->defname,
+ (*opts)[i].value.u_modet);
+ break;
+ case TYPE_STRING:
+ if (!assign) {
+ Error1("option \"%s\": value required", a0);
+ continue;
+ }
+ if (((*opts)[i].value.u_string = strdup(token)) == NULL) {
+ Error("out of memory"); return -1;
+ }
+ Info2("setting option \"%s\" to \"%s\"", ent->desc->defname,
+ (*opts)[i].value.u_string);
+ break;
+ case TYPE_STRING_NULL:
+ if (!assign) {
+ (*opts)[i].value.u_string = NULL;
+ Info1("setting option \"%s\" to NULL", ent->desc->defname);
+ } else {
+ (*opts)[i].value.u_string = strdup(token);
+ Info2("setting option \"%s\" to \"%s\"", ent->desc->defname,
+ (*opts)[i].value.u_string);
+ }
+ break;
+#if LATER
+ case TYPE_INT3:
+
+ break;
+#endif
+ case TYPE_TIMEVAL:
+ if (!assign) {
+ Error1("option \"%s\": value required", a0);
+ continue;
+ } else {
+ double val;
+ val = strtod(token, NULL);
+ if (val == HUGE_VAL || val == -HUGE_VAL ||
+ val == 0.0 && errno == ERANGE) {
+ Error2("strtod(\"%s\", NULL): %s", token, strerror(errno));
+ val = 0.0;
+ }
+ (*opts)[i].value.u_timeval.tv_sec = val;
+ (*opts)[i].value.u_timeval.tv_usec =
+ (val-(*opts)[i].value.u_timeval.tv_sec) * 1000000;
+ }
+ break;
+#if HAVE_STRUCT_TIMESPEC
+ case TYPE_TIMESPEC:
+ if (!assign) {
+ Error1("option \"%s\": value required", a0);
+ continue;
+ } else {
+ double val;
+ val = strtod(token, NULL);
+ if (val == HUGE_VAL || val == -HUGE_VAL ||
+ val == 0.0 && errno == ERANGE) {
+ Error2("strtod(\"%s\", NULL): %s", token, strerror(errno));
+ val = 0.0;
+ }
+ (*opts)[i].value.u_timespec.tv_sec = val;
+ (*opts)[i].value.u_timespec.tv_nsec =
+ (val-(*opts)[i].value.u_timespec.tv_sec) * 1000000000.;
+ }
+ break;
+#endif /* HAVE_STRUCT_TIMESPEC */
+#if HAVE_STRUCT_LINGER
+ case TYPE_LINGER:
+ if (!assign) {
+ Error1("option \"%s\": value required", a0);
+ continue;
+ }
+ (*opts)[i].value.u_linger.l_onoff = 1;
+ {
+ char *rest;
+ (*opts)[i].value.u_linger.l_linger = strtoul(token, &rest/*!*/, 0);
+ }
+ Info3("setting option \"%s\" to {%d,%d}", ent->desc->defname,
+ (*opts)[i].value.u_linger.l_onoff,
+ (*opts)[i].value.u_linger.l_linger);
+ break;
+#endif /* HAVE_STRUCT_LINGER */
+#if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
+ case TYPE_IP_MREQN:
+ {
+ /* we do not resolve the addresses here because we do not yet know
+ if we are coping with a IPv4 or IPv6 socat address */
+ const char *ends[] = { ":", NULL };
+ const char *nests[] = { "[","]", NULL };
+ char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1;
+
+ /* parse first IP address, expect ':' */
+ tokp = token;
+ /*! result= */
+ nestlex((const char **)&tokp, &buffp, &bufspc,
+ ends, NULL, NULL, nests,
+ true, false, false);
+ if (*tokp != ':') {
+ Error1("syntax in option %s: missing ':'", token);
+ }
+ *buffp++ = '\0';
+ (*opts)[i].value.u_ip_mreq.multiaddr = strdup(buff); /*!!! NULL */
+
+ ++tokp;
+ /* parse second IP address, expect ':' or '\0'' */
+ buffp = buff;
+ /*! result= */
+ nestlex((const char **)&tokp, &buffp, &bufspc,
+ ends, NULL, NULL, nests,
+ true, false, false);
+ *buffp++ = '\0';
+ (*opts)[i].value.u_ip_mreq.param2 = strdup(buff); /*!!! NULL */
+
+#if HAVE_STRUCT_IP_MREQN
+ if (*tokp++ == ':') {
+ strncpy((*opts)[i].value.u_ip_mreq.ifindex, tokp, IF_NAMESIZE);
+ Info4("setting option \"%s\" to {\"%s\",\"%s\",\"%s\"}",
+ ent->desc->defname,
+ (*opts)[i].value.u_ip_mreq.multiaddr,
+ (*opts)[i].value.u_ip_mreq.param2,
+ (*opts)[i].value.u_ip_mreq.ifindex);
+ } else {
+ (*opts)[i].value.u_ip_mreq.ifindex[0] = '\0';
+ Info3("setting option \"%s\" to {\"%s\",\"%s\"}",
+ ent->desc->defname,
+ (*opts)[i].value.u_ip_mreq.multiaddr,
+ (*opts)[i].value.u_ip_mreq.param2);
+ }
+#else /* !HAVE_STRUCT_IP_MREQN */
+ Info3("setting option \"%s\" to {0x%08x,0x%08x}",
+ ent->desc->defname,
+ (*opts)[i].value.u_ip_mreq.multiaddr,
+ (*opts)[i].value.u_ip_mreq.param2);
+#endif /* !HAVE_STRUCT_IP_MREQN */
+ }
+ break;
+#endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */
+
+#if WITH_IP4
+ case TYPE_IP4NAME:
+ {
+ struct sockaddr_in sa; size_t salen = sizeof(sa);
+ const char *ends[] = { NULL };
+ const char *nests[] = { "[","]", NULL };
+ char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1;
+
+ tokp = token;
+ nestlex((const char **)&tokp, &buffp, &bufspc,
+ ends, NULL, NULL, nests,
+ true, false, false);
+ if (*tokp != '\0') {
+ Error1("trailing data in option \"%s\"", token);
+ }
+ *buffp = '\0';
+ if (xiogetaddrinfo(buff, NULL, AF_INET, SOCK_DGRAM, IPPROTO_IP,
+ (union sockaddr_union *)&sa, &salen,
+ 0, 0/*!!!*/) != STAT_OK) {
+ opt->desc = ODESC_ERROR; continue;
+ }
+ opt->value.u_ip4addr = sa.sin_addr.s_addr;
+ }
+ break;
+#endif /* defined(WITH_IP4) */
+
+ default:
+ Error2("parseopts(): internal error on option \"%s\": unimplemented type %d",
+ ent->desc->defname, ent->desc->type);
+ continue;
+ }
+
+ ++i;
+ if ((i % 8) == 0) {
+ *opts = Realloc(*opts, (i+8) * sizeof(struct opt));
+ if (*opts == NULL) {
+ return -1;
+ }
+ }
+ }
+
+ /*(*opts)[i+1].desc = ODESC_END;*/
+ (*opts)[i].desc = ODESC_END;
+ return 0;
+}
+
+/* copy the already parsed options for repeated application, but only those
+ matching groups ANY and <groups> */
+struct opt *copyopts(const struct opt *opts, unsigned int groups) {
+ struct opt *new;
+ int i, j, n;
+
+ if (!opts) return NULL;
+
+ /* just count the options in the array */
+ i = 0; while (opts[i].desc != ODESC_END) {
+ ++i;
+ }
+ n = i+1;
+
+ new = Malloc(n * sizeof(struct opt));
+ if (new == NULL) {
+ return NULL;
+ }
+
+ i = 0, j = 0;
+ while (i < n-1) {
+ if (opts[i].desc == ODESC_DONE) {
+ new[j].desc = ODESC_DONE;
+ } else if ((opts[i].desc->group & (GROUP_ANY&~GROUP_PROCESS)) ||
+ (opts[i].desc->group & groups)) {
+ new[j++] = opts[i];
+ }
+ ++i;
+ }
+ new[j].desc = ODESC_END;
+ return new;
+}
+
+/* move options to a new options list
+ move only those matching <groups> */
+struct opt *moveopts(struct opt *opts, unsigned int groups) {
+ struct opt *new;
+ int i, j, n;
+
+ if (!opts) return NULL;
+
+ /* just count the options in the array */
+ i = 0; j = 0; while (opts[i].desc != ODESC_END) {
+ if (opts[i].desc != ODESC_DONE &&
+ opts[i].desc != ODESC_ERROR)
+ ++j;
+ ++i;
+ }
+ n = i;
+
+ new = Malloc((j+1) * sizeof(struct opt));
+ if (new == NULL) {
+ return NULL;
+ }
+
+ i = 0, j = 0;
+ while (i < n) {
+ if (opts[i].desc == ODESC_DONE ||
+ opts[i].desc == ODESC_ERROR) {
+ ++i; continue;
+ } else if (opts[i].desc->group & groups) {
+ new[j++] = opts[i];
+ opts[i].desc = ODESC_DONE;
+ }
+ ++i;
+ }
+ new[j].desc = ODESC_END;
+ return new;
+}
+
+/* return the number of yet unconsumed options; -1 on error */
+int leftopts(const struct opt *opts) {
+ const struct opt *opt = opts;
+ int num = 0;
+
+ if (!opts) return 0;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE) {
+ ++num;
+ }
+ ++opt;
+ }
+ return num;
+}
+
+/* show as warning which options are still unused */
+int showleft(const struct opt *opts) {
+ const struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE) {
+ Warn1("showleft(): option \"%s\" not inquired", opt->desc->defname);
+ }
+ ++opt;
+ }
+ return 0;
+}
+
+
+/* determines the address group from mode_t */
+/* does not set GROUP_FD; cannot determine GROUP_TERMIOS ! */
+int _groupbits(mode_t mode) {
+ unsigned int result = 0;
+
+ switch ((mode&S_IFMT)>>12) {
+ case (S_IFIFO>>12): /* 1, FIFO */
+ result = GROUP_FIFO; break;
+ case (S_IFCHR>>12): /* 2, character device */
+ result = GROUP_CHR|GROUP_TERMIOS; break;
+ case (S_IFDIR>>12): /* 4, directory !!! not supported */
+ result = GROUP_NONE; break;
+ case (S_IFBLK>>12): /* 6, block device */
+ result = GROUP_BLK; break;
+ case (S_IFREG>>12): /* 8, regular file */
+ result = GROUP_REG; break;
+ case (S_IFLNK>>12): /* 10, symbolic link !!! not supported */
+ result = GROUP_NONE; break;
+#ifdef S_IFSOCK
+ case (S_IFSOCK>>12): /* 12, socket */
+ result = GROUP_SOCKET|GROUP_SOCK_UNIX; break;
+#else
+ default: /* some systems (pure POSIX.1) do not know S_IFSOCK */
+ result = GROUP_SOCKET|GROUP_SOCK_UNIX; break;
+#endif
+ }
+ Debug2("_groupbits(%d) -> %d", mode, result);
+ return result;
+}
+
+/* does not set GROUP_FD */
+int groupbits(int fd) {
+#if HAVE_STAT64
+ struct stat64 buf;
+#else
+ struct stat buf;
+#endif /* !HAVE_STAT64 */
+ int result;
+
+ if (
+#if HAVE_STAT64
+ Fstat64(fd, &buf) < 0
+#else
+ Fstat(fd, &buf) < 0
+#endif /* !HAVE_STAT64 */
+ ) {
+ Error4("groupbits(%d): fstat(%d, %p): %s",
+ fd, fd, &buf, strerror(errno));
+ return -1;
+ }
+ result = _groupbits(buf.st_mode&S_IFMT);
+ if (result == GROUP_CHR) {
+ if (Isatty(fd) > 0) {
+ result |= GROUP_TERMIOS;
+ }
+ }
+ return result;
+}
+
+#if 0 /* currently not used */
+int retropt(struct opt *opts, int optcode, union integral *result) {
+ struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
+ *result = opt->value;
+ opt->desc = ODESC_DONE;
+ return 0;
+ }
+ ++opt;
+ }
+ return -1;
+}
+#endif
+
+static struct opt *xio_findopt(struct opt *opts, int optcode) {
+ struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
+ return opt;
+ }
+ ++opt;
+ }
+ return NULL;
+}
+
+int retropt_timespec(struct opt *opts, int optcode, struct timespec *result) {
+ struct opt *opt;
+
+ if (!(opt = xio_findopt(opts, optcode))) {
+ return -1;
+ }
+ *result = opt->value.u_timespec;
+ opt->desc = ODESC_DONE;
+ return 0;
+}
+
+
+/* Looks for the first option of type <optcode>. If the option is found,
+ this function stores its bool value in *result, "consumes" the
+ option, and returns 0.
+ If the option is not found, *result is not modified, and -1 is returned. */
+int retropt_bool(struct opt *opts, int optcode, bool *result) {
+ struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
+ *result = opt->value.u_bool;
+ opt->desc = ODESC_DONE;
+ return 0;
+ }
+ ++opt;
+ }
+ return -1;
+}
+
+#if 0 /* currently not used */
+/* Looks for the first option of type <optcode>. If the option is found,
+ this function stores its short value in *result, "consumes" the
+ option, and returns 0.
+ If the option is not found, *result is not modified, and -1 is returned. */
+int retropt_short(struct opt *opts, int optcode, short *result) {
+ struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
+ *result = opt->value.u_short;
+ opt->desc = ODESC_DONE;
+ return 0;
+ }
+ ++opt;
+ }
+ return -1;
+}
+#endif
+
+/* Looks for the first option of type <optcode>. If the option is found,
+ this function stores its unsigned short value in *result, "consumes" the
+ option, and returns 0.
+ If the option is not found, *result is not modified, and -1 is returned. */
+int retropt_ushort(struct opt *opts, int optcode, unsigned short *result) {
+ struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
+ *result = opt->value.u_ushort;
+ opt->desc = ODESC_DONE;
+ return 0;
+ }
+ ++opt;
+ }
+ return -1;
+}
+
+/* Looks for the first option of type <optcode>. If the option is found,
+ this function stores its int value in *result, "consumes" the
+ option, and returns 0.
+ If the option is not found, *result is not modified, and -1 is returned. */
+int retropt_int(struct opt *opts, int optcode, int *result) {
+ struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
+ *result = opt->value.u_int;
+ opt->desc = ODESC_DONE;
+ return 0;
+ }
+ ++opt;
+ }
+ return -1;
+}
+
+/* Looks for the first option of type <optcode>. If the option is found,
+ this function stores its unsigned int value in *result, "consumes" the
+ option, and returns 0.
+ If the option is not found, *result is not modified, and -1 is returned. */
+int retropt_uint(struct opt *opts, int optcode, unsigned int *result) {
+ struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
+ *result = opt->value.u_uint;
+ opt->desc = ODESC_DONE;
+ return 0;
+ }
+ ++opt;
+ }
+ return -1;
+}
+
+/* Looks for the first option of type <optcode>. If the option is found,
+ this function stores its long value in *result, "consumes" the option,
+ and returns 0.
+ If the option is not found, *result is not modified, and -1 is returned. */
+int retropt_long(struct opt *opts, int optcode, long *result) {
+ struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
+ *result = opt->value.u_long;
+ opt->desc = ODESC_DONE;
+ return 0;
+ }
+ ++opt;
+ }
+ return -1;
+}
+
+/* Looks for the first option of type <optcode>. If the option is found,
+ this function stores its unsigned long value in *result, "consumes" the
+ option, and returns 0.
+ If the option is not found, *result is not modified, and -1 is returned. */
+int retropt_ulong(struct opt *opts, int optcode, unsigned long *result) {
+ struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
+ *result = opt->value.u_ulong;
+ opt->desc = ODESC_DONE;
+ return 0;
+ }
+ ++opt;
+ }
+ return -1;
+}
+
+#if 0 /* currently not used */
+/* get the value of a FLAG typed option, and apply it to the appropriate
+ bit position. Mark the option as consumed (done). return 0 if options was found and successfully applied,
+ or -1 if option was not in opts */
+int retropt_flag(struct opt *opts, int optcode, flags_t *result) {
+ struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
+ if (opt->value.u_bool) {
+ *result |= opt->desc->major;
+ } else {
+ *result &= ~opt->desc->major;
+ }
+ opt->desc = ODESC_DONE;
+ return 0;
+ }
+ ++opt;
+ }
+ return -1;
+}
+#endif
+
+/* Looks for the first option of type <optcode>. If the option is found,
+ this function stores its character pointer value in *result, "consumes" the
+ option, and returns 0. Note that, for options of type STRING_NULL, the
+ character pointer might degenerate to NULL.
+ The resulting string is malloc'ed and should be freed after use.
+ If the option is not found, *result is not modified, and -1 is returned.
+ */
+int retropt_string(struct opt *opts, int optcode, char **result) {
+ struct opt *opt = opts;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
+ if (opt->value.u_string == NULL) {
+ *result = NULL;
+ } else if ((*result = strdup(opt->value.u_string)) == NULL) {
+ Error1("strdup("F_Zu"): out of memory",
+ strlen(opt->value.u_string));
+ return -1;
+ }
+ opt->desc = ODESC_DONE;
+ return 0;
+ }
+ ++opt;
+ }
+ return -1;
+}
+
+
+#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) */
+int retropt_bind(struct opt *opts,
+ int af,
+ int socktype,
+ int ipproto,
+ struct sockaddr *sa,
+ socklen_t *salen,
+ int feats, /* TCP etc: 1..address allowed,
+ 3..address and port allowed */
+ unsigned long res_opts0, unsigned long res_opts1) {
+ const char portsep[] = ":";
+ const char *ends[] = { portsep, NULL };
+ const char *nests[] = { "[", "]", NULL };
+ bool addrallowed, portallowed;
+ char *bindname, *bindp;
+ char hostname[512], *hostp = hostname, *portp = NULL;
+ size_t hostlen = sizeof(hostname)-1;
+ int result;
+
+ 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, 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) {
+#if WITH_IP4 || WITH_IP6
+#if WITH_IP4
+ case AF_INET:
+#endif
+#if WITH_IP6
+ case AF_INET6:
+#endif /*WITH_IP6 */
+ if ((result =
+ xiogetaddrinfo(hostname[0]!='\0'?hostname:NULL, portp,
+ af, socktype, ipproto,
+ (union sockaddr_union *)sa, salen,
+ res_opts0, res_opts1))
+ != STAT_OK) {
+ Error("error resolving bind option");
+ return STAT_NORETRY;
+ }
+ break;
+#endif /* WITH_IP4 || WITH_IP6 */
+
+#if WITH_UNIX
+ case AF_UNIX:
+ {
+ bool tight = false;
+ struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
+ *salen = xiosetunix(s_un, bindname, false, tight);
+ }
+ break;
+#endif /* WITH_UNIX */
+
+ default:
+ Error1("bind: unknown address family %d", af);
+ return STAT_NORETRY;
+ }
+ return STAT_OK;
+}
+#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) {
+ struct opt *opt;
+
+ opt = opts; while (opt && opt->desc != ODESC_END) {
+ if (opt->desc == ODESC_DONE ||
+ (phase != PH_ALL && opt->desc->phase != phase)) {
+ ++opt; continue; }
+
+ if (opt->desc->func == OFUNC_SEEK32) {
+ if (Lseek(fd, opt->value.u_long, opt->desc->major) < 0) {
+ Error4("lseek(%d, %ld, %d): %s",
+ fd, opt->value.u_long, opt->desc->major, strerror(errno));
+ }
+#if HAVE_LSEEK64
+ } else if (opt->desc->func == OFUNC_SEEK64) {
+
+ /*! this depends on off64_t atomic type */
+ if (Lseek64(fd, opt->value.u_off64, opt->desc->major) < 0) {
+ Error4("lseek64(%d, %Ld, %d): %s",
+ fd, opt->value.u_off64, opt->desc->major, strerror(errno));
+ }
+#endif /* HAVE_LSEEK64 */
+
+ } else if (opt->desc->func == OFUNC_FCNTL) {
+ int flag;
+
+ /* retrieve existing flag setttings */
+ if ((flag = Fcntl(fd, opt->desc->major-1)) < 0) {
+ Error3("fcntl(%d, %d): %s",
+ fd, opt->desc->major, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ } else {
+ if (opt->value.u_bool) {
+ flag |= opt->desc->minor;
+ } else {
+ flag &= ~opt->desc->minor;
+ }
+ if (Fcntl_l(fd, opt->desc->major, flag) < 0) {
+ Error4("fcntl(%d, %d, %d): %s",
+ fd, opt->desc->major, flag, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ }
+
+ } else if (opt->desc->func == OFUNC_IOCTL) {
+ if (Ioctl(fd, opt->desc->major, (void *)&opt->value) < 0) {
+ Error4("ioctl(%d, 0x%x, %p): %s",
+ fd, opt->desc->major, (void *)&opt->value, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+
+ } else if (opt->desc->func == OFUNC_IOCTL_MASK_LONG) {
+ long val;
+ int getreq = opt->desc->major;
+ int setreq = opt->desc->minor;
+ long mask = opt->desc->arg3;
+
+ if (Ioctl(fd, getreq, (void *)&val) < 0) {
+ Error4("ioctl(%d, 0x%x, %p): %s",
+ fd, opt->desc->major, (void *)&val, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ val &= ~mask;
+ if (opt->value.u_bool) val |= mask;
+ if (Ioctl(fd, setreq, (void *)&val) < 0) {
+ Error4("ioctl(%d, 0x%x, %p): %s",
+ fd, opt->desc->major, (void *)&val, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+
+#if WITH_SOCKET
+ } else if (opt->desc->func == OFUNC_SOCKOPT) {
+ if (0) {
+ ;
+#if 0 && HAVE_STRUCT_LINGER
+ } else if (opt->desc->optcode == OPT_SO_LINGER) {
+ struct linger lingstru;
+ lingstru.l_onoff = (opt->value.u_int>=0 ? 1 : 0);
+ lingstru.l_linger = opt->value.u_int;
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor, &lingstru,
+ sizeof(lingstru)) < 0) {
+ Error6("setsockopt(%d, %d, %d, {%d,%d}, "F_Zu,
+ fd, opt->desc->major, opt->desc->minor, lingstru.l_onoff,
+ lingstru.l_linger, sizeof(lingstru));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+#endif /* HAVE_STRUCT_LINGER */
+ } else {
+ switch (opt->desc->type) {
+ case TYPE_BIN:
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
+ opt->value.u_bin.b_data, opt->value.u_bin.b_len)
+ < 0) {
+ Error6("setsockopt(%d, %d, %d, %p, %d): %s",
+ fd, opt->desc->major, opt->desc->minor,
+ opt->value.u_bin.b_data, opt->value.u_bin.b_len,
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case TYPE_BOOL:
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
+ &opt->value.u_bool, sizeof(opt->value.u_bool))
+ < 0) {
+ Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", fd,
+ opt->desc->major, opt->desc->minor,
+ opt->value.u_bool, sizeof(opt->value.u_bool),
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case TYPE_BYTE:
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
+ &opt->value.u_byte, sizeof(uint8_t)) < 0) {
+ Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s",
+ fd, opt->desc->major, opt->desc->minor,
+ opt->value.u_byte, sizeof(uint8_t), strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case TYPE_INT:
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
+ &opt->value.u_int, sizeof(int)) < 0) {
+ Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s",
+ fd, opt->desc->major, opt->desc->minor,
+ opt->value.u_int, sizeof(int), strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case TYPE_LONG:
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
+ &opt->value.u_long, sizeof(long)) < 0) {
+ Error6("setsockopt(%d, %d, %d, {%ld}, "F_Zu"): %s",
+ fd, opt->desc->major, opt->desc->minor,
+ opt->value.u_long, sizeof(long), strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case TYPE_STRING:
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
+ opt->value.u_string,
+ strlen(opt->value.u_string)+1) < 0) {
+ Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s",
+ fd, opt->desc->major, opt->desc->minor,
+ opt->value.u_string, strlen(opt->value.u_string)+1,
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case TYPE_UINT:
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
+ &opt->value.u_uint, sizeof(unsigned int)) < 0) {
+ Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s",
+ fd, opt->desc->major, opt->desc->minor,
+ opt->value.u_uint, sizeof(unsigned int),
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case TYPE_TIMEVAL:
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
+ &opt->value.u_timeval, sizeof(struct timeval)) < 0) {
+ Error7("setsockopt(%d, %d, %d, {%ld,%ld}, "F_Zu"): %s",
+ fd, opt->desc->major, opt->desc->minor,
+ opt->value.u_timeval.tv_sec, opt->value.u_timeval.tv_usec,
+ sizeof(struct timeval), strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+#if HAVE_STRUCT_LINGER
+ case TYPE_LINGER:
+ {
+ struct linger lingstru;
+ lingstru.l_onoff = (opt->value.u_linger.l_onoff>=0 ? 1 : 0);
+ lingstru.l_linger = opt->value.u_linger.l_linger;
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
+ &lingstru, sizeof(lingstru)) < 0) {
+ Error6("setsockopt(%d, %d, %d, {%d,%d}): %s",
+ fd, opt->desc->major, opt->desc->minor,
+ lingstru.l_onoff, lingstru.l_linger,
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ }
+ break;
+#endif /* HAVE_STRUCT_LINGER */
+#if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
+ case TYPE_IP_MREQN:
+ /* handled in applyopts_single */
+ ++opt; continue;
+#endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */
+
+ /*! still many types missing; implement on demand */
+#if WITH_IP4
+ case TYPE_IP4NAME:
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
+ &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),
+ strerror(errno));
+ }
+ break;
+#endif /* defined(WITH_IP4) */
+ default:
+#if !NDEBUG
+ Error1("applyopts(): type %d not implemented",
+ opt->desc->type);
+#else
+ Warn1("applyopts(): type %d not implemented",
+ opt->desc->type);
+#endif
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ }
+
+ } else if (opt->desc->func == OFUNC_SOCKOPT_APPEND) {
+ switch (opt->desc->type) {
+ uint8_t data[256];
+ socklen_t oldlen, newlen;
+ case TYPE_BIN:
+ oldlen = sizeof(data);
+ if (Getsockopt(fd, opt->desc->major, opt->desc->minor,
+ data, &oldlen)
+ < 0) {
+ Error6("getsockopt(%d, %d, %d, %p, {"F_Zu"}): %s",
+ fd, opt->desc->major, opt->desc->minor, data, oldlen,
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ memcpy(&data[oldlen], opt->value.u_bin.b_data,
+ MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen));
+ newlen = oldlen + MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen);
+ if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
+ data, newlen)
+ < 0) {
+ Error6("setsockopt(%d, %d, %d, %p, %d): %s",
+ fd, opt->desc->major, opt->desc->minor, data, newlen,
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ default:
+ Error2("internal: option \"%s\": unimplemented type %d",
+ opt->desc->defname, opt->desc->type);
+ break;
+ }
+#endif /* WITH_SOCKET */
+
+#if HAVE_FLOCK
+ } else if (opt->desc->func == OFUNC_FLOCK) {
+ if (Flock(fd, opt->desc->major) < 0) {
+ Error3("flock(%d, %d): %s",
+ fd, opt->desc->major, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+#endif /* defined(HAVE_FLOCK) */
+
+ } else if (opt->desc->func == OFUNC_SPEC ||
+ opt->desc->func == OFUNC_FLAG) {
+ switch (opt->desc->optcode) {
+ case OPT_USER:
+ case OPT_USER_LATE:
+ if (Fchown(fd, opt->value.u_uidt, -1) < 0) {
+ Error3("fchown(%d, "F_uid", -1): %s",
+ fd, opt->value.u_uidt, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case OPT_GROUP:
+ case OPT_GROUP_LATE:
+ if (Fchown(fd, -1, opt->value.u_gidt) < 0) {
+ Error3("fchown(%d, -1, "F_gid"): %s",
+ fd, opt->value.u_gidt, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case OPT_PERM:
+ case OPT_PERM_LATE:
+ if (Fchmod(fd, opt->value.u_modet) < 0) {
+ Error3("fchmod(%d, %u): %s",
+ fd, opt->value.u_modet, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case OPT_FTRUNCATE32:
+ if (Ftruncate(fd, opt->value.u_long) < 0) {
+ Error3("ftruncate(%d, %ld): %s",
+ fd, opt->value.u_long, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+#if HAVE_FTRUNCATE64
+ case OPT_FTRUNCATE64:
+ if (Ftruncate64(fd, opt->value.u_long) < 0) {
+ Error3("ftruncate64(%d, %ld): %s",
+ fd, opt->value.u_long, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+#endif /* HAVE_FTRUNCATE64 */
+ break;
+ case OPT_F_SETLK_RD:
+ case OPT_F_SETLK_WR:
+ case OPT_F_SETLKW_RD:
+ case OPT_F_SETLKW_WR:
+ {
+ struct flock l; /* Linux: <asm/fcntl.h> */
+ l.l_type = opt->desc->minor;
+ l.l_whence = SEEK_SET;
+ l.l_start = 0;
+ l.l_len = LONG_MAX;
+ l.l_pid = 0; /* hope this uses our current process */
+ if (Fcntl_lock(fd, opt->desc->major, &l) < 0) {
+ Error3("fcntl(%d, %d, {type=F_WRLCK,whence=SEEK_SET,start=0,len=LONG_MAX,pid=0}): %s", fd, opt->desc->major, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ }
+ break;
+ case OPT_SETUID_EARLY:
+ case OPT_SETUID:
+ if (Setuid(opt->value.u_uidt) < 0) {
+ Error2("setuid("F_uid"): %s", opt->value.u_uidt,
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case OPT_SETGID_EARLY:
+ case OPT_SETGID:
+ if (Setgid(opt->value.u_gidt) < 0) {
+ Error2("setgid("F_gid"): %s", opt->value.u_gidt,
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ break;
+ case OPT_SUBSTUSER:
+ {
+ struct passwd *pwd;
+ if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) {
+ Error1("getpwuid("F_uid"): no such user",
+ opt->value.u_uidt);
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ if (Initgroups(pwd->pw_name, pwd->pw_gid) < 0) {
+ Error3("initgroups(%s, "F_gid"): %s",
+ pwd->pw_name, pwd->pw_gid, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ if (Setgid(pwd->pw_gid) < 0) {
+ Error2("setgid("F_gid"): %s", pwd->pw_gid,
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ if (Setuid(opt->value.u_uidt) < 0) {
+ Error2("setuid("F_uid"): %s", opt->value.u_uidt,
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+#if 1
+ if (setenv("USER", pwd->pw_name, 1) < 0)
+ Error1("setenv(\"USER\", \"%s\", 1): insufficient space",
+ pwd->pw_name);
+ if (setenv("LOGNAME", pwd->pw_name, 1) < 0)
+ Error1("setenv(\"LOGNAME\", \"%s\", 1): insufficient space",
+ pwd->pw_name);
+ if (setenv("HOME", pwd->pw_dir, 1) < 0)
+ Error1("setenv(\"HOME\", \"%s\", 1): insufficient space",
+ pwd->pw_dir);
+ if (setenv("SHELL", pwd->pw_shell, 1) < 0)
+ Error1("setenv(\"SHELL\", \"%s\", 1): insufficient space",
+ pwd->pw_shell);
+#endif
+ }
+ break;
+ case OPT_SUBSTUSER_DELAYED:
+ {
+ struct passwd *pwd;
+
+ if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) {
+ Error1("getpwuid("F_uid"): no such user",
+ opt->value.u_uidt);
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ delayeduser_uid = opt->value.u_uidt;
+ delayeduser_gid = pwd->pw_gid;
+ if ((delayeduser_name = strdup(pwd->pw_name)) == NULL) {
+ Error1("strdup("F_Zu"): out of memory",
+ strlen(pwd->pw_name)+1);
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ if ((delayeduser_dir = strdup(pwd->pw_dir)) == NULL) {
+ Error1("strdup("F_Zu"): out of memory",
+ strlen(pwd->pw_dir)+1);
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ if ((delayeduser_shell = strdup(pwd->pw_shell)) == NULL) {
+ Error1("strdup("F_Zu"): out of memory",
+ strlen(pwd->pw_shell)+1);
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ /* function to get all supplementary groups of user */
+ delayeduser_ngids = sizeof(delayeduser_gids)/sizeof(gid_t);
+ getusergroups(delayeduser_name, delayeduser_gids,
+ &delayeduser_ngids);
+ delayeduser = true;
+ }
+ break;
+ case OPT_CHROOT_EARLY:
+ case OPT_CHROOT:
+ if (Chroot(opt->value.u_string) < 0) {
+ Error2("chroot(\"%s\"): %s", opt->value.u_string,
+ strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ if (Chdir("/") < 0) {
+ Error1("chdir(\"/\"): %s", strerror(errno));
+ }
+ break;
+ case OPT_SETSID:
+ if (Setsid() < 0) {
+ Warn1("setsid(): %s", strerror(errno));
+ if (Setpgid(getpid(), getppid()) < 0) {
+ Warn3("setpgid(%d, %d): %s",
+ getpid(), getppid(), strerror(errno));
+ } else {
+ if (Setsid() < 0) {
+ Error1("setsid(): %s", strerror(errno));
+ }
+ }
+ }
+ break;
+ case OPT_SETPGID:
+ if (Setpgid(0, opt->value.u_int) < 0) {
+ Warn2("setpgid(0, "F_pid"): %s",
+ opt->value.u_int, strerror(errno));
+ }
+ break;
+ case OPT_TIOCSCTTY:
+ {
+ int mytty;
+ /* this code idea taken from ssh/pty.c: make pty controlling term. */
+ if ((mytty = Open("/dev/tty", O_NOCTTY, 0640)) < 0) {
+ Warn1("open(\"/dev/tty\", O_NOCTTY, 0640): %s", strerror(errno));
+ } else {
+ /*0 Info1("open(\"/dev/tty\", O_NOCTTY, 0640) -> %d", mytty);*/
+#ifdef TIOCNOTTY
+ if (Ioctl(mytty, TIOCNOTTY, NULL) < 0) {
+ Warn2("ioctl(%d, TIOCNOTTY, NULL): %s",
+ mytty, strerror(errno));
+ }
+#endif
+ if (Close(mytty) < 0) {
+ Info2("close(%d): %s",
+ mytty, strerror(errno));
+ }
+ }
+#ifdef TIOCSCTTY
+ if (Ioctl(fd, TIOCSCTTY, NULL) < 0) {
+ Warn2("ioctl(%d, TIOCSCTTY, NULL): %s", fd, strerror(errno));
+ }
+#endif
+ if (Tcsetpgrp(0, getpid()) < 0) {
+ Warn2("tcsetpgrp("F_pid"): %s", getpid(), strerror(errno));
+ }
+ }
+ break;
+ default: Error1("applyopts(): option \"%s\" not implemented",
+ opt->desc->defname);
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+
+#if WITH_TERMIOS
+ } else if (opt->desc->func == OFUNC_TERMIOS_FLAG) {
+#if 0
+ union {
+ struct termios termarg;
+ tcflag_t flags[4];
+ } tdata;
+ if (Tcgetattr(fd, &tdata.termarg) < 0) {
+ Error3("tcgetattr(%d, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ if (opt->value.u_bool) {
+ tdata.flags[opt->desc->major] |= opt->desc->minor;
+ } else {
+ tdata.flags[opt->desc->major] &= ~opt->desc->minor;
+ }
+ if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
+ Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+#else
+ if (xiotermiosflag_applyopt(fd, opt) < 0) {
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+#endif
+
+ } else if (opt->desc->func == OFUNC_TERMIOS_VALUE) {
+ union {
+ struct termios termarg;
+ tcflag_t flags[4];
+ } tdata;
+ if (((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) !=
+ (opt->value.u_uint << opt->desc->arg3)) {
+ Error2("option %s: invalid value %u",
+ opt->desc->defname, opt->value.u_uint);
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ if (Tcgetattr(fd, &tdata.termarg) < 0) {
+ Error3("tcgetattr(%d, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+
+ tdata.flags[opt->desc->major] &= ~opt->desc->minor;
+ tdata.flags[opt->desc->major] |=
+ ((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor);
+ if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
+ Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+
+ } else if (opt->desc->func == OFUNC_TERMIOS_PATTERN) {
+ union {
+ struct termios termarg;
+ tcflag_t flags[4];
+ } tdata;
+ if (Tcgetattr(fd, &tdata.termarg) < 0) {
+ Error3("tcgetattr(%d, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ tdata.flags[opt->desc->major] &= ~opt->desc->arg3;
+ tdata.flags[opt->desc->major] |= opt->desc->minor;
+ if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
+ Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ opt->desc = ODESC_ERROR;++opt; continue;
+ }
+
+ } else if (opt->desc->func == OFUNC_TERMIOS_CHAR) {
+ struct termios termarg;
+ if (Tcgetattr(fd, &termarg) < 0) {
+ Error3("tcgetattr(%d, %p): %s",
+ fd, &termarg, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ termarg.c_cc[opt->desc->major] = opt->value.u_byte;
+ if (Tcsetattr(fd, TCSADRAIN, &termarg) < 0) {
+ Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
+ fd, &termarg, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+
+#ifdef HAVE_TERMIOS_ISPEED
+ } else if (opt->desc->func == OFUNC_TERMIOS_SPEED) {
+ union {
+ struct termios termarg;
+ speed_t speeds[sizeof(struct termios)/sizeof(speed_t)];
+ } tdata;
+ if (Tcgetattr(fd, &tdata.termarg) < 0) {
+ Error3("tcgetattr(%d, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ tdata.speeds[opt->desc->major] = opt->value.u_uint;
+ if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
+ Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
+ fd, &tdata.termarg, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+#endif /* HAVE_TERMIOS_ISPEED */
+
+ } else if (opt->desc->func == OFUNC_TERMIOS_SPEC) {
+ struct termios termarg;
+ if (Tcgetattr(fd, &termarg) < 0) {
+ Error3("tcgetattr(%d, %p): %s",
+ fd, &termarg, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+ switch (opt->desc->optcode) {
+ case OPT_RAW:
+ termarg.c_iflag &=
+ ~(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF
+#ifdef IUCLC
+ |IUCLC
+#endif
+ |IXANY|IMAXBEL);
+ termarg.c_iflag |= (0);
+ termarg.c_oflag &= ~(OPOST);
+ termarg.c_oflag |= (0);
+ termarg.c_cflag &= ~(0);
+ termarg.c_cflag |= (0);
+ termarg.c_lflag &= ~(ISIG|ICANON
+#ifdef XCASE
+ |XCASE
+#endif
+ );
+ termarg.c_lflag |= (0);
+ termarg.c_cc[VMIN] = 1;
+ termarg.c_cc[VTIME] = 0;
+ break;
+ case OPT_SANE:
+ /* cread -ignbrk brkint -inlcr -igncr icrnl
+ -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl
+ onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0
+ vt0 ff0 isig icanon iexten echo echoe echok -echonl
+ -noflsh -xcase -tostop -echoprt echoctl echoke, and
+ also sets all special characters to their default
+ values.
+*/
+ termarg.c_iflag &= ~(IGNBRK|INLCR|IGNCR|IXOFF
+#ifdef IUCLC
+ |IUCLC
+#endif
+ |IXANY);
+ termarg.c_iflag |= (BRKINT|ICRNL|IMAXBEL);
+ termarg.c_oflag &= ~(0 /* for canonical reasons */
+#ifdef OLCUC
+ |OLCUC
+#endif
+#ifdef OCRNL
+ |OCRNL
+#endif
+#ifdef ONOCR
+ |ONOCR
+#endif
+#ifdef ONLRET
+ |ONLRET
+#endif
+#ifdef OFILL
+ |OFILL
+#endif
+#ifdef OFDEL
+ |OFDEL
+#endif
+#ifdef NLDLY
+ |NLDLY
+#endif
+#ifdef CRDLY
+ |CRDLY
+#endif
+#ifdef TABDLY
+ |TABDLY
+#endif
+#ifdef BSDLY
+ |BSDLY
+#endif
+#ifdef VTDLY
+ |VTDLY
+#endif
+#ifdef FFDLY
+ |FFDLY
+#endif
+ );
+ termarg.c_oflag |= (OPOST|ONLCR
+#ifdef NL0
+ |NL0
+#endif
+#ifdef CR0
+ |CR0
+#endif
+#ifdef TAB0
+ |TAB0
+#endif
+#ifdef BS0
+ |BS0
+#endif
+#ifdef VT0
+ |VT0
+#endif
+#ifdef FF0
+ |FF0
+#endif
+ );
+ termarg.c_cflag &= ~(0);
+ termarg.c_cflag |= (CREAD);
+ termarg.c_lflag &= ~(ECHONL|NOFLSH
+#ifdef XCASE
+ |XCASE
+#endif
+ |TOSTOP
+#ifdef ECHOPRT
+ |ECHOPRT
+#endif
+ );
+ termarg.c_lflag |= (ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE);
+ /*! "sets characters to their default values... - which? */
+ break;
+ default:
+ Error("TERMIOS option not handled - internal error?");
+ }
+ if (Tcsetattr(fd, TCSADRAIN, &termarg) < 0) {
+ Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
+ fd, &termarg, strerror(errno));
+ opt->desc = ODESC_ERROR; ++opt; continue;
+ }
+
+#endif /* WITH_TERMIOS */
+
+ } else {
+ /*Error1("applyopts(): function %d not implemented",
+ opt->desc->func);*/
+ if (opt->desc->func != OFUNC_EXT && opt->desc->func != OFUNC_SIGNAL) {
+ Error1("applyopts(): option \"%s\" does not apply",
+ opt->desc->defname);
+ opt->desc = ODESC_ERROR;
+ ++opt;
+ continue;
+ }
+ ++opt;
+ continue;
+ }
+ opt->desc = ODESC_DONE;
+ ++opt;
+ }
+ return 0;
+}
+
+/* applies to fd all options belonging to phases */
+/* 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 applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to) {
+ unsigned int i;
+ int stat;
+
+ for (i = from; i <= to; ++i) {
+ if ((stat = applyopts(fd, opts, i)) < 0)
+ return stat;
+ }
+ return 0;
+}
+
+/* apply and consume all options of type FLAG and group.
+ Return 0 if everything went right, or -1 if an error occurred. */
+int applyopts_flags(struct opt *opts, int group, flags_t *result) {
+ struct opt *opt = opts;
+
+ if (!opts) return 0;
+
+ while (opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE &&
+ (opt->desc->group & group)) {
+ if (opt->desc->func == OFUNC_FLAG) {
+ if (opt->value.u_bool) {
+ *result |= opt->desc->major;
+ } else {
+ *result &= ~opt->desc->major;
+ }
+ opt->desc = ODESC_DONE;
+ } else if (opt->desc->func == OFUNC_FLAG_PATTERN) {
+ *result &= ~opt->desc->minor;
+ *result |= opt->desc->major;
+ opt->desc = ODESC_DONE;
+ }
+ }
+ ++opt;
+ }
+ return 0;
+}
+
+
+
+/* set the FD_CLOEXEC fcntl if the options do not set it to 0 */
+int applyopts_cloexec(int fd, struct opt *opts) {
+ bool docloexec = 1;
+
+ if (!opts) return 0;
+
+ retropt_bool(opts, OPT_CLOEXEC, &docloexec);
+ if (docloexec) {
+ if (Fcntl_l(fd, F_SETFD, FD_CLOEXEC) < 0) {
+ Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", fd, strerror(errno));
+ }
+ }
+ return 0;
+}
+
+int applyopts_fchown(int fd, struct opt *opts) {
+ uid_t user = -1;
+ gid_t group = -1;
+
+ retropt_uidt(opts, OPT_USER, &user);
+ retropt_gidt(opts, OPT_GROUP, &group);
+
+ if (user != (uid_t)-1 || group != (gid_t)-1) {
+ if (Fchown(fd, user, group) < 0) {
+ Error4("fchown(%d, "F_uid", "F_gid"): %s", fd, user, group,
+ strerror(errno));
+ return STAT_RETRYLATER;
+ }
+ }
+ return 0;
+}
+
+/* caller must make sure that option is not yet consumed */
+static int applyopt_offset(struct single *xfd, struct opt *opt) {
+ unsigned char *ptr;
+
+ ptr = (unsigned char *)xfd + opt->desc->major;
+ switch (opt->desc->type) {
+ case TYPE_BOOL:
+ *(bool *)ptr = opt->value.u_bool; break;
+ case TYPE_DOUBLE:
+ *(double *)ptr = opt->value.u_double; break;
+ case TYPE_TIMEVAL:
+ *(struct timeval *)ptr = opt->value.u_timeval; break;
+ case TYPE_STRING_NULL:
+ if (opt->value.u_string == NULL) {
+ *(char **)ptr = NULL;
+ break;
+ }
+ /* PASSTHROUGH */
+ case TYPE_STRING:
+ if ((*(char **)ptr = strdup(opt->value.u_string)) == NULL) {
+ Error1("strdup("F_Zu"): out of memory",
+ strlen(opt->value.u_string)+1);
+ }
+ break;
+ case TYPE_CONST:
+ *(int *)ptr = opt->desc->minor;
+ break;
+ default:
+ Error1("applyopt_offset(): type %d not implemented",
+ opt->desc->type);
+ return -1;
+ }
+ opt->desc = ODESC_DONE;
+ return 0;
+}
+
+int applyopts_offset(struct single *xfd, struct opt *opts) {
+ struct opt *opt;
+
+ opt = opts; while (opt->desc != ODESC_END) {
+ if ((opt->desc == ODESC_DONE) ||
+ opt->desc->func != OFUNC_OFFSET) {
+ ++opt; continue; }
+
+ applyopt_offset(xfd, opt);
+ opt->desc = ODESC_DONE;
+ ++opt;
+ }
+ return 0;
+}
+
+/* applies to xfd all OFUNC_EXT options belonging to phase
+ returns -1 if an error occurred */
+int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
+ struct opt *opt;
+ int lockrc;
+
+ if (!opts) return 0;
+
+ opt = opts; while (opt->desc != ODESC_END) {
+ if ((opt->desc == ODESC_DONE) ||
+ (opt->desc->phase != phase && phase != PH_ALL)) {
+ /* option not handled in this function */
+ ++opt; continue;
+ } else {
+ switch (opt->desc->func) {
+
+ case OFUNC_OFFSET:
+ applyopt_offset(xfd, opt);
+ break;
+
+ case OFUNC_EXT:
+ switch (opt->desc->optcode) {
+#if 0
+ case OPT_IGNOREEOF:
+ xfd->ignoreeof = true;
+ break;
+ case OPT_CR:
+ xfd->lineterm = LINETERM_CR;
+ break;
+ case OPT_CRNL:
+ xfd->lineterm = LINETERM_CRNL;
+ break;
+#endif /* 0 */
+ case OPT_READBYTES:
+ xfd->readbytes = opt->value.u_sizet;
+ xfd->actbytes = xfd->readbytes;
+ break;
+ case OPT_LOCKFILE:
+ if (xfd->lock.lockfile) {
+ Error("only one use of options lockfile and waitlock allowed");
+ }
+ xfd->lock.lockfile = strdup(opt->value.u_string);
+ xfd->lock.intervall.tv_sec = 1;
+ xfd->lock.intervall.tv_nsec = 0;
+
+ if ((lockrc = xiolock(&xfd->lock)) < 0) {
+ /* error message already printed */
+ return -1;
+ }
+ if (lockrc) {
+ Error1("could not obtain lock \"%s\"", xfd->lock.lockfile);
+ } else {
+ xfd->havelock = true;
+ }
+ break;
+ case OPT_WAITLOCK:
+ if (xfd->lock.lockfile) {
+ Error("only one use of options lockfile and waitlock allowed");
+ }
+ xfd->lock.lockfile = strdup(opt->value.u_string);
+ xfd->lock.waitlock = true;
+ xfd->lock.intervall.tv_sec = 1;
+ xfd->lock.intervall.tv_nsec = 0;
+
+ /*! this should be integrated into central select loop */
+ if (xiolock(&xfd->lock) < 0) {
+ return -1;
+ }
+ xfd->havelock = true;
+ break;
+
+ default:
+ /* just store the value in the correct component of struct single */
+ if (opt->desc->type == TYPE_CONST) {
+ /* only for integral types compatible to int */
+ *(int *)(&((char *)xfd)[opt->desc->major]) = opt->desc->arg3;
+ } else {
+ memcpy(&((char *)xfd)[opt->desc->major], &opt->value, opt->desc->minor);
+ }
+ }
+ break;
+
+ case OFUNC_OFFSET_MASKS:
+ {
+ void *masks = (char *)xfd + opt->desc->major;
+ size_t masksize = opt->desc->minor;
+ unsigned long bit = opt->desc->arg3;
+ switch (masksize) {
+ case sizeof(uint16_t):
+ if (opt->value.u_bool) {
+ ((uint16_t *)masks)[0] |= bit;
+ } else {
+ ((uint16_t *)masks)[1] |= bit;
+ }
+ break;
+ case sizeof(uint32_t):
+ if (opt->value.u_bool) {
+ ((uint32_t *)masks)[0] |= bit;
+ } else {
+ ((uint32_t *)masks)[1] |= bit;
+ }
+ break;
+ default:
+ Info1("sizeof(uint32_t)="F_Zu, sizeof(uint32_t));
+ Error1("applyopts_single: masksize "F_Zu" not implemented",
+ masksize);
+ }
+ }
+ break;
+
+#if WITH_SOCKET
+ case OFUNC_SOCKOPT:
+ switch (opt->desc->optcode) {
+#if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN))
+ case OPT_IP_ADD_MEMBERSHIP:
+ {
+ union {
+#if HAVE_STRUCT_IP_MREQN
+ struct ip_mreqn mreqn;
+#endif
+ struct ip_mreq mreq;
+ } ip4_mreqn = {{{0}}};
+ /* IPv6 not supported - seems to have different handling */
+/*
+mc:addr:ifname|ifind
+mc:ifname|ifind
+mc:addr
+*/
+ union sockaddr_union sockaddr1;
+ size_t socklen1 = sizeof(sockaddr1.ip4);
+ union sockaddr_union sockaddr2;
+ size_t socklen2 = sizeof(sockaddr2.ip4);
+
+ /* first parameter is alway multicast address */
+ /*! result */
+ xiogetaddrinfo(opt->value.u_ip_mreq.multiaddr, NULL,
+ xfd->para.socket.la.soa.sa_family,
+ SOCK_DGRAM, IPPROTO_IP,
+ &sockaddr1, &socklen1, 0, 0);
+ ip4_mreqn.mreq.imr_multiaddr = sockaddr1.ip4.sin_addr;
+ if (0) {
+ ; /* for canonical reasons */
+#if HAVE_STRUCT_IP_MREQN
+ } else if (opt->value.u_ip_mreq.ifindex[0] != '\0') {
+ /* three parameters */
+ /* second parameter is interface address */
+ xiogetaddrinfo(opt->value.u_ip_mreq.param2, NULL,
+ xfd->para.socket.la.soa.sa_family,
+ SOCK_DGRAM, IPPROTO_IP,
+ &sockaddr2, &socklen2, 0, 0);
+ 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)
+ < 0) {
+ Error1("cannot resolve interface \"%s\"",
+ opt->value.u_ip_mreq.ifindex);
+ }
+#endif /* HAVE_STRUCT_IP_MREQN */
+ } else {
+ /* two parameters */
+ if (0) {
+ ; /* for canonical reasons */
+#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)
+ >= 0) {
+ /* yes, second param converts to interface */
+ ip4_mreqn.mreq.imr_interface.s_addr = htonl(0);
+#endif /* HAVE_STRUCT_IP_MREQN */
+ } else {
+ /*! result */
+ xiogetaddrinfo(opt->value.u_ip_mreq.param2, NULL,
+ xfd->para.socket.la.soa.sa_family,
+ SOCK_DGRAM, IPPROTO_IP,
+ &sockaddr2, &socklen2, 0, 0);
+ ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
+ }
+ }
+
+#if LATER
+ if (0) {
+ ; /* for canonical reasons */
+ } else if (xfd->para.socket.la.soa.sa_family == PF_INET) {
+ } else if (xfd->para.socket.la.soa.sa_family == PF_INET6) {
+ ip6_mreqn.mreq.imr_multiaddr = sockaddr1.ip6.sin6_addr;
+ ip6_mreqn.mreq.imr_interface = sockaddr2.ip6.sin6_addr;
+ }
+#endif
+
+#if HAVE_STRUCT_IP_MREQN
+ if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
+ &ip4_mreqn.mreqn, sizeof(ip4_mreqn.mreqn)) < 0) {
+ Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,%d}, "F_Zu"): %s",
+ xfd->fd, opt->desc->major, opt->desc->minor,
+ ip4_mreqn.mreqn.imr_multiaddr.s_addr,
+ ip4_mreqn.mreqn.imr_address.s_addr,
+ ip4_mreqn.mreqn.imr_ifindex,
+ sizeof(ip4_mreqn.mreqn),
+ strerror(errno));
+ opt->desc = ODESC_ERROR; continue;
+ }
+#else
+ if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
+ &ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) {
+ Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s",
+ xfd->fd, opt->desc->major, opt->desc->minor,
+ ip4_mreqn.mreq.imr_multiaddr,
+ ip4_mreqn.mreq.imr_interface,
+ sizeof(ip4_mreqn.mreq),
+ strerror(errno));
+ opt->desc = ODESC_ERROR; continue;
+ }
+#endif
+ break;
+ }
+ break;
+#endif /* WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) */
+
+
+
+#if WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ)
+ case OPT_IPV6_JOIN_GROUP:
+ {
+ struct ipv6_mreq ip6_mreq = {{{{0}}}};
+ union sockaddr_union sockaddr1;
+ size_t socklen1 = sizeof(sockaddr1.ip6);
+
+ /* always two parameters */
+ /* first parameter is multicast address */
+ /*! result */
+ xiogetaddrinfo(opt->value.u_ip_mreq.multiaddr, NULL,
+ xfd->para.socket.la.soa.sa_family,
+ SOCK_DGRAM, IPPROTO_IP,
+ &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) {
+ Error1("interface \"%s\" not found",
+ opt->value.u_ip_mreq.param2);
+ ip6_mreq.ipv6mr_interface = htonl(0);
+ }
+
+ if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
+ &ip6_mreq, sizeof(ip6_mreq)) < 0) {
+ Error6("setsockopt(%d, %d, %d, {...,0x%08x}, "F_Zu"): %s",
+ xfd->fd, opt->desc->major, opt->desc->minor,
+ ip6_mreq.ipv6mr_interface,
+ sizeof(ip6_mreq),
+ strerror(errno));
+ opt->desc = ODESC_ERROR; continue;
+ }
+ }
+ break;
+#endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
+ default:
+ /* ignore here */
+ ++opt; continue;
+ }
+ break;
+#endif /* WITH_SOCKET */
+
+ default:
+ ++opt;
+ continue;
+ }
+ opt->desc = ODESC_DONE;
+ ++opt;
+ }
+ }
+ return 0;
+}
+
+
+/* xfd->para.exec.pid must be set */
+int applyopts_signal(struct single *xfd, struct opt *opts) {
+ struct opt *opt;
+
+ if (!opts) return 0;
+
+ opt = opts; while (opt->desc != ODESC_END) {
+ if (opt->desc == ODESC_DONE || opt->desc->func != OFUNC_SIGNAL) {
+ ++opt; continue;
+ }
+
+ if (xio_opt_signal(xfd->para.exec.pid, opt->desc->major) < 0) {
+ opt->desc = ODESC_ERROR; continue;
+ }
+ opt->desc = ODESC_DONE;
+ ++opt;
+ }
+ return 0;
+}
+
+/* apply remaining options to file descriptor, and tell us if something is
+ still unused */
+int _xio_openlate(struct single *fd, struct opt *opts) {
+ int numleft;
+ int result;
+
+ _xioopen_setdelayeduser();
+
+ if ((result = applyopts(fd->fd, opts, PH_LATE)) < 0) {
+ return result;
+ }
+ if ((result = applyopts_single(fd, opts, PH_LATE)) < 0) {
+ return result;
+ }
+ if ((result = applyopts(fd->fd, opts, PH_LATE2)) < 0) {
+ return result;
+ }
+
+ if ((numleft = leftopts(opts)) > 0) {
+ showleft(opts);
+ Error1("%d option(s) could not be used", numleft);
+ return -1;
+ }
+ return 0;
+}
+
+int dropopts(struct opt *opts, unsigned int phase) {
+ struct opt *opt;
+
+ /*!*/
+ if (phase == PH_ALL) {
+ free(opts);
+ return 0;
+ }
+ opt = opts; while (opt && opt->desc != ODESC_END) {
+ if (opt->desc != ODESC_DONE && opt->desc->phase == phase) {
+ Debug1("ignoring option \"%s\"", opt->desc->defname);
+ opt->desc = ODESC_DONE;
+ }
+ ++opt;
+ }
+ return 0;
+}
+
+int dropopts2(struct opt *opts, unsigned int from, unsigned int to) {
+ unsigned int i;
+
+ for (i = from; i <= to; ++i) {
+ dropopts(opts, i);
+ }
+ return 0;
+}
+
diff --git a/xioopts.h b/xioopts.h
new file mode 100644
index 0000000..7d13ea5
--- /dev/null
+++ b/xioopts.h
@@ -0,0 +1,872 @@
+/* $Id: xioopts.h,v 1.70 2007/03/06 21:19:46 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xioopts_h_included
+#define __xioopts_h_included 1
+
+#define ODESC_END ((void *)0) /* indicates end of actual option array */
+#define ODESC_DONE ((void *)-1) /* indicates that option has been applied */
+#define ODESC_ERROR ODESC_DONE /* maybe later */
+
+/* atomic structure for use in the option search table; keep compatible with
+ struct wordent! */
+struct optname {
+ const char *name;
+ const struct optdesc *desc;
+} ;
+
+/* keep consistent with xiohelp.c:optiontypenames[] ! */
+enum e_types {
+ TYPE_CONST, /* keyword means a fix value */
+ 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_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_IP_MREQN, /* for struct ip_mreq or struct ip_mreqn */
+ TYPE_IP4NAME, /* IPv4 hostname or address */
+
+ TYPE_2BYTE = TYPE_USHORT
+} ;
+
+enum e_func {
+ OFUNC_NONE, /* no function - should not occur */
+ OFUNC_FLAG, /* no function, but bitposition, only with bool; arg1 is mask */
+ OFUNC_FLAG_PATTERN, /* no function, but bitpattern: arg1 is pattern, arg2 is mask */
+ 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_MASK_LONG, /* arg1 is getrequest, arg2 is setrequest:
+ ioctl(arg1, ); |= arg3; ioctl(arg2, ); */
+ OFUNC_SOCKOPT, /* setsockopt() */
+ OFUNC_SOCKOPT_APPEND,/* getsockopt(), append data, setsockopt() */
+ OFUNC_FLOCK, /* flock() */
+ OFUNC_TERMIO, /* termio() ? */
+ OFUNC_SPEC, /* special, i.e. no generalizable function call */
+ OFUNC_OFFSET, /* put a value into xiofile struct; major is offset */
+ OFUNC_OFFSET_MASKS, /* !!! */
+ /*OFUNC_APPL,*/ /* special, i.e. application must know which f. */
+ OFUNC_EXT, /* with extended file descriptors only */
+ OFUNC_TERMIOS_FLAG, /* a flag in struct termios: major..tcflag, minor..bit
+ */
+ OFUNC_TERMIOS_PATTERN, /* a multibit: major..tcflag, minor..pattern,
+ arg3..mask */
+ OFUNC_TERMIOS_VALUE, /* a variable value: major..tcflag, minor..mask, arg3..shift */
+ OFUNC_TERMIOS_CHAR, /* a termios functional character: major..c_cc index */
+ OFUNC_TERMIOS_SPEED, /* termios c_ispeed etc on FreeBSD */
+ 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 */
+} ;
+
+/* for simpler handling of option-to-connection-type relations we define
+ groups. to keep the search for options simple, we allow each option to
+ belong to at most one group only. (we have a dummy GROUP_NONE for those
+ that don't want to belong to any...)
+ The caller of parseopts() specifies per bitpatter a set of groups where it
+ accepts options from.
+*/
+
+/*- the group bits are:
+- 000ooooo 00000000 000000uf 0000ssss
+- ooooo: more detailed description to ssss (e.g., socket family)
+- ssss: the type of stream, as in stat.h: S_IF...
+- f: has a named entry in the file system
+- u: has user and group
+*/
+/* keep consistent with xiohelp.c:addressgroupnames[] ! */
+/* a dummy group */
+#define GROUP_NONE 0x00000000
+
+#define GROUP_FD 0x00000001 /* everything applyable to a fd */
+#define GROUP_FIFO 0x00000002
+#define GROUP_CHR 0x00000004
+#define GROUP_BLK 0x00000008
+#define GROUP_REG 0x00000010
+#define GROUP_FILE GROUP_REG
+#define GROUP_SOCKET 0x00000020
+#define GROUP_READLINE 0x00000040
+
+#define GROUP_NAMED 0x00000100 /* file system entry */
+#define GROUP_OPEN 0x00000200 /* flags for open() */
+#define GROUP_EXEC 0x00000400 /* program or script execution */
+#define GROUP_FORK 0x00000800 /* communication with forked process */
+
+#define GROUP_LISTEN 0x00001000 /* socket in listening mode */
+/* 0x00002000 */
+#define GROUP_CHILD 0x00004000 /* autonom child process */
+#define GROUP_RETRY 0x00008000 /* when open/connect etc. fails */
+#define GROUP_TERMIOS 0x00010000
+#define GROUP_RANGE 0x00020000 /* differs from GROUP_LISTEN */
+#define GROUP_PTY 0x00040000 /* address pty or exec...,pty */
+#define GROUP_PARENT 0x00080000 /* for parent of communicating child */
+
+#define GROUP_SOCK_UNIX 0x00100000
+#define GROUP_SOCK_IP4 0x00200000
+#define GROUP_SOCK_IP6 0x00400000
+#define GROUP_SOCK_IP (GROUP_SOCK_IP4|GROUP_SOCK_IP6)
+#define GROUP_INTERFACE 0x00800000
+#define GROUP_TUN GROUP_INTERFACE
+
+#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_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_ANY (GROUP_PROCESS|GROUP_APPL)
+#define GROUP_ALL 0xffffffff
+
+
+/* no IP multicasts, no error queue yet */
+/* the only reason for keeping this enum sorted is to help detecting name
+ conflicts. */
+/* optcode's */
+enum e_optcode {
+ OPT_ADDRESS_FAMILY = 1,
+ /* these are not alphabetically, I know... */
+ OPT_B0, /* termios.c_cflag */
+ OPT_B50, /* termios.c_cflag */
+ OPT_B75, /* termios.c_cflag */
+ OPT_B110, /* termios.c_cflag */
+ OPT_B134, /* termios.c_cflag */
+ OPT_B150, /* termios.c_cflag */
+ OPT_B200, /* termios.c_cflag */
+ OPT_B300, /* termios.c_cflag */
+ OPT_B600, /* termios.c_cflag */
+ OPT_B900, /* termios.c_cflag - HP-UX */
+ OPT_B1200, /* termios.c_cflag */
+ OPT_B1800, /* termios.c_cflag */
+ OPT_B2400, /* termios.c_cflag */
+ OPT_B3600, /* termios.c_cflag - HP-UX */
+ OPT_B4800, /* termios.c_cflag */
+ OPT_B7200, /* termios.c_cflag - HP-UX */
+ OPT_B9600, /* termios.c_cflag */
+ OPT_B19200, /* termios.c_cflag */
+ OPT_B38400, /* termios.c_cflag */
+ OPT_B57600, /* termios.c_cflag */
+ OPT_B115200, /* termios.c_cflag */
+ OPT_B230400, /* termios.c_cflag */
+ OPT_B460800, /* termios.c_cflag */
+ OPT_B500000, /* termios.c_cflag */
+ OPT_B576000, /* termios.c_cflag */
+ OPT_B921600, /* termios.c_cflag */
+ OPT_B1000000, /* termios.c_cflag */
+ OPT_B1152000, /* termios.c_cflag */
+ OPT_B1500000, /* termios.c_cflag */
+ OPT_B2000000, /* termios.c_cflag */
+ OPT_B2500000, /* termios.c_cflag */
+ OPT_B3000000, /* termios.c_cflag */
+ OPT_B3500000, /* termios.c_cflag */
+ OPT_B4000000, /* termios.c_cflag */
+ OPT_BACKLOG,
+ OPT_BIND, /* a socket address as character string */
+ OPT_BRKINT, /* termios.c_iflag */
+#ifdef BSDLY
+# ifdef BS0
+ OPT_BS0, /* termios.c_oflag */
+# endif
+# ifdef BS1
+ OPT_BS1, /* termios.c_oflag */
+# endif
+ OPT_BSDLY, /* termios.c_oflag */
+#endif
+ OPT_CHROOT, /* chroot() past file system access */
+ OPT_CHROOT_EARLY, /* chroot() before file system access */
+ /*OPT_CIBAUD,*/ /* termios.c_cflag */
+ OPT_CLOCAL, /* termios.c_cflag */
+ OPT_CLOEXEC,
+ OPT_CONNECT_TIMEOUT, /* socket connect */
+ OPT_COOL_WRITE,
+ OPT_CR, /* customized */
+#ifdef CR0
+ OPT_CR0, /* termios.c_oflag */
+#endif
+#ifdef CR1
+ OPT_CR1, /* termios.c_oflag */
+#endif
+#ifdef CR2
+ OPT_CR2, /* termios.c_oflag */
+#endif
+#ifdef CR3
+ OPT_CR3, /* termios.c_oflag */
+#endif
+#ifdef CRDLY
+ OPT_CRDLY, /* termios.c_oflag */
+#endif
+ OPT_CREAD, /* termios.c_cflag */
+ OPT_CRNL, /* customized */
+#ifdef CRTSCTS
+ OPT_CRTSCTS, /* termios.c_cflag */
+#endif
+ OPT_CS5, /* termios.c_cflag */
+ OPT_CS6, /* termios.c_cflag */
+ OPT_CS7, /* termios.c_cflag */
+ OPT_CS8, /* termios.c_cflag */
+ OPT_CSIZE, /* termios.c_cflag */
+ OPT_CSTOPB, /* termios.c_cflag */
+ OPT_DASH, /* exec() */
+ OPT_ECHO, /* termios.c_lflag */
+ OPT_ECHOCTL, /* termios.c_lflag */
+ OPT_ECHOE, /* termios.c_lflag */
+ OPT_ECHOK, /* termios.c_lflag */
+ OPT_ECHOKE, /* termios.c_lflag */
+ OPT_ECHONL, /* termios.c_lflag */
+#ifdef ECHOPRT
+ OPT_ECHOPRT, /* termios.c_lflag */
+#endif
+ OPT_END_CLOSE, /* xfd.stream.howtoend = END_CLOSE */
+ OPT_EXT2_SECRM,
+ OPT_EXT2_UNRM,
+ OPT_EXT2_COMPR,
+ OPT_EXT2_SYNC,
+ OPT_EXT2_IMMUTABLE,
+ OPT_EXT2_APPEND,
+ OPT_EXT2_NODUMP,
+ OPT_EXT2_NOATIME,
+ OPT_EXT2_JOURNAL_DATA,
+ OPT_EXT2_NOTAIL,
+ OPT_EXT2_DIRSYNC,
+ OPT_EXT2_TOPDIR,
+ OPT_FDIN,
+ OPT_FDOUT,
+#ifdef FFDLY
+# ifdef FF0
+ OPT_FF0, /* termios.c_oflag */
+# endif
+# ifdef FF1
+ OPT_FF1, /* termios.c_oflag */
+# endif
+ OPT_FFDLY, /* termios.c_oflag */
+#endif
+#ifdef FIOSETOWN
+ OPT_FIOSETOWN, /* asm/sockios.h */
+#endif
+ OPT_FLOCK_EX, /* flock(fd, LOCK_EX) */
+ OPT_FLOCK_EX_NB, /* flock(fd, LOCK_EX|LOCK_NB) */
+ OPT_FLOCK_SH, /* flock(fd, LOCK_SH) */
+ OPT_FLOCK_SH_NB, /* flock(fd, LOCK_SH|LOCK_NB) */
+ OPT_FLUSHO, /* termios.c_lflag */
+ /*0 OPT_FORCE,*/
+ OPT_FOREVER,
+ OPT_FORK,
+ OPT_FTRUNCATE32, /* ftruncate() */
+ OPT_FTRUNCATE64, /* ftruncate64() */
+ OPT_F_SETLKW_RD, /* fcntl with struct flock - read-lock, wait */
+ OPT_F_SETLKW_WR, /* fcntl with struct flock - write-lock, wait */
+ OPT_F_SETLK_RD, /* fcntl with struct flock - read-lock */
+ OPT_F_SETLK_WR, /* fcntl with struct flock - write-lock */
+ OPT_GROUP,
+ OPT_GROUP_EARLY,
+ OPT_GROUP_LATE,
+ OPT_HISTORY_FILE, /* readline history file */
+ OPT_HUPCL, /* termios.c_cflag */
+ OPT_ICANON, /* termios.c_lflag */
+ OPT_ICRNL, /* termios.c_iflag */
+ OPT_IEXTEN, /* termios.c_lflag */
+ OPT_IFF_ALLMULTI, /* struct ifreq.ifr_flags */
+ OPT_IFF_AUTOMEDIA, /* struct ifreq.ifr_flags */
+ OPT_IFF_BROADCAST, /* struct ifreq.ifr_flags */
+ OPT_IFF_DEBUG, /* struct ifreq.ifr_flags */
+ /*OPT_IFF_DYNAMIC,*/ /* struct ifreq.ifr_flags */
+ OPT_IFF_LOOPBACK, /* struct ifreq.ifr_flags */
+ OPT_IFF_MASTER, /* struct ifreq.ifr_flags */
+ OPT_IFF_MULTICAST, /* struct ifreq.ifr_flags */
+ OPT_IFF_NOARP, /* struct ifreq.ifr_flags */
+ OPT_IFF_NOTRAILERS, /* struct ifreq.ifr_flags */
+ OPT_IFF_NO_PI, /* tun: IFF_NO_PI */
+ OPT_IFF_PORTSEL, /* struct ifreq.ifr_flags */
+ OPT_IFF_POINTOPOINT, /* struct ifreq.ifr_flags */
+ OPT_IFF_PROMISC, /* struct ifreq.ifr_flags */
+ OPT_IFF_RUNNING, /* struct ifreq.ifr_flags */
+ OPT_IFF_SLAVE, /* struct ifreq.ifr_flags */
+ OPT_IFF_UP, /* struct ifreq.ifr_flags */
+ OPT_IGNBRK, /* termios.c_iflag */
+ OPT_IGNCR, /* termios.c_iflag */
+ OPT_IGNORECR, /* HTTP */
+ OPT_IGNOREEOF, /* customized */
+ OPT_IGNPAR, /* termios.c_iflag */
+ OPT_IMAXBEL, /* termios.c_iflag */
+ OPT_INLCR, /* termios.c_iflag */
+ OPT_INPCK, /* termios.c_iflag */
+ OPT_INTERVALL,
+ OPT_IPV6_JOIN_GROUP,
+ OPT_IPV6_V6ONLY,
+#if 0 /* see Linux: man 7 netlink; probably not what we need yet */
+ OPT_IO_SIOCGIFNAME,
+#endif
+ OPT_IP_ADD_MEMBERSHIP,
+#ifdef IP_HDRINCL
+ OPT_IP_HDRINCL,
+#endif
+#ifdef IP_FREEBIND
+ OPT_IP_FREEBIND,
+#endif
+#ifdef IP_MTU
+ OPT_IP_MTU,
+#endif
+#ifdef IP_MTU_DISCOVER
+ OPT_IP_MTU_DISCOVER,
+#endif
+ OPT_IP_MULTICAST_IF,
+ OPT_IP_MULTICAST_LOOP,
+ OPT_IP_MULTICAST_TTL,
+ OPT_IP_OPTIONS,
+#ifdef IP_PKTINFO
+ OPT_IP_PKTINFO,
+#endif
+#ifdef IP_PKTOPTIONS
+ OPT_IP_PKTOPTIONS,
+#endif
+#ifdef IP_RECVERR
+ OPT_IP_RECVERR,
+#endif
+#ifdef IP_RECVOPTS
+ OPT_IP_RECVOPTS,
+#endif
+#ifdef IP_RECVTOS
+ OPT_IP_RECVTOS,
+#endif
+#ifdef IP_RECVTTL
+ OPT_IP_RECVTTL,
+#endif
+#ifdef IP_RETOPTS
+ OPT_IP_RETOPTS,
+#endif
+#ifdef IP_ROUTER_ALERT
+ OPT_IP_ROUTER_ALERT,
+#endif
+ OPT_IP_TOS,
+ OPT_IP_TTL,
+ OPT_ISIG, /* termios.c_lflag */
+ OPT_ISPEED, /* termios.c_ispeed */
+ OPT_ISTRIP, /* termios.c_iflag */
+#ifdef IUCLC
+ OPT_IUCLC, /* termios.c_iflag */
+#endif
+ OPT_IXANY, /* termios.c_iflag */
+ OPT_IXOFF, /* termios.c_iflag */
+ OPT_IXON, /* termios.c_iflag */
+ OPT_LOCKFILE,
+ OPT_LOWPORT,
+#ifdef NLDLY
+# ifdef NL0
+ OPT_NL0, /* termios.c_oflag */
+# endif
+# ifdef NL0
+ OPT_NL1, /* termios.c_oflag */
+# endif
+ OPT_NLDLY, /* termios.c_oflag */
+#endif
+ OPT_NOECHO, /* readline */
+ OPT_NOFLSH, /* termios.c_lflag */
+ OPT_NOFORK, /* exec, system */
+ OPT_NOPROMPT, /* readline */
+#ifdef OCRNL
+ OPT_OCRNL, /* termios.c_oflag */
+#endif
+#ifdef OFDEL
+ OPT_OFDEL, /* termios.c_oflag */
+#endif
+#ifdef OFILL
+ OPT_OFILL, /* termios.c_oflag */
+#endif
+#ifdef OLCUC
+ OPT_OLCUC, /* termios.c_oflag */
+#endif
+ OPT_ONLCR, /* termios.c_oflag */
+#ifdef ONLRET
+ OPT_ONLRET, /* termios.c_oflag */
+#endif
+#ifdef ONOCR
+ OPT_ONOCR, /* termios.c_oflag */
+#endif
+#if HAVE_OPENPTY
+ OPT_OPENPTY,
+#endif
+ OPT_OPENSSL_CAFILE,
+ OPT_OPENSSL_CAPATH,
+ OPT_OPENSSL_CERTIFICATE,
+ OPT_OPENSSL_CIPHERLIST,
+ OPT_OPENSSL_DHPARAM,
+ OPT_OPENSSL_EGD,
+ OPT_OPENSSL_FIPS,
+ OPT_OPENSSL_KEY,
+ OPT_OPENSSL_METHOD,
+ OPT_OPENSSL_PSEUDO,
+ OPT_OPENSSL_VERIFY,
+ OPT_OPOST, /* termios.c_oflag */
+ OPT_OSPEED, /* termios.c_ospeed */
+ OPT_O_APPEND,
+#ifdef O_ASYNC
+ OPT_O_ASYNC,
+#endif
+ OPT_O_BINARY, /* Cygwin */
+ OPT_O_CREATE,
+#ifdef O_DEFER
+ OPT_O_DEFER,
+#endif
+#ifdef O_DELAY
+ OPT_O_DELAY,
+#endif
+#ifdef O_DIRECT
+ OPT_O_DIRECT,
+#endif
+#ifdef O_DIRECTORY
+ OPT_O_DIRECTORY,
+#endif
+#ifdef O_DSYNC
+ OPT_O_DSYNC,
+#endif
+ OPT_O_EXCL,
+#ifdef O_LARGEFILE
+ OPT_O_LARGEFILE,
+#endif
+#if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
+ OPT_O_NDELAY,
+#endif
+ OPT_O_NOATIME,
+ OPT_O_NOCTTY,
+#ifdef O_NOFOLLOW
+ OPT_O_NOFOLLOW,
+#endif
+ OPT_O_NOINHERIT, /* Cygwin */
+ OPT_O_NONBLOCK,
+#ifdef O_NSHARE
+ OPT_O_NSHARE,
+#endif
+#ifdef O_PRIV
+ OPT_O_PRIV,
+#endif
+ OPT_O_RDONLY, /* open() */
+ OPT_O_RDWR, /* open() */
+#ifdef O_RSHARE
+ OPT_O_RSHARE,
+#endif
+#ifdef O_RSYNC
+ OPT_O_RSYNC,
+#endif
+#ifdef O_SYNC
+ OPT_O_SYNC,
+#endif
+ OPT_O_TEXT, /* Cygwin */
+ OPT_O_TRUNC, /* open(): O_TRUNC */
+ OPT_O_WRONLY, /* open() */
+ OPT_PARENB, /* termios.c_cflag */
+ OPT_PARMRK, /* termios.c_iflag */
+ OPT_PARODD, /* termios.c_cflag */
+ OPT_PATH,
+#ifdef PENDIN
+ OPT_PENDIN, /* termios.c_lflag */
+#endif
+ OPT_PERM,
+ OPT_PERM_EARLY,
+ OPT_PERM_LATE,
+ OPT_PIPES,
+ /*OPT_PORT,*/
+ OPT_PROMPT, /* readline */
+ OPT_PROTOCOL_FAMILY,
+ OPT_PROXYPORT,
+ OPT_PROXY_AUTHORIZATION,
+ OPT_PROXY_RESOLVE,
+#if HAVE_DEV_PTMX || HAVE_DEV_PTC
+ OPT_PTMX,
+#endif
+ OPT_PTY,
+ OPT_PTY_INTERVALL,
+ OPT_PTY_WAIT_SLAVE,
+ OPT_RANGE, /* restrict client socket address */
+ OPT_RAW, /* termios */
+ OPT_READBYTES,
+ OPT_RES_AAONLY, /* resolver(3) */
+ OPT_RES_DEBUG, /* resolver(3) */
+ OPT_RES_DEFNAMES, /* resolver(3) */
+ OPT_RES_DNSRCH, /* resolver(3) */
+ OPT_RES_IGNTC, /* resolver(3) */
+ OPT_RES_PRIMARY, /* resolver(3) */
+ OPT_RES_RECURSE, /* resolver(3) */
+ OPT_RES_STAYOPEN, /* resolver(3) */
+ OPT_RES_USEVC, /* resolver(3) */
+ OPT_RETRY,
+ OPT_SANE, /* termios */
+ OPT_SEEK32_CUR,
+ OPT_SEEK32_END,
+ OPT_SEEK32_SET,
+ OPT_SEEK64_CUR,
+ OPT_SEEK64_END,
+ OPT_SEEK64_SET,
+ OPT_SETGID,
+ OPT_SETGID_EARLY,
+ OPT_SETPGID,
+ OPT_SETSID,
+ OPT_SETUID,
+ OPT_SETUID_EARLY,
+ OPT_SIGHUP,
+ OPT_SIGINT,
+ OPT_SIGQUIT,
+#ifdef SIOCSPGRP
+ OPT_SIOCSPGRP,
+#endif
+#ifdef SO_ACCEPTCONN
+ OPT_SO_ACCEPTCONN,
+#endif /* SO_ACCEPTCONN */
+#ifdef SO_ATTACH_FILTER
+ OPT_SO_ATTACH_FILTER,
+#endif
+#ifdef SO_AUDIT /* AIX 4.3.3 */
+ OPT_SO_AUDIT,
+#endif /* SO_AUDIT */
+#ifdef SO_BINDTODEVICE
+ OPT_SO_BINDTODEVICE,
+#endif
+ OPT_SO_BROADCAST,
+#ifdef SO_BSDCOMPAT
+ OPT_SO_BSDCOMPAT,
+#endif
+#ifdef SO_CKSUMRECV
+ OPT_SO_CKSUMRECV,
+#endif /* SO_CKSUMRECV */
+ OPT_SO_DEBUG,
+#ifdef SO_DETACH_FILTER
+ OPT_SO_DETACH_FILTER,
+#endif
+#ifdef SO_DGRAM_ERRIND
+ OPT_SO_DGRAM_ERRIND,
+#endif
+#ifdef SO_DONTLINGER
+ OPT_SO_DONTLINGER,
+#endif
+ OPT_SO_DONTROUTE,
+ OPT_SO_ERROR,
+ OPT_SO_KEEPALIVE,
+#ifdef SO_KERNACCEPT /* AIX 4.3.3 */
+ OPT_SO_KERNACCEPT,
+#endif /* SO_KERNACCEPT */
+ OPT_SO_LINGER,
+#ifdef SO_NO_CHECK
+ OPT_SO_NO_CHECK,
+#endif
+#ifdef SO_NOREUSEADDR /* AIX 4.3.3 */
+ OPT_SO_NOREUSEADDR,
+#endif /* SO_NOREUSEADDR */
+ OPT_SO_OOBINLINE,
+#ifdef SO_PASSCRED
+ OPT_SO_PASSCRED,
+#endif
+#ifdef SO_PEERCRED
+ OPT_SO_PEERCRED,
+#endif
+#ifdef SO_PRIORITY
+ OPT_SO_PRIORITY,
+#endif
+#ifdef SO_PROTOTYPE
+ OPT_SO_PROTOTYPE,
+#endif
+ OPT_SO_RCVBUF,
+ OPT_SO_RCVBUF_LATE,
+#ifdef SO_RCVLOWAT
+ OPT_SO_RCVLOWAT,
+#endif
+#ifdef SO_RCVTIMEO
+ OPT_SO_RCVTIMEO,
+#endif
+ OPT_SO_REUSEADDR,
+#ifdef SO_REUSEPORT
+ OPT_SO_REUSEPORT,
+#endif /* defined(SO_REUSEPORT) */
+#ifdef SO_SECURITY_AUTHENTICATION
+ OPT_SO_SECURITY_AUTHENTICATION,
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_NETWORK
+ OPT_SO_SECURITY_ENCRYPTION_NETWORK,
+#endif
+#ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
+ OPT_SO_SECURITY_ENCRYPTION_TRANSPORT,
+#endif
+ OPT_SO_SNDBUF,
+ OPT_SO_SNDBUF_LATE,
+#ifdef SO_SNDLOWAT
+ OPT_SO_SNDLOWAT,
+#endif
+#ifdef SO_SNDTIMEO
+ OPT_SO_SNDTIMEO,
+#endif
+ OPT_SO_TYPE,
+#ifdef SO_USELOOPBACK
+ OPT_SO_USELOOPBACK,
+#endif /* SO_USELOOPBACK */
+#ifdef SO_USE_IFBUFS
+ OPT_SO_USE_IFBUFS,
+#endif /* SO_USE_IFBUFS */
+#if 1 || defined(WITH_SOCKS4)
+ OPT_SOCKSPORT,
+ OPT_SOCKSUSER,
+#endif
+ OPT_SOURCEPORT,
+ OPT_STDERR, /* with exec, system */
+ OPT_SUBSTUSER,
+ OPT_SUBSTUSER_DELAYED,
+ OPT_SYMBOLIC_LINK, /* with pty */
+#ifdef TABDLY
+# ifdef TAB0
+ OPT_TAB0, /* termios.c_oflag */
+# endif
+# ifdef TAB1
+ OPT_TAB1, /* termios.c_oflag */
+# endif
+# ifdef TAB2
+ OPT_TAB2, /* termios.c_oflag */
+# endif
+# ifdef TAB3
+ OPT_TAB3, /* termios.c_oflag */
+# endif
+ OPT_TABDLY, /* termios.c_oflag */
+#endif
+ OPT_TCPWRAPPERS, /* libwrap */
+ OPT_TCPWRAP_ETC, /* libwrap */
+ OPT_TCPWRAP_HOSTS_ALLOW_TABLE, /* libwrap */
+ OPT_TCPWRAP_HOSTS_DENY_TABLE, /* libwrap */
+ OPT_TCP_ABORT_THRESHOLD, /* HP-UX */
+ OPT_TCP_CONN_ABORT_THRESHOLD, /* HP-UX */
+#ifdef TCP_CORK
+ OPT_TCP_CORK,
+#endif
+#ifdef TCP_DEFER_ACCEPT
+ OPT_TCP_DEFER_ACCEPT, /* Linux 2.4.0 */
+#endif
+#ifdef TCP_INFO
+ OPT_TCP_INFO, /* Linux 2.4.0 */
+#endif
+#ifdef TCP_KEEPCNT
+ OPT_TCP_KEEPCNT, /* Linux 2.4.0 */
+#endif
+#ifdef TCP_KEEPIDLE
+ OPT_TCP_KEEPIDLE, /* Linux 2.4.0 */
+#endif
+ OPT_TCP_KEEPINIT, /* OSF1 */
+#ifdef TCP_KEEPINTVL
+ OPT_TCP_KEEPINTVL, /* Linux 2.4.0 */
+#endif
+#ifdef TCP_LINGER2
+ OPT_TCP_LINGER2, /* Linux 2.4.0 */
+#endif
+#ifdef TCP_MAXSEG
+ OPT_TCP_MAXSEG,
+ OPT_TCP_MAXSEG_LATE,
+#endif
+ OPT_TCP_MD5SIG, /* FreeBSD */
+#ifdef TCP_NODELAY
+ OPT_TCP_NODELAY,
+#endif
+ OPT_TCP_NOOPT, /* FreeBSD */
+ OPT_TCP_NOPUSH, /* FreeBSD */
+ OPT_TCP_PAWS, /* OSF1 */
+#ifdef TCP_QUICKACK
+ OPT_TCP_QUICKACK, /* Linux 2.4 */
+#endif
+#ifdef TCP_RFC1323
+ OPT_TCP_RFC1323, /* AIX 4.3.3 */
+#endif
+ OPT_TCP_SACKENA, /* OSF1 */
+ OPT_TCP_SACK_DISABLE, /* OpenBSD */
+ OPT_TCP_SIGNATURE_ENABLE, /* OpenBSD */
+#ifdef TCP_STDURG
+ OPT_TCP_STDURG, /* AIX 4.3.3; Linux: see man 7 tcp */
+#endif
+#ifdef TCP_SYNCNT
+ OPT_TCP_SYNCNT, /* Linux 2.4.0 */
+#endif
+ OPT_TCP_TSOPTENA, /* OSF1 */
+#ifdef TCP_WINDOW_CLAMP
+ OPT_TCP_WINDOW_CLAMP, /* Linux 2.4.0 */
+#endif
+ OPT_TIOCSCTTY,
+ OPT_TOSTOP, /* termios.c_lflag */
+ OPT_TUN_DEVICE, /* tun: /dev/net/tun ... */
+ OPT_TUN_NAME, /* tun: tun0 */
+ OPT_TUN_TYPE, /* tun: tun|tap */
+ OPT_UMASK,
+ OPT_UNIX_TIGHTSOCKLEN, /* UNIX domain sockets */
+ OPT_UNLINK,
+ OPT_UNLINK_CLOSE,
+ OPT_UNLINK_EARLY,
+ OPT_UNLINK_LATE,
+ OPT_USER,
+ OPT_USER_EARLY,
+ OPT_USER_LATE,
+#ifdef VDISCARD
+ OPT_VDISCARD, /* termios.c_cc */
+#endif
+ OPT_VDSUSP, /* termios.c_cc - HP-UX */
+ OPT_VEOF, /* termios.c_cc */
+ OPT_VEOL, /* termios.c_cc */
+ OPT_VEOL2, /* termios.c_cc */
+ OPT_VERASE, /* termios.c_cc */
+ OPT_VINTR, /* termios.c_cc */
+ OPT_VKILL, /* termios.c_cc */
+ OPT_VLNEXT, /* termios.c_cc */
+ OPT_VMIN, /* termios.c_cc */
+ OPT_VQUIT, /* termios.c_cc */
+ OPT_VREPRINT, /* termios.c_cc */
+ OPT_VSTART, /* termios.c_cc */
+ OPT_VSTOP, /* termios.c_cc */
+ OPT_VSUSP, /* termios.c_cc */
+ OPT_VSWTC, /* termios.c_cc */
+ OPT_VTIME, /* termios.c_cc */
+#ifdef VTDLY
+# ifdef VT0
+ OPT_VT0, /* termios.c_oflag */
+# endif
+# ifdef VT1
+ OPT_VT1, /* termios.c_oflag */
+# endif
+ OPT_VTDLY, /* termios.c_oflag */
+#endif
+#ifdef VWERASE
+ OPT_VWERASE, /* termios.c_cc */
+#endif
+ OPT_WAITLOCK,
+#ifdef XCASE
+ OPT_XCASE, /* termios.c_lflag */
+#endif
+#if defined(TABDLY) && defined(XTABS)
+ OPT_XTABS, /* termios.c_oflag */
+#endif
+ OPT_nocomma /* make aix xlc happy, no trailing comma */
+} ;
+
+/* keep consistent with xiohelp.c:optionphasenames ! */
+enum e_phase {
+ PH_ALL, /* not for options; 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 */
+ PH_OPEN, /* during filesystem entry creation/open */
+ PH_PASTOPEN, /* past filesystem entry creation/open */
+ PH_PRESOCKET, /* before socket call */
+ PH_SOCKET, /* for socket call */
+ PH_PASTSOCKET, /* after socket call */
+ PH_PREBIGEN, /* before socketpair() pipe() openpty() */
+ PH_BIGEN, /* during socketpair() pipe() openpty() */
+ PH_PASTBIGEN, /* past socketpair() pipe() openpty() */
+ PH_FD, /* soon after FD creation or identification */
+ PH_PREBIND, /* before socket bind() */
+ PH_BIND, /* during socket bind() ? */
+ PH_PASTBIND, /* past socket bind() - for client and server sockets! */
+ PH_PRELISTEN, /* before socket listen() */
+ PH_LISTEN, /* during socket listen() ? */
+ PH_PASTLISTEN, /* after socket listen() */
+ PH_PRECONNECT, /* before socket connect() */
+ PH_CONNECT, /* during socket connect() ? */
+ PH_PASTCONNECT, /* after socket connect() */
+ PH_PREACCEPT, /* before socket accept() */
+ PH_ACCEPT, /* during socket accept() ? */
+ PH_PASTACCEPT, /* after socket accept() */
+ PH_CONNECTED, /* for sockets, after connect() or accept() */
+ PH_PREFORK, /* before fork() (with both listen and exec!) */
+ PH_FORK, /* during fork() (with both listen and exec!) */
+ PH_PASTFORK, /* after fork() (with both listen and exec!) */
+ PH_LATE, /* FD is ready, before start of data loop */
+ PH_LATE2, /* FD is ready, dropping privileges */
+ PH_PREEXEC, /* before exec() or system() */
+ PH_EXEC, /* during exec() or system() */
+ PH_SPEC /* specific to situation, not fix */
+} ;
+
+/* atomic structure to describe the syntax and more important semantics of an
+ option */
+struct optdesc {
+ const char *defname; /* default name */
+ const char *nickname; /* usual name */
+ enum e_optcode optcode; /* short form of option name */
+ unsigned int group;
+ enum e_phase phase; /* when this option is to be used */
+ enum e_types type; /* the data type as expected on input, and stored */
+ enum e_func func; /* which function can apply this option, e.g. ioctl(),
+ getsockopt(), or just a bit pattern */
+ int major; /* major id for func: level (SOL_...) for setsockopt(),
+ request for ioctl() */
+ int minor; /* minor id for func: SO_..., IP_..., */
+ long arg3;
+} ;
+
+extern bool xioopts_ignoregroups;
+extern const struct optname optionnames[];
+
+
+extern int retropt_bool(struct opt *opts, int optcode, bool *result);
+extern int retropt_short(struct opt *opts, int optcode, short *result);
+extern int retropt_ushort(struct opt *opts, int optcode, unsigned short *result);
+extern int retropt_int(struct opt *opts, int optcode, int *result);
+extern int retropt_uint(struct opt *opts, int optcode, unsigned int *result);
+extern int retropt_long(struct opt *opts, int optcode, long *result);
+extern int retropt_ulong(struct opt *opts, int optcode, unsigned long *result);
+extern int retropt_flag(struct opt *opts, int optcode, flags_t *result);
+extern int retropt_string(struct opt *opts, int optcode, char **result);
+extern int retropt_timespec(struct opt *opts, int optcode, struct timespec *result);
+extern int retropt_bind(struct opt *opts,
+ int af,
+ int socktype,
+ int ipproto,
+ struct sockaddr *sa,
+ socklen_t *salen,
+ 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 applyopts2(int fd, struct opt *opts, unsigned int from,
+ unsigned int to);
+extern int applyopts_flags(struct opt *opts, int group, flags_t *result);
+extern int applyopts_cloexec(int fd, struct opt *opts);
+extern int applyopts_early(const char *path, struct opt *opts);
+extern int applyopts_fchown(int fd, struct opt *opts);
+extern int applyopts_single(struct single *fd, struct opt *opts, enum e_phase phase);
+extern int applyopts_offset(struct single *xfd, struct opt *opts);
+extern int applyopts_signal(struct single *xfd, struct opt *opts);
+extern int _xio_openlate(struct single *fd, struct opt *opts);
+extern int parseopts(const char **a, unsigned int groups, struct opt **opts);
+extern int parseopts_table(const char **a, unsigned int groups,
+ struct opt **opts,
+ const struct optname optionnames[], size_t optionnum);
+extern struct opt *copyopts(const struct opt *opts, unsigned int groups);
+extern struct opt *moveopts(struct opt *opts, unsigned int groups);
+extern int leftopts(const struct opt *opts);
+extern int showleft(const struct opt *opts);
+extern int groupbits(int fd);
+extern int _groupbits(mode_t mode);
+extern int dropopts(struct opt *opts, unsigned int phase);
+extern int dropopts2(struct opt *opts, unsigned int from, unsigned int to);
+
+#endif /* !defined(__xioopts_h_included) */
diff --git a/xioparam.c b/xioparam.c
new file mode 100644
index 0000000..4cbd11d
--- /dev/null
+++ b/xioparam.c
@@ -0,0 +1,67 @@
+/* $Id: xioparam.c,v 1.10 2006/06/19 20:30:24 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for xio options handling */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+/*#include "xioparam.h" are all in xio.h */
+
+/* options that can be applied to this module */
+xioopts_t xioopts = {
+ false, /* strictopts */
+ "!!", /* pipesep */
+ ":", /* paramsep */
+ ",", /* optionsep */
+ ':', /* ip4portsep */
+ ':', /* ip6portsep */
+ '\0', /* logopt */
+ NULL, /* syslogfac */
+ '4', /* default_ip */
+ '4' /* preferred_ip */
+} ;
+
+
+/* allow application to set xioopen options */
+int xiosetopt(char what, const char *arg) {
+ switch (what) {
+ case 's': xioopts.strictopts = true; break;
+ case 'p': if ((xioopts.pipesep = strdup(arg)) == NULL) {
+ Error1("strdup("F_Zu"): out of memory", strlen(arg)+1);
+ return -1;
+ }
+ break;
+ case 'o': xioopts.ip4portsep = arg[0];
+ if (arg[1] != '\0') {
+ Error2("xiosetopt('%c', \"%s\"): port separator must be single character",
+ what, arg);
+ return -1;
+ }
+ break;
+ case 'l': xioopts.logopt = *arg; break;
+ case 'y': xioopts.syslogfac = arg; break;
+ default:
+ Error2("xiosetopt('%c', \"%s\"): unknown option",
+ what, arg?arg:"NULL");
+ return -1;
+ }
+ return 0;
+}
+
+
+int xioinqopt(char what, char *arg, size_t n) {
+ switch (what) {
+ case 's': return xioopts.strictopts;
+ case 'p': strncpy(arg, xioopts.pipesep, n);
+ return 0;
+ case 'o': return xioopts.ip4portsep;
+ case 'l': return xioopts.logopt;
+ default:
+ Error3("xioinqopt('%c', \"%s\", "F_Zu"): unknown option",
+ what, arg, n);
+ return -1;
+ }
+ return 0;
+}
diff --git a/xioread.c b/xioread.c
new file mode 100644
index 0000000..9d8b94d
--- /dev/null
+++ b/xioread.c
@@ -0,0 +1,401 @@
+/* $Id: xioread.c,v 1.38 2007/03/06 21:20:07 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this is the source of the extended read function */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-termios.h"
+#include "xio-socket.h"
+#include "xio-readline.h"
+#include "xio-openssl.h"
+
+
+/* xioread() performs read() or recvfrom()
+ If result is < 0, errno is valid */
+ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
+ ssize_t bytes;
+#if WITH_IP6 && 0
+ int nexthead;
+#endif
+ struct single *pipe;
+ int _errno;
+
+ if (file->tag == XIO_TAG_INVALID) {
+ Error1("xioread(): invalid xiofile descriptor %p", file);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (file->tag == XIO_TAG_DUAL) {
+ pipe = file->dual.stream[0];
+ if (pipe->tag == XIO_TAG_INVALID) {
+ Error1("xioread(): invalid xiofile sub descriptor %p[0]", file);
+ errno = EINVAL;
+ return -1;
+ }
+ } else {
+ pipe = &file->stream;
+ }
+
+ if (pipe->readbytes) {
+ if (pipe->actbytes == 0) {
+ return 0; /* EOF by count */
+ }
+
+ if (pipe->actbytes < bufsiz) {
+ bufsiz = pipe->actbytes;
+ }
+ }
+
+ switch (pipe->dtype & XIODATA_READMASK) {
+ case XIOREAD_STREAM:
+ do {
+ bytes = Read(pipe->fd, buff, bufsiz);
+ } while (bytes < 0 && errno == EINTR);
+ if (bytes < 0) {
+ _errno = errno;
+ switch (_errno) {
+#if 1
+ case EPIPE: case ECONNRESET:
+ Warn4("read(%d, %p, "F_Zu"): %s",
+ pipe->fd, buff, bufsiz, strerror(_errno));
+ break;
+#endif
+ default:
+ Error4("read(%d, %p, "F_Zu"): %s",
+ pipe->fd, buff, bufsiz, strerror(_errno));
+ }
+ errno = _errno;
+ return -1;
+ }
+ break;
+
+ case XIOREAD_PTY:
+ do {
+ bytes = Read(pipe->fd, buff, bufsiz);
+ } while (bytes < 0 && errno == EINTR);
+ if (bytes < 0) {
+ _errno = errno;
+ if (_errno == EIO) {
+ Notice4("read(%d, %p, "F_Zu"): %s (probably PTY closed)",
+ pipe->fd, buff, bufsiz, strerror(_errno));
+ return 0;
+ } else {
+ Error4("read(%d, %p, "F_Zu"): %s",
+ pipe->fd, buff, bufsiz, strerror(_errno));
+ }
+ errno = _errno;
+ return -1;
+ }
+ break;
+
+#if WITH_READLINE
+ case XIOREAD_READLINE:
+ if ((bytes = xioread_readline(pipe, buff, bufsiz)) < 0) {
+ return -1;
+ }
+ break;
+#endif /* WITH_READLINE */
+
+#if WITH_OPENSSL
+ case XIOREAD_OPENSSL:
+ /* this function prints its error messages */
+ if ((bytes = xioread_openssl(pipe, buff, bufsiz)) < 0) {
+ return -1;
+ }
+ break;
+#endif /* WITH_OPENSSL */
+
+#if WITH_SOCKET
+ case XIOREAD_RECV:
+ if (pipe->dtype & XIOREAD_RECV_FROM) {
+#if WITH_RAWIP || WITH_UDP || WITH_UNIX
+ union sockaddr_union from = {{0}};
+ socklen_t fromlen = sizeof(from);
+ char infobuff[256];
+
+ do {
+ bytes =
+ Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen);
+ } while (bytes < 0 && errno == EINTR);
+ if (bytes < 0) {
+ char infobuff[256];
+ _errno = errno;
+ Error6("recvfrom(%d, %p, "F_Zu", 0, %s, {"F_socklen"}): %s",
+ pipe->fd, buff, bufsiz,
+ sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)),
+ fromlen, strerror(errno));
+ errno = _errno;
+ return -1;
+ }
+ Notice2("received packet with "F_Zu" bytes from %s",
+ bytes,
+ sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)));
+ if (bytes == 0) {
+ if (!pipe->para.socket.emptyiseof) {
+ errno = EAGAIN; return -1;
+ }
+ return bytes;
+ }
+
+ if (pipe->peersa.soa.sa_family != PF_UNSPEC) {
+ /* a peer address is defined, so we need to check if it matches */
+#if 0 /* with UNIX sockets we find inconsistent lengths */
+ if (fromlen != pipe->salen) {
+ Info("recvfrom(): wrong peer address length, ignoring packet");
+ errno = EAGAIN; return -1;
+ }
+#endif
+ if (pipe->dtype & XIOREAD_RECV_SKIPIP) {
+ if (pipe->peersa.soa.sa_family != from.soa.sa_family) {
+ Info("recvfrom(): wrong peer protocol, ignoring packet");
+ errno = EAGAIN; return -1;
+ }
+#if WITH_IP4
+ switch (pipe->peersa.soa.sa_family) {
+ case PF_INET:
+ if (pipe->peersa.ip4.sin_addr.s_addr !=
+ from.ip4.sin_addr.s_addr) {
+ Info("recvfrom(): wrong peer address, ignoring packet");
+ errno = EAGAIN; return -1;
+ }
+ break;
+ }
+#endif /* WITH_IP4 */
+ } else {
+ switch (pipe->peersa.soa.sa_family) {
+#if 0
+ case PF_UNIX:
+ if (strncmp(pipe->peersa.un.sun_path, from.un.sun_path,
+ sizeof(from.un.sun_path))) {
+ Info("recvfrom(): wrong peer address, ignoring packet");
+ errno = EAGAIN; return -1;
+ }
+ break;
+#endif
+#if WITH_IP6
+ case PF_INET6:
+ /* e.g. Solaris recvfrom sets a __sin6_src_id component */
+ if (memcmp(&from.ip6.sin6_addr, &pipe->peersa.ip6.sin6_addr,
+ sizeof(from.ip6.sin6_addr)) ||
+ from.ip6.sin6_port != pipe->peersa.ip6.sin6_port) {
+ Info("recvfrom(): wrong peer address, ignoring packet");
+ errno = EAGAIN; return -1;
+ }
+ break;
+#endif /* WITH_IP6 */
+ default:
+ if (memcmp(&from, &pipe->peersa, fromlen)) {
+ Info("recvfrom(): wrong peer address, ignoring packet");
+ errno = EAGAIN; return -1;
+ }
+ }
+ }
+ }
+
+ switch(from.soa.sa_family) {
+ int headlen;
+#if WITH_IP4
+ case AF_INET:
+ if (pipe->dtype & XIOREAD_RECV_SKIPIP) {
+ /* IP4 raw sockets include the header when passing a packet to the
+ application - we don't need it here. */
+#if HAVE_STRUCT_IP_IP_HL
+ headlen = 4*((struct ip *)buff)->ip_hl;
+#else /* happened on Tru64 */
+ headlen = 4*((struct ip *)buff)->ip_vhl;
+#endif
+ if (headlen > bytes) {
+ Warn1("xioread(%d, ...)/IP4: short packet", pipe->fd);
+ bytes = 0;
+ } else {
+ memmove(buff, ((char *)buff)+headlen, bytes-headlen);
+ bytes -= headlen;
+ }
+ }
+ break;
+#endif
+#if WITH_IP6
+ case AF_INET6:
+ /* does not seem to include header on Linux */
+ /* but sometimes on AIX */
+ break;
+#endif
+ default:
+ /* do nothing, for now */
+ break;
+ }
+ if (pipe->dtype & XIOREAD_RECV_ONESHOT) {
+#if 1
+ pipe->eof = 2;
+#else
+ Shutdown(pipe->fd, SHUT_RD);
+#endif
+ if (pipe->ppid > 0) {
+ Kill(pipe->ppid, SIGUSR1);
+ }
+ }
+
+#if 0
+ if (fromlen != pipe->fd[0].salen) {
+ Debug("recvfrom(): wrong peer address length, ignoring packet");
+ continue;
+ }
+ if (memcmp(&from, &pipe->fd[0].peersa.sa, fromlen)) {
+ Debug("recvfrom(): other peer address, ignoring packet");
+ Debug16("peer: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ pipe->fd[0].peersa.space[0],
+ pipe->fd[0].peersa.space[1],
+ pipe->fd[0].peersa.space[2],
+ pipe->fd[0].peersa.space[3],
+ pipe->fd[0].peersa.space[4],
+ pipe->fd[0].peersa.space[5],
+ pipe->fd[0].peersa.space[6],
+ pipe->fd[0].peersa.space[7],
+ pipe->fd[0].peersa.space[8],
+ pipe->fd[0].peersa.space[9],
+ pipe->fd[0].peersa.space[10],
+ pipe->fd[0].peersa.space[11],
+ pipe->fd[0].peersa.space[12],
+ pipe->fd[0].peersa.space[13],
+ pipe->fd[0].peersa.space[14],
+ pipe->fd[0].peersa.space[15]);
+ Debug16("from: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ from.space[0], from.space[1],
+ from.space[2], from.space[3],
+ from.space[4], from.space[5],
+ from.space[6], from.space[7],
+ from.space[8], from.space[9],
+ from.space[10], from.space[11],
+ from.space[12], from.space[13],
+ from.space[14], from.space[15]);
+ continue;
+ }
+#endif
+#else /* !WITH_RAWIP */
+ Fatal("address requires raw sockets, but they are not compiled in");
+ return -1;
+#endif /* !WITH_RAWIP || WITH_UDP || WITH_UNIX */
+
+ } else /* ~XIOREAD_RECV_FROM */ {
+ union sockaddr_union from; socklen_t fromlen = sizeof(from);
+ char infobuff[256];
+
+ socket_init(pipe->para.socket.la.soa.sa_family, &from);
+ /* get source address */
+ if (xiogetpacketsrc(pipe->fd, &from, &fromlen) < 0) {
+ return STAT_RETRYNOW;
+ }
+ if (xiocheckpeer(pipe, &from, &pipe->para.socket.la) < 0) {
+ Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen); /* drop */
+ errno = EAGAIN; return -1;
+ }
+ Info1("permitting packet from %s",
+ sockaddr_info((struct sockaddr *)&from, fromlen,
+ infobuff, sizeof(infobuff)));
+
+ do {
+ bytes =
+ Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen);
+ } while (bytes < 0 && errno == EINTR);
+ if (bytes < 0) {
+ char infobuff[256];
+ _errno = errno;
+ Error6("recvfrom(%d, %p, "F_Zu", 0, %s, "F_socklen"): %s",
+ pipe->fd, buff, bufsiz,
+ sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)),
+ fromlen, strerror(errno));
+ errno = _errno;
+ return -1;
+ }
+ Notice2("received packet with "F_Zu" bytes from %s",
+ bytes,
+ sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)));
+ if (bytes == 0) {
+ if (!pipe->para.socket.emptyiseof) {
+ errno = EAGAIN; return -1;
+ }
+ return bytes;
+ }
+
+ switch(from.soa.sa_family) {
+ int headlen;
+#if WITH_IP4
+ case AF_INET:
+ if (pipe->dtype & XIOREAD_RECV_SKIPIP) {
+ /* IP4 raw sockets include the header when passing a packet to the
+ application - we don't need it here. */
+#if HAVE_STRUCT_IP_IP_HL
+ headlen = 4*((struct ip *)buff)->ip_hl;
+#else /* happened on Tru64 */
+ headlen = 4*((struct ip *)buff)->ip_vhl;
+#endif
+ if (headlen > bytes) {
+ Warn1("xioread(%d, ...)/IP4: short packet", pipe->fd);
+ bytes = 0;
+ } else {
+ memmove(buff, ((char *)buff)+headlen, bytes-headlen);
+ bytes -= headlen;
+ }
+ }
+ break;
+#endif
+#if WITH_IP6
+ case AF_INET6: /* does not seem to include header... */
+ break;
+#endif
+ default:
+ /* do nothing, for now */
+ break;
+ }
+
+ }
+ break;
+#endif /* WITH_SOCKET */
+
+ default:
+ Error("internal: undefined read operation");
+ errno = EINVAL; return -1;
+ }
+ pipe->actbytes -= bytes;
+ return bytes;
+}
+
+
+/* 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.
+*/
+ssize_t xiopending(xiofile_t *file) {
+ struct single *pipe;
+
+ if (file->tag == XIO_TAG_INVALID) {
+ Error1("xiopending(): invalid xiofile descriptor %p", file);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (file->tag == XIO_TAG_DUAL) {
+ pipe = file->dual.stream[0];
+ if (pipe->tag == XIO_TAG_INVALID) {
+ Error1("xiopending(): invalid xiofile sub descriptor %p[0]", file);
+ errno = EINVAL;
+ return -1;
+ }
+ } else {
+ pipe = &file->stream;
+ }
+
+ switch (pipe->dtype & XIODATA_READMASK) {
+#if WITH_OPENSSL
+ case XIOREAD_OPENSSL:
+ return xiopending_openssl(pipe);
+#endif /* WITH_OPENSSL */
+ default:
+ return 0;
+ }
+}
+
diff --git a/xioshutdown.c b/xioshutdown.c
new file mode 100644
index 0000000..8e2ddb9
--- /dev/null
+++ b/xioshutdown.c
@@ -0,0 +1,134 @@
+/* $Id: xioshutdown.c,v 1.21 2007/01/25 21:36:11 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this is the source of the extended shutdown function */
+
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+static pid_t socat_kill_pid; /* here we pass the pid to be killed in sighandler */
+
+static void signal_kill_pid(int dummy) {
+ Notice("SIGALRM while waiting for w/o child process to die, killing it now");
+ Kill(socat_kill_pid, SIGTERM);
+}
+
+int xioshutdown(xiofile_t *sock, int how) {
+ int result = 0;
+
+ if (sock->tag == XIO_TAG_INVALID) {
+ Error("xioshutdown(): invalid file descriptor");
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (sock->tag == XIO_TAG_DUAL) {
+ if ((how+1)&1) {
+ result = xioshutdown((xiofile_t *)sock->dual.stream[0], 0);
+ }
+ if ((how+1)&2) {
+ result |= xioshutdown((xiofile_t *)sock->dual.stream[1], 1);
+ }
+
+#if WITH_OPENSSL
+ } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_OPENSSL) {
+ sycSSL_shutdown (sock->stream.para.openssl.ssl);
+ /*! what about half/full close? */
+#endif /* WITH_OPENSSL */
+
+ } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_PIPE) {
+ if ((how+1)&1) {
+ if (Close(sock->stream.fd) < 0) {
+ Info2("close(%d): %s",
+ sock->stream.fd, strerror(errno));
+ }
+ }
+ if ((how+1)&2) {
+ if (Close(sock->stream.para.bipipe.fdout) < 0) {
+ Info2("close(%d): %s",
+ sock->stream.para.bipipe.fdout, strerror(errno));
+ }
+ }
+
+ } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_2PIPE) {
+ if ((how+1)&1) {
+ if (Close(sock->stream.fd) < 0) {
+ Info2("close(%d): %s",
+ sock->stream.fd, strerror(errno));
+ }
+ }
+ if ((how+1)&2) {
+ if (Close(sock->stream.para.exec.fdout) < 0) {
+ Info2("close(%d): %s",
+ sock->stream.para.exec.fdout, strerror(errno));
+ }
+ }
+#if WITH_SOCKET
+ } else if (sock->stream.howtoend == END_SHUTDOWN) {
+ if ((result = Shutdown(sock->stream.fd, how)) < 0) {
+ Info3("shutdown(%d, %d): %s",
+ sock->stream.fd, how, strerror(errno));
+ }
+ } else if (sock->stream.howtoend == END_SHUTDOWN_KILL) {
+ if ((result = Shutdown(sock->stream.fd, how)) < 0) {
+ Info3("shutdown(%d, %d): %s",
+ sock->stream.fd, how, strerror(errno));
+ }
+ if ((sock->stream.flags&XIO_ACCMODE) == XIO_WRONLY) {
+ /* the child process might want to flush some data before terminating
+ */
+ int status = 0;
+
+ /* we wait for the child process to die, but to prevent timeout
+ we raise an alarm after some time.
+ NOTE: the alarm does not terminate waitpid() on Linux/glibc (BUG?),
+ therefore we have to do the kill in the signal handler */
+ Signal(SIGALRM, signal_kill_pid);
+ socat_kill_pid = sock->stream.para.exec.pid;
+#if HAVE_SETITIMER
+ /*! with next feature release, we get usec resolution and an option */
+#else
+ Alarm(1 /*! sock->stream.para.exec.waitdie */);
+#endif /* !HAVE_SETITIMER */
+ if (Waitpid(sock->stream.para.exec.pid, &status, 0) < 0) {
+ Warn3("waitpid("F_pid", %p, 0): %s",
+ sock->stream.para.exec.pid, &status, strerror(errno));
+ }
+ Alarm(0);
+ }
+ } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_RECVFROM) {
+ if (how >= 1) {
+ if (Close(sock->stream.fd) < 0) {
+ Info2("close(%d): %s",
+ sock->stream.fd, strerror(errno));
+ }
+ sock->stream.eof = 2;
+ sock->stream.fd = -1;
+ }
+#endif /* WITH_SOCKET */
+#if 0
+ } else {
+ Error1("xioshutdown(): bad data type specification %d", sock->stream.dtype);
+ return -1;
+#endif
+
+ }
+#if 0
+ else if (sock->stream.howtoend == END_CLOSE &&
+ sock->stream.dtype == DATA_STREAM) {
+ return result;
+ }
+#if WITH_TERMIOS
+ if (sock->stream.ttyvalid) {
+ if (Tcsetattr(sock->stream.fd, 0, &sock->stream.savetty) < 0) {
+ Warn2("cannot restore terminal settings on fd %d: %s",
+ sock->stream.fd, strerror(errno));
+ }
+ }
+#endif /* WITH_TERMIOS */
+#endif
+
+ return result;
+}
diff --git a/xiosigchld.c b/xiosigchld.c
new file mode 100644
index 0000000..39c03f9
--- /dev/null
+++ b/xiosigchld.c
@@ -0,0 +1,159 @@
+/* $Id: xiosigchld.c,v 1.21 2006/12/28 14:38:38 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2006 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this is the source of the extended child signal handler */
+
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+
+/*!! with socat, at most 4 exec children exist */
+pid_t diedunknown1; /* child died before it is registered */
+pid_t diedunknown2;
+pid_t diedunknown3;
+pid_t diedunknown4;
+
+
+/* register for a xio filedescriptor a callback (handler).
+ when a SIGCHLD occurs, the signal handler will ??? */
+int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *)) {
+ if (xfd->tag != XIO_TAG_DUAL) {
+ xfd->stream.sigchild = callback;
+ } else {
+ xfd->dual.stream[0]->sigchild = callback;
+ xfd->dual.stream[1]->sigchild = callback;
+ }
+ return 0;
+}
+
+/* exec'd child has died, perform appropriate changes to descriptor */
+static int sigchld_stream(struct single *file) {
+ /*!! call back to application */
+ file->para.exec.pid = 0;
+ if (file->sigchild) {
+ return (*file->sigchild)(file);
+ }
+ return 0;
+}
+
+/* return 0 if socket is not responsible for deadchild */
+static int xio_checkchild(xiofile_t *socket, int socknum, pid_t deadchild) {
+ int retval;
+ if (socket != NULL) {
+ if (socket->tag != XIO_TAG_DUAL) {
+ if ((socket->stream.howtoend == END_KILL ||
+ socket->stream.howtoend == END_CLOSE_KILL ||
+ socket->stream.howtoend == END_SHUTDOWN_KILL) &&
+ socket->stream.para.exec.pid == deadchild) {
+ Info2("exec'd process %d on socket %d terminated",
+ socket->stream.para.exec.pid, socknum);
+ sigchld_stream(&socket->stream);
+ return 1;
+ }
+ } else {
+ if (retval = xio_checkchild((xiofile_t *)socket->dual.stream[0], socknum, deadchild))
+ return retval;
+ else
+ return xio_checkchild((xiofile_t *)socket->dual.stream[1], socknum, deadchild);
+ }
+ }
+ return 0;
+}
+
+/* this is the "physical" signal handler for SIGCHLD */
+/* the current socat/xio implementation knows two kinds of children:
+ exec/system addresses perform a fork: these children are registered and
+ there death influences the parents flow;
+ listen-socket with fork children: these children are "anonymous" and their
+ death does not affect the parent process (now; maybe we have a child
+ process counter later) */
+void childdied(int signum) {
+ pid_t pid;
+ int _errno;
+ int status = 0;
+ bool wassig = false;
+ int i;
+
+ _errno = errno; /* save current value; e.g., select() on Cygwin seems
+ to set it to EINTR _before_ handling the signal, and
+ then passes the value left by the signal handler to
+ the caller of select(), accept() etc. */
+ /* is not thread/signal save, but confused messages in rare cases are better
+ than no messages at all */
+ Info1("childdied(signum=%d)", signum);
+ 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;
+ }
+ /*! indent */
+ /* check if it was a registered child process */
+ i = 0;
+ while (i < XIO_MAXSOCK) {
+ if (xio_checkchild(sock[i], i, pid)) break;
+ ++i;
+ }
+ if (i == XIO_MAXSOCK) {
+ Info2("childdied(%d): cannot identify child %d", signum, pid);
+ if (diedunknown1 == 0) {
+ diedunknown1 = pid;
+ Debug("saving pid in diedunknown1");
+ } else if (diedunknown2 == 0) {
+ diedunknown2 = pid;
+ Debug("saving pid in diedunknown2");
+ } else if (diedunknown3 == 0) {
+ diedunknown3 = pid;
+ Debug("saving pid in diedunknown3");
+ } else {
+ diedunknown4 = pid;
+ Debug("saving pid in diedunknown4");
+ }
+ }
+
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) == 0) {
+ Info2("waitpid(): child %d exited with status %d",
+ pid, WEXITSTATUS(status));
+ } else {
+ Warn2("waitpid(): child %d exited with status %d",
+ pid, WEXITSTATUS(status));
+ }
+ } else if (WIFSIGNALED(status)) {
+ Info2("waitpid(): child %d exited on signal %d",
+ pid, WTERMSIG(status));
+ } else if (WIFSTOPPED(status)) {
+ Info2("waitpid(): child %d stopped on signal %d",
+ pid, WSTOPSIG(status));
+ } else {
+ Warn1("waitpid(): cannot determine status of child %d", pid);
+ }
+
+#if !HAVE_SIGACTION
+ /* we might need to re-register our handler */
+ if (Signal(SIGCHLD, childdied) == SIG_ERR) {
+ Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
+ }
+#endif /* !HAVE_SIGACTION */
+ } while (1);
+ Info("childdied() finished");
+ errno = _errno;
+}
diff --git a/xiosignal.c b/xiosignal.c
new file mode 100644
index 0000000..405ff98
--- /dev/null
+++ b/xiosignal.c
@@ -0,0 +1,107 @@
+/* $Id: xiosignal.c,v 1.2 2003/12/23 21:22:38 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2003 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains code for handling signals (except SIGCHLD) */
+
+#include "config.h"
+#include "xioconfig.h" /* what features are enabled */
+
+#include "sysincludes.h"
+
+#include "mytypes.h"
+#include "compat.h"
+#include "error.h"
+
+#include "sycls.h"
+
+
+#define SOCAT_MAXPIDS 4
+
+struct socat_sig_desc {
+ int sig_use;
+ pid_t sig_pids[SOCAT_MAXPIDS];
+} ;
+
+#if 0
+size_t socat_sigint_use; /* how many pids are set in following array */
+static pid_t socat_sigint_pids[SOCAT_MAXPIDS];
+size_t socat_sigquit_use; /* how many pids are set in following array */
+static pid_t socat_sigquit_pids[SOCAT_MAXPIDS];
+#else
+static struct socat_sig_desc socat_sighup;
+static struct socat_sig_desc socat_sigint;
+static struct socat_sig_desc socat_sigquit;
+#endif
+
+
+static struct socat_sig_desc *socat_get_sig_desc(int signum) {
+ struct socat_sig_desc *sigdesc;
+ switch (signum) {
+ case SIGHUP: sigdesc = &socat_sighup; break;
+ case SIGINT: sigdesc = &socat_sigint; break;
+ case SIGQUIT: sigdesc = &socat_sigquit; break;
+ default: sigdesc = NULL; break;
+ }
+ return sigdesc;
+}
+
+/* a signal handler that eventually passes the signal to sub processes */
+void socatsignalpass(int sig) {
+ int i;
+ struct socat_sig_desc *sigdesc;
+
+ Debug1("socatsignalpass(%d)", sig);
+ if ((sigdesc = socat_get_sig_desc(sig)) == NULL) {
+ return;
+ }
+
+ for (i=0; i<sigdesc->sig_use; ++i) {
+ if (sigdesc->sig_pids[i]) {
+ if (Kill(sigdesc->sig_pids[i], sig) < 0) {
+ Warn3("kill("F_pid", %d): %s",
+ sigdesc->sig_pids[i], sig, strerror(errno));
+ }
+ }
+ }
+#if !HAVE_SIGACTION
+ Signal(sig, socatsignalpass);
+#endif /* !HAVE_SIGACTION */
+ Debug("socatsignalpass() ->");
+}
+
+
+/* register the sub process pid for passing of signals of type signum.
+ Only for SIGHUP, SIGINT, and SIGQUIT!
+ returns 0 on success or <0 if an error occurred */
+int xio_opt_signal(pid_t pid, int signum) {
+ struct socat_sig_desc *sigdesc;
+
+ if ((sigdesc = socat_get_sig_desc(signum)) == NULL) {
+ Error("sub process registered for unsupported signal");
+ return -1;
+ }
+
+ if (sigdesc->sig_use >= SOCAT_MAXPIDS) {
+ Error1("too many sub processes registered for signal %d", signum);
+ return -1;
+ }
+ if (sigdesc->sig_use == 0) {
+ /* the special signal handler has not been registered yet - do it now */
+#if HAVE_SIGACTION
+ struct sigaction act;
+ memset(&act, 0, sizeof(struct sigaction));
+ act.sa_flags = SA_RESTART;
+ act.sa_handler = socatsignalpass;
+ if (Sigaction(signum, &act, NULL) < 0) {
+ /*! man does not say that errno is defined */
+ Warn3("sigaction(%d, %p, NULL): %s", signum, &act, strerror(errno));
+ }
+#else
+ Signal(signum, socatsignalpass);
+#endif /* !HAVE_SIGACTION */
+ }
+ sigdesc->sig_pids[sigdesc->sig_use++] = pid;
+ return 0;
+}
+
diff --git a/xiosysincludes.h b/xiosysincludes.h
new file mode 100644
index 0000000..e30ef13
--- /dev/null
+++ b/xiosysincludes.h
@@ -0,0 +1,13 @@
+/* $Id: xiosysincludes.h,v 1.4 2001/12/27 16:52:34 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xiosysincludes_h_included
+#define __xiosysincludes_h_included 1
+
+#include "config.h"
+#include "xioconfig.h" /* what features are enabled */
+
+#include "sysincludes.h"
+
+#endif /* !defined(__xiosysincludes_h_included) */
diff --git a/xiowrite.c b/xiowrite.c
new file mode 100644
index 0000000..d5e0cce
--- /dev/null
+++ b/xiowrite.c
@@ -0,0 +1,168 @@
+/* $Id: xiowrite.c,v 1.29 2007/02/08 18:27:00 gerhard Exp $ */
+/* Copyright Gerhard Rieger 2001-2007 */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this is the source of the extended write function */
+
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-readline.h"
+#include "xio-openssl.h"
+
+
+/* ...
+ 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.
+ 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;
+ struct single *pipe;
+ int _errno;
+
+ if (file->tag == XIO_TAG_INVALID) {
+ Error1("xiowrite(): invalid xiofile descriptor %p", file);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (file->tag == XIO_TAG_DUAL) {
+ pipe = file->dual.stream[1];
+ if (pipe->tag == XIO_TAG_INVALID) {
+ Error1("xiowrite(): invalid xiofile sub descriptor %p[1]", file);
+ errno = EINVAL;
+ return -1;
+ }
+ } else {
+ pipe = &file->stream;
+ }
+
+#if WITH_READLINE
+ /* try to extract a prompt from the write data */
+ if ((pipe->dtype & XIODATA_READMASK) == XIOREAD_READLINE) {
+ xioscan_readline(pipe, buff, bytes);
+ }
+#endif /* WITH_READLINE */
+
+ switch (pipe->dtype & XIODATA_WRITEMASK) {
+
+ case XIOWRITE_STREAM:
+ do {
+ writt = Write(pipe->fd, buff, bytes);
+ } while (writt < 0 && errno == EINTR);
+ if (writt < 0) {
+ _errno = errno;
+ switch (_errno) {
+ case EPIPE:
+ case ECONNRESET:
+ if (pipe->cool_write) {
+ Notice4("write(%d, %p, "F_Zu"): %s",
+ pipe->fd, buff, bytes, strerror(_errno));
+ break;
+ }
+ /*PASSTRHOUGH*/
+ default:
+ Error4("write(%d, %p, "F_Zu"): %s",
+ pipe->fd, buff, bytes, strerror(_errno));
+ }
+ errno = _errno;
+ return -1;
+ }
+ if ((size_t)writt < bytes) {
+ Warn2("write() only wrote "F_Zu" of "F_Zu" bytes",
+ writt, bytes);
+ }
+ break;
+
+#if WITH_SOCKET
+ case XIOWRITE_SENDTO:
+ /*union {
+ char space[sizeof(struct sockaddr_un)];
+ struct sockaddr sa;
+ } from;*/
+ /*socklen_t fromlen;*/
+
+ do {
+ writt = Sendto(pipe->fd, buff, bytes, 0,
+ &pipe->peersa.soa, pipe->salen);
+ } while (writt < 0 && errno == EINTR);
+ if (writt < 0) {
+ char infobuff[256];
+ _errno = errno;
+ Error6("sendto(%d, %p, "F_Zu", 0, %s, "F_socklen"): %s",
+ pipe->fd, buff, bytes,
+ sockaddr_info(&pipe->peersa.soa, pipe->salen,
+ infobuff, sizeof(infobuff)),
+ pipe->salen, strerror(_errno));
+ errno = _errno;
+ return -1;
+ }
+ if ((size_t)writt < bytes) {
+ char infobuff[256];
+ Warn7("sendto(%d, %p, "F_Zu", 0, %s, "F_socklen") only wrote "F_Zu" of "F_Zu" bytes",
+ pipe->fd, buff, bytes,
+ sockaddr_info(&pipe->peersa.soa, pipe->salen,
+ infobuff, sizeof(infobuff)),
+ pipe->salen, writt, bytes);
+ } else {
+ }
+ {
+ char infobuff[256];
+ union sockaddr_union us;
+ socklen_t uslen = sizeof(us);
+ Getsockname(pipe->fd, &us.soa, &uslen);
+ Notice1("local address: %s",
+ sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)));
+ }
+ break;
+#endif /* WITH_SOCKET */
+
+ case XIOWRITE_PIPE:
+ do {
+ writt = Write(pipe->para.bipipe.fdout, buff, bytes);
+ } while (writt < 0 && errno == EINTR);
+ _errno = errno;
+ if (writt < 0) {
+ Error4("write(%d, %p, "F_Zu"): %s",
+ pipe->para.bipipe.fdout, buff, bytes, strerror(_errno));
+ errno = _errno;
+ return -1;
+ }
+ if ((size_t)writt < bytes) {
+ Warn2("write() only wrote "F_Zu" of "F_Zu" bytes",
+ writt, bytes);
+ }
+ break;
+
+ case XIOWRITE_2PIPE:
+ do {
+ writt = Write(pipe->para.exec.fdout, buff, bytes);
+ } while (writt < 0 && errno == EINTR);
+ _errno = errno;
+ if (writt < 0) {
+ Error4("write(%d, %p, "F_Zu"): %s",
+ pipe->para.exec.fdout, buff, bytes, strerror(_errno));
+ errno = _errno;
+ return -1;
+ }
+ if ((size_t)writt < bytes) {
+ Warn2("write() only processed "F_Zu" of "F_Zu" bytes",
+ writt, bytes);
+ }
+ break;
+
+#if WITH_OPENSSL
+ case XIOWRITE_OPENSSL:
+ /* this function prints its own error messages */
+ return xiowrite_openssl(pipe, buff, bytes);
+#endif /* WITH_OPENSSL */
+
+ default:
+ Error1("xiowrite(): bad data type specification %d", pipe->dtype);
+ errno = EINVAL;
+ return -1;
+ }
+ return writt;
+}