Compare commits

...

102 Commits

Author SHA1 Message Date
Travis Burtrum 268432bf42 Add OpenSSL snihost option for TLS SNI extension 2015-07-17 22:08:00 -04:00
Gerhard Rieger 8fda559e8d version 1.7.3.0 2015-01-24 18:40:49 +01:00
Gerhard Rieger b6541b4de7 Final fixes before release 1.7.3.0 2015-01-24 18:40:03 +01:00
Gerhard Rieger 053c4565b3 Added OpenSSL server side EDHCE cipher support 2015-01-23 21:35:55 +01:00
Gerhard Rieger c65a1c9791 Function cfmakeraw() is simulated when missing 2015-01-23 21:34:14 +01:00
Gerhard Rieger f0c3b1f387 Port to Openindiana 2015-01-23 21:31:08 +01:00
Gerhard Rieger 81c4892599 Function cfmakeraw() is simulated when missing 2015-01-23 21:30:38 +01:00
Gerhard Rieger 3f63c9889f minor corrections to docu and test.sh 2015-01-23 18:46:54 +01:00
Gerhard Rieger f0abfc19fd environ variable from C runtime is not declared on all systems 2015-01-23 18:46:54 +01:00
Gerhard Rieger f749f5c3e4 Red Hat issue: socat 1.7.2.4 build failure missing linux/errqueue.h 2015-01-23 18:46:04 +01:00
Gerhard Rieger 59658d8267 Include netinet/if_ether.h on Illumos 2015-01-23 18:41:04 +01:00
Gerhard Rieger 05c0b2873e Support for NetBSD 5.1 2015-01-23 18:41:04 +01:00
Gerhard Rieger fb0246084a Prevent multiple definition of bool,Min(),Max() (MacOS X) 2015-01-23 18:41:04 +01:00
Gerhard Rieger 4228399da0 Actual spec file 2015-01-23 18:41:04 +01:00
Gerhard Rieger 3ee5ac5275 Debian Bug 764251: Set the build timestamp to a deterministic time 2015-01-23 18:41:04 +01:00
Gerhard Rieger 6f6d7ccb86 Revert gcc check to reenable cross compiling 2015-01-23 18:41:04 +01:00
Gerhard Rieger 522bb45479 Added option rawer for pty 2015-01-23 18:40:54 +01:00
Gerhard Rieger 8c8f817780 Print error on useless fdout,fdin options 2015-01-23 18:38:48 +01:00
Gerhard Rieger 2b99929bfc Corrected help text for filan -L 2015-01-23 18:38:42 +01:00
Gerhard Rieger ca872c9a9f Fixed memory leaks 2015-01-23 18:38:37 +01:00
Gerhard Rieger 281d1bd651 FIPS requires 1024 bit DH prime 2015-01-23 18:38:28 +01:00
Gerhard Rieger d430147bc6 Added TLS methods support 2015-01-23 18:38:06 +01:00
Gerhard Rieger 899bc6845d Red Hat issue 1019972: needs to specify OpenSSL cipher suites 2015-01-12 23:43:23 +01:00
Gerhard Rieger d4c44ff649 Red Hat issue 1019964: socat now uses the system certificate store 2015-01-12 23:39:57 +01:00
Gerhard Rieger 9e863458c6 Generate testcert.conf and testcert6.conf in test.sh 2015-01-12 23:36:01 +01:00
Gerhard Rieger 2f40a439cb Check OpenSSL peers commonName+subjectAltName; new option openssl-commonname 2015-01-12 23:34:47 +01:00
Gerhard Rieger 05afec429d OpenSSL peer certificate subject,issuer details are passed to env 2015-01-12 23:11:26 +01:00
Gerhard Rieger cf3f6403bc Corrected some configure --disable 2015-01-12 22:30:28 +01:00
Gerhard Rieger 59a11f2efb Include <poll.h> instead of <sys/poll.h> 2015-01-12 22:22:38 +01:00
Gerhard Rieger ad524a56b7 Passive addresses like TCP-LISTEN with empty port bound to random 2015-01-12 22:21:36 +01:00
Gerhard Rieger 0ab324b173 Address SYSTEM, when terminating, shutted down its parent addresses 2015-01-12 22:20:35 +01:00
Gerhard Rieger 466cb7921c Option ignoreeof on the right address hung 2015-01-12 22:19:01 +01:00
Gerhard Rieger 0219d6ac27 Fixed return value of nestlex() 2015-01-12 21:57:51 +01:00
Gerhard Rieger 98028900e0 Fixed bind with abstract unix domain sockets (Linux) 2015-01-12 21:54:26 +01:00
Gerhard Rieger 2af0495cc6 Made code async-signal-safe 2015-01-12 21:46:16 +01:00
Gerhard Rieger e4c6f3d934 version 1.7.2.4 2014-03-09 22:08:59 +01:00
Gerhard Rieger 80c7fa0bca struct cmsghdr.cmsg is system dependend; more print format corrections 2014-03-09 22:08:19 +01:00
Gerhard Rieger 93cfe88290 autoconf now prefers configure.ac over configure.in 2014-03-09 15:50:19 +01:00
Gerhard Rieger 8371aa3dc0 linux/errqueue.h may require linux/types.h 2014-03-09 15:47:56 +01:00
Gerhard Rieger 9585312903 The check for fips.h requires stddef.h 2014-03-02 20:14:04 +01:00
Gerhard Rieger bc38f04072 Android build script with pty code 2014-03-02 20:11:06 +01:00
Gerhard Rieger 133c180fb1 long long supported for time_t, socklen_t and a few other libc types 2014-03-02 20:03:55 +01:00
Gerhard Rieger fbb521e45e Red Hat issue 1020203: configure checks fail with some compilers 2014-03-02 20:00:25 +01:00
Gerhard Rieger cf39583b25 Red Hat issue 1021948: snprintf API change 2014-03-02 18:35:54 +01:00
Gerhard Rieger 52e8a5ec2b Red Hat issue 1021429: getgroupent fails with large number of groups 2014-03-02 18:34:58 +01:00
Gerhard Rieger ab74be65e5 some file system bases addresses failed to apply file options 2014-03-02 18:15:52 +01:00
Gerhard Rieger a793c8047e fixed some typos and minor issues, including Red Hat issue 1021967 2014-03-02 17:43:23 +01:00
Gerhard Rieger dfdeaa4836 Red Hat issue 1022070: missing length check in xiolog_ancillary_socket() 2014-03-02 17:36:20 +01:00
Gerhard Rieger 04ad6d5275 Red Hat issue 1022063: out-of-range shifts on net mask bits 2014-03-02 17:35:34 +01:00
Gerhard Rieger 2e17542be7 Red Hat issue 1022062: strcpy misuse in xiosetsockaddrenv_ip4() 2014-03-02 17:30:43 +01:00
Gerhard Rieger 520e84aba7 Red Hat issue 1022048: strncpy hardening 2014-03-02 17:29:53 +01:00
Gerhard Rieger 82231ad799 Red Hat issue 1021972: fixed a missing NUL termination in return string of sysutils.c:sockaddr_info() for the AF_UNIX case 2014-03-02 17:24:57 +01:00
Gerhard Rieger a214cbca6f Red Hat issue 1021958: fixed a bug with faulty buffer/data length calculation in xio-ascii.c:_xiodump() 2014-03-02 17:24:32 +01:00
Gerhard Rieger bf17d38dab On big endian platforms with type long >32bit the range option applied a bad base address 2014-03-02 16:57:11 +01:00
Gerhard Rieger 0fad8877fd Changed some variable definitions to make gcc -O2 aliasing checker happy 2014-03-02 16:56:12 +01:00
Gerhard Rieger 257834e501 OPENSSL-CONNECT with bind option failed on some systems with Invalid argument 2014-03-02 16:53:30 +01:00
Gerhard Rieger 1898116eca Increased field width for ulimit values from 16 to 24 digits 2014-03-02 16:51:50 +01:00
Gerhard Rieger 5e63eff878 In xioshutdown() a wrong branch was chosen after RECVFROM type addresses 2014-03-02 16:49:24 +01:00
Gerhard Rieger b732d00d30 configure checked for --disable-rawsocket but printed --disable-genericsocket 2014-03-02 16:46:00 +01:00
Gerhard Rieger 91b00e8c44 LISTEN based addresses applied some address options to the listening FD instead of the connected FD 2014-03-02 16:42:08 +01:00
Gerhard Rieger 4d013105ea make failed after configure with non gcc compiler due to missing include 2014-03-02 16:38:42 +01:00
Gerhard Rieger b6deb56a14 libwrap only logs to syslog; actual COPYING file 2014-03-02 16:37:11 +01:00
Gerhard Rieger 0978ada95e improved test.sh script 2014-02-26 18:19:37 +01:00
Gerhard Rieger 77a9c7ae10 performed changes for Fedora release 19 2014-02-09 17:55:06 +01:00
Gerhard Rieger 7a348bdfd5 version 1.7.2.3 - CVE-2014-0019: fixed PROXY-CONNECT address overflow 2014-01-25 17:44:55 +01:00
Gerhard Rieger 022f0a46e6 version 1.7.2.2 - fixed FD leak in accept() loop 2013-03-25 20:42:58 +01:00
Gerhard Rieger 464d23a34f version 1.7.2.1 - fixed READLINE buffer overflow 2012-04-24 07:30:01 +02:00
Gerhard Rieger 42ef3f4645 version 1.7.2.0 2011-12-05 22:28:49 +01:00
Gerhard Rieger 97db9bce50 corrected some message formats 2011-12-04 20:51:31 +01:00
Gerhard Rieger 4c9898446d Ubuntu Oneiric: OpenSSL w/o SSLv2, bsd/libutil.h, unused vars 2011-12-04 15:14:34 +01:00
Gerhard Rieger 76291f6a67 corrections to test.sh 2011-12-04 14:44:00 +01:00
Gerhard Rieger abb25c1427 improved dev_t print format definition 2011-11-27 11:37:32 +01:00
Gerhard Rieger eccce7542e corrected check for net/if.h 2011-11-27 11:03:56 +01:00
Gerhard Rieger 1c302dc23c dropopts must not free() 2011-11-27 10:49:28 +01:00
Gerhard Rieger 3ef7b3e366 port to Dragonfly 2011-11-26 14:56:19 +01:00
Gerhard Rieger 490a01d245 typos in docu and source 2011-11-26 14:49:51 +01:00
Gerhard Rieger 7e3386f228 OpenSSL option compress allows to disable compression 2011-11-26 14:27:02 +01:00
Gerhard Rieger 9e0c4e1df5 allow tun/tap specification without IP address 2011-11-26 14:25:27 +01:00
Gerhard Rieger 02f3b29ab6 new option max-children that limits the number of concurrent child processes 2011-11-26 14:24:09 +01:00
Gerhard Rieger 6cefd1941e UDP-LISTEN need not sleep 2011-11-26 14:09:02 +01:00
Gerhard Rieger a593b09df6 test.sh: corrected ancilliary messages with timestamps 2011-11-26 14:05:55 +01:00
Gerhard Rieger b579f27765 minor corrections to docu and test.sh resulting from local compilation on Openmoko SHR 2011-11-22 13:57:46 +01:00
Gerhard Rieger d2fab02571 corrections for OpenEmbedded, especially termios SHIFT values andISPEED/OSPEED 2011-11-22 13:47:58 +01:00
Gerhard Rieger 98abed1abd fixed compiler warnings on Mac OS X 64bit 2011-11-22 13:37:23 +01:00
Gerhard Rieger b4b7ffc732 check if define __APPLE_USE_RFC_2292 helps to enable IPV6_* 2011-11-22 13:20:02 +01:00
Gerhard Rieger baa16a52a6 check for defines IPV6_* 2011-11-22 13:11:51 +01:00
Gerhard Rieger 0cf1e34018 port to RHEL6 - fips.h 2011-11-22 12:48:22 +01:00
Gerhard Rieger 7a3ed71270 port to Cygwin - struct pktinfo.ipi_spec_dst 2011-11-22 11:24:35 +01:00
Gerhard Rieger 26801266f2 port to Android 2011-11-22 10:58:15 +01:00
Gerhard Rieger 0b472d59d2 OPENSSL-LISTEN failed with "no shared cipher" when using cipher aNULL 2011-11-22 10:42:38 +01:00
Gerhard Rieger 49c0505298 fixed sporadic data loss on pid reuse 2011-11-19 10:43:50 +01:00
Gerhard Rieger 976d6f0b75 fixed bug that could freeze socat during signal handling 2011-11-10 09:09:04 +01:00
Gerhard Rieger 6a8f6c0734 handle partial write()'s without data loss 2011-10-09 09:18:31 +02:00
Gerhard Rieger 3881c794a7 unnamed unix domain socket could generate invalid log output or lead to a process crash 2011-10-08 11:10:58 +02:00
Gerhard Rieger b8d16ecd51 issue error when PTY called with parameters 2011-03-10 07:55:03 +01:00
Gerhard Rieger aae035c5b9 option -x prints info about packet 2010-12-08 10:58:25 +01:00
Gerhard Rieger 06179edeb6 address option ioctl-intp failed with "unimplemented type 26" 2010-10-05 09:11:47 +02:00
Gerhard Rieger 290b62c817 TCP-CONNECT with option nonblock reported successful connect even when it was still pending 2010-10-05 07:35:02 +02:00
Gerhard Rieger e0d548df71 UNIX-CONNECT did not support half-close 2010-10-04 00:18:13 +02:00
Gerhard Rieger 2e385902c0 UDP-LISTEN would alway set SO_REUSEADDR even without fork option and when user set it to 0 2010-10-03 16:38:04 +02:00
Gerhard Rieger cb913fbc0c when UNIX-LISTEN was applied to an existing file it failed as expected but removed the file 2010-10-03 16:28:06 +02:00
Gerhard Rieger 4c3d1ca49d fixed a bug where socat might crash when connecting to a unix domain socket using address GOPEN 2010-10-03 15:46:10 +02:00
83 changed files with 7899 additions and 1868 deletions

395
CHANGES
View File

@ -1,7 +1,397 @@
####################### V 1.7.3.0:
security:
(CVE Id pending)
Fixed problems with signal handling caused by use of not async signal
safe functions in signal handlers that could freeze socat, allowing
denial of service attacks.
Many changes in signal handling and the diagnostic messages system were
applied to make the code async signal safe but still provide detailled
logging from signal handlers:
Coded function vsnprintf_r() as async signal safe incomplete substitute
of libc vsnprintf()
Coded function snprinterr() to replace %m in strings with a system error
message
Instead of gettimeofday() use clock_gettime() when available
Pass Diagnostic messages from signal handler per unix socket to the main
program flow
Use sigaction() instead of signal() for better control
Turn off nested signal handler invocations
Thanks to Peter Lobsinger for reporting and explaining this issue.
Red Hat issue 1019975: add TLS host name checks
OpenSSL client checks if the server certificates names in
extensions/subjectAltName/DNS or in subject/commonName match the name
used to connect or the value of the openssl-commonname option.
Test: OPENSSL_CN_CLIENT_SECURITY
OpenSSL server checks if the client certificates names in
extensions/subjectAltNames/DNS or subject/commonName match the value of
the openssl-commonname option when it is used.
Test: OPENSSL_CN_SERVER_SECURITY
Red Hat issue 1019964: socat now uses the system certificate store with
OPENSSL when neither options cafile nor capath are used
Red Hat issue 1019972: needs to specify OpenSSL cipher suites
Default cipherlist is now "HIGH:-NULL:-PSK:-aNULL" instead of empty to
prevent downgrade attacks
new features:
OpenSSL addresses set couple of environment variables from values in
peer certificate, e.g.:
SOCAT_OPENSSL_X509_SUBJECT, SOCAT_OPENSSL_X509_ISSUER,
SOCAT_OPENSSL_X509_COMMONNAME,
SOCAT_OPENSSL_X509V3_SUBJECTALTNAME_DNS
Tests: ENV_OPENSSL_{CLIENT,SERVER}_X509_*
Added support for methods TLSv1, TLSv1.1, TLSv1.2, and DTLS1
Tests: OPENSSL_METHOD_*
Enabled OpenSSL server side use of ECDHE ciphers. Feature suggested
by Andrey Arapov.
Added a new option termios-rawer for ptys.
Thanks to Christian Vogelgsang for pointing me to this requirement
corrections:
Bind with ABSTRACT commands used non-abstract namespace (Linux).
Test: ABSTRACT_BIND
Thanks to Denis Shatov for reporting this bug.
Fixed return value of nestlex()
Option ignoreeof on the right address hung.
Test: IGNOREEOF_REV
Thanks to Franz Fasching for reporting this bug.
Address SYSTEM, when terminating, shut down its parent addresses,
e.g. an SSL connection which the parent assumed to still be active.
Test: SYSTEM_SHUTDOWN
Passive (listening or receiving) addresses with empty port field bound
to a random port instead of terminating with error.
Test: TCP4_NOPORT
configure with some combination of disable options produced config
files that failed to compile due to missing IPPROTO_TCP.
Thanks to Thierry Fournier for report and patch.
fixed a few minor bugs with OpenSSL in configure and with messages
Socat did not work in FIPS mode because 1024 instead of 512 bit DH prime
is required. Thanks to Zhigang Wang for reporting and sending a patch.
Christophe Leroy provided a patch that fixes memory leaks reported by
valgrind
Help for filan -L was bad, is now corrected to:
"follow symbolic links instead of showing their properties"
Address options fdin and fdout were silently ignored when not applicable
due to -u or -U option. Now these combinations are caught as errors.
Test: FDOUT_ERROR
Issue reported by Hendrik.
Added option termios-cfmakeraw that calls cfmakeraw() and is preferred
over option raw which is now obsolote. On SysV systems this call is
simulated by appropriate setting.
Thanks to Youfu Zhang for reporting issue with option raw.
porting:
Socat included <sys/poll.h> instead of POSIX <poll.h>
Thanks to John Spencer for reporting this issue.
Version 1.7.2.4 changed the check for gcc in configure.ac; this
broke cross compiling. The particular check gets reverted.
Thanks to Ross Burton and Danomi Manchego for reporting this issue.
Debian Bug#764251: Set the build timestamp to a deterministic time:
support external BUILD_DATE env var to allow to build reproducable
binaries
Joachim Fenkes provided an new adapted spec file.
Type bool and macros Min and Max are defined by socat which led to
compile errors when they were already provided by build framework.
Thanks to Liyu Liu for providing a patch.
David Arnstein contributed a patch for NetBSD 5.1 including stdbool.h
support and appropriate files in Config/
Lauri Tirkkonen contributed a patch regarding netinet/if_ether.h
on Illumos
Changes for Openindiana: define _XPG4_2, __EXTENSIONS__,
_POSIX_PTHREAD_SEMANTICS; and minor changes
Red Hat issue 1182005: socat 1.7.2.4 build failure missing
linux/errqueue.h
Socat failed to compile on on PPC due to new requirements for
including <linux/errqueue.h> and a weakness in the conditional code.
Thanks to Michel Normand for reporting this issue.
doc:
In the man page the PTY example was badly formatted. Thanks to
J.F.Sebastian for sending a patch.
Added missing CVE ids to security issues in CHANGES
testing:
Do not distribute testcert.conf with socat source but generate it
(and new testcert6.conf) during test.sh run.
####################### V 1.7.2.4:
corrections:
LISTEN based addresses applied some address options, e.g. so-keepalive,
to the listening file descriptor instead of the connected file
descriptor
Thanks to Ulises Alonso for reporting this bug
make failed after configure with non gcc compiler due to missing
include. Thanks to Horacio Mijail for reporting this problem
configure checked for --disable-rawsocket but printed
--disable-genericsocket in the help text. Thanks to Ben Gardiner for
reporting and patching this bug
In xioshutdown() a wrong branch was chosen after RECVFROM type addresses.
Probably no impact.
Thanks to David Binderman for reproting this issue.
procan could not cleanly format ulimit values longer than 16 decimal
digits. Thanks to Frank Dana for providing a patch that increases field
width to 24 digits.
OPENSSL-CONNECT with bind option failed on some systems, eg.FreeBSD, with
"Invalid argument"
Thanks to Emile den Tex for reporting this bug.
Changed some variable definitions to make gcc -O2 aliasing checker happy
Thanks to Ilya Gordeev for reporting these warnings
On big endian platforms with type long >32bit the range option applied a
bad base address. Thanks to hejia hejia for reporting and fixing this bug.
Red Hat issue 1022070: missing length check in xiolog_ancillary_socket()
Red Hat issue 1022063: out-of-range shifts on net mask bits
Red Hat issue 1022062: strcpy misuse in xiosetsockaddrenv_ip4()
Red Hat issue 1022048: strncpy hardening: corrected suspicious strncpy()
uses
Red Hat issue 1021958: fixed a bug with faulty buffer/data length
calculation in xio-ascii.c:_xiodump()
Red Hat issue 1021972: fixed a missing NUL termination in return string
of sysutils.c:sockaddr_info() for the AF_UNIX case
fixed some typos and minor issues, including:
Red Hat issue 1021967: formatting error in manual page
UNIX-LISTEN with fork option did not remove the socket file system entry
when exiting. Other file system based passive address types had similar
issues or failed to apply options umask, user e.a.
Thanks to Lorenzo Monti for pointing me to this issue
porting:
Red Hat issue 1020203: configure checks fail with some compilers.
Use case: clang
Performed changes for Fedora release 19
Adapted, improved test.sh script
Red Hat issue 1021429: getgroupent fails with large number of groups;
use getgrouplist() when available instead of sequence of calls to
getgrent()
Red Hat issue 1021948: snprintf API change;
Implemented xio_snprintf() function as wrapper that tries to emulate C99
behaviour on old glibc systems, and adapted all affected calls
appropriately
Mike Frysinger provided a patch that supports long long for time_t,
socklen_t and a few other libc types.
Artem Mygaiev extended Cedril Priscals Android build script with pty code
The check for fips.h required stddef.h
Thanks to Matt Hilt for reporting this issue and sending a patch
Check for linux/errqueue.h failed on some systems due to lack of
linux/types.h inclusion. Thanks to Michael Vastola for sending a patch.
autoconf now prefers configure.ac over configure.in
Thanks to Michael Vastola for sending a patch.
type of struct cmsghdr.cmsg is system dependend, determine it with
configure; some more print format corrections
docu:
libwrap always logs to syslog
added actual text version of GPLv2
####################### V 1.7.2.3:
security:
CVE-2014-0019: socats PROXY-CONNECT address was vulnerable to a buffer
overflow with data from command line (see socat-secadv5.txt)
Credits to Florian Weimer of the Red Hat Product Security Team
####################### V 1.7.2.2:
security:
CVE-2013-3571:
after refusing a client connection due to bad source address or source
port socat shutdown() the socket but did not close() it, resulting in
a file descriptor leak in the listening process, visible with lsof and
possibly resulting in EMFILE Too many open files. This issue could be
misused for a denial of service attack.
Full credits to Catalin Mitrofan for finding and reporting this issue.
####################### V 1.7.2.1:
security:
CVE-2012-0219:
fixed a possible heap buffer overflow in the readline address. This bug
could be exploited when all of the following conditions were met:
1) one of the addresses is READLINE without the noprompt and without the
prompt options.
2) the other (almost arbitrary address) reads malicious data (which is
then transferred by socat to READLINE).
Workaround: when using the READLINE address apply option prompt or
noprompt.
Full credits to Johan Thillemann for finding and reporting this issue.
####################### V 1.7.2.0:
corrections:
when UNIX-LISTEN was applied to an existing file it failed as expected
but removed the file. Thanks to Bjoern Bosselmann for reporting this
problem
fixed a bug where socat might crash when connecting to a unix domain
socket using address GOPEN. Thanks to Martin Forssen for bug report and
patch.
UDP-LISTEN would alway set SO_REUSEADDR even without fork option and
when user set it to 0. Thanks to Michal Svoboda for reporting this bug.
UNIX-CONNECT did not support half-close. Thanks to Greg Hughes who
pointed me to that bug
TCP-CONNECT with option nonblock reported successful connect even when
it was still pending
address option ioctl-intp failed with "unimplemented type 26". Thanks
to Jeremy W. Sherman for reporting and fixing that bug
socat option -x did not print packet direction, timestamp etc; thanks
to Anthony Sharobaiko for sending a patch
address PTY does not take any parameters but did not report an error
when some were given
Marcus Meissner provided a patch that fixes invalid output and possible
process crash when socat prints info about an unnamed unix domain
socket
Michal Soltys reported the following problem and provided an initial
patch: when socat was interrupted, e.g. by SIGSTOP, and resumed during
data transfer only parts of the data might have been written.
Option o-nonblock in combination with large transfer block sizes
may result in partial writes and/or EAGAIN errors that were not handled
properly but resulted in data loss or process termination.
Fixed a bug that could freeze socat when during assembly of a log
message a signal was handled that also printed a log message. socat
development had been aware that localtime() is not thread safe but had
only expected broken messages, not corrupted stack (glibc 2.11.1,
Ubuntu 10.4)
an internal store for child pids was susceptible to pid reuse which
could lead to sporadic data loss when both fork option and exec address
were used. Thanks to Tetsuya Sodo for reporting this problem and
sending a patch
OpenSSL server failed with "no shared cipher" when using cipher aNULL.
Fixed by providing temporary DH parameters. Thanks to Philip Rowlands
for drawing my attention to this issue.
UDP-LISTEN slept 1s after accepting a connection. This is not required.
Thanks to Peter Valdemar Morch for reporting this issue
fixed a bug that could lead to error or socat crash after a client
connection with option retry had been established
fixed configure.in bug on net/if.h check that caused IF_NAMESIZE to be
undefined
improved dev_t print format definition
porting:
Cedril Priscal ported socat to Android (using Googles cross compiler).
The port includes the socat_buildscript_for_android.sh script
added check for component ipi_spec_dst in struct in_pktinfo so
compilation does not fail on Cygwin (thanks to Peter Wagemans for
reporting this problem)
build failed on RHEL6 due to presence of fips.h; configure now checks
for fipsld too. Thanks to Andreas Gruenbacher for reporting this
problem
check for netinet6/in6.h only when IPv6 is available and enabled
don't fail to compile when the following defines are missing:
IPV6_PKTINFO IPV6_RTHDR IPV6_DSTOPTS IPV6_HOPOPTS IPV6_HOPLIMIT
Thanks to Jerry Jacobs for reporting this problem (Mac OS X Lion 10.7)
check if define __APPLE_USE_RFC_2292 helps to enable IPV6_* (MacOSX
Lion 7.1); thanks to Jerry Jacobs to reporting this problem and
proposing a solution
fixed compiler warnings on Mac OS X 64bit. Thanks to Guy Harris for
providing the patch.
corrections for OpenEmbedded, especially termios SHIFT values and
ISPEED/OSPEED. Thanks to John Faith for providing the patch
minor corrections to docu and test.sh resulting from local compilation
on Openmoko SHR
fixed sa_family_t compile error on DragonFly. Thanks to Tony Young for
reporting this issue and sending a patch.
Ubuntu Oneiric: OpenSSL no longer provides SSLv2 functions; libutil.sh
is now bsd/libutil.h; compiler warns on vars that is only written to
new features:
added option max-children that limits the number of concurrent child
processes. Thanks to Sam Liddicott for providing the patch.
Till Maas added support for tun/tap addresses without IP address
added an option openssl-compress that allows to disable the compression
feature of newer OpenSSL versions. Thanks to Michael Hanselmann for
providing this contribution (sponsored by Google Inc.)
docu:
minor corrections in docu (thanks to Paggas)
client process -> child process
####################### V 1.7.1.3:
security:
CVE-2010-2799:
fixed a stack overflow vulnerability that occurred when command
line arguments (whole addresses, host names, file names) were longer
than 512 bytes.
@ -501,7 +891,8 @@ further corrections:
####################### V 1.4.0.3:
corrections:
security:
CVE-2004-1484:
fix to a syslog() based format string vulnerability that can lead to
remote code execution. See advisory socat-adv-1.txt
@ -735,7 +1126,7 @@ further corrections:
ftp.sh script supports proxy address
man page no longer installed with execute permissions (thanks to Peter
Bray)
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

42
COPYING
View File

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ 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
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@ -55,8 +55,8 @@ 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
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
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
@ -168,7 +168,7 @@ 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
@ -225,7 +225,7 @@ 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
@ -255,7 +255,7 @@ 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
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
@ -277,9 +277,9 @@ 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
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
@ -291,7 +291,7 @@ 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>
Copyright (C) <year> <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
@ -303,16 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
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.
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 version 69, Copyright (C) year 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.
@ -335,5 +335,5 @@ necessary. Here is a sample; alter the names:
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
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

195
Config/Makefile.NetBSD-5-1 Normal file
View File

@ -0,0 +1,195 @@
# source: Makefile.in
# Copyright Gerhard Rieger 2001-2008
# Published under the GNU General Public License V.2, see file COPYING
# note: @...@ forms are filled in by configure script
SHELL = /bin/sh
AR = ar
RANLIB = ranlib
.SUFFIXES: .c .o
prefix = /usr/local
exec_prefix = ${prefix}
BINDEST = ${exec_prefix}/bin
datarootdir = ${prefix}/share
MANDEST = ${datarootdir}/man
srcdir = .
CC = gcc
CCOPTS = $(CCOPT) -Wall -Wno-parentheses
SYSDEFS =
CPPFLAGS = -I.
#0 INCLS = -I. @V_INCL@
DEFS = -DHAVE_CONFIG_H
LIBS = -lwrap -lutil -lssl
LDFLAGS =
INSTALL = /usr/bin/install -c
#OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o)
#0 CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(INCLS)
CFLAGS = -O -D_GNU_SOURCE $(CCOPTS) $(DEFS) $(CPPFLAGS)
CLIBS = $(LIBS)
#CLIBS = $(LIBS) -lm -lefence
XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \
xiosignal.c xiosigchld.c xioread.c xiowrite.c \
xiolayer.c xioshutdown.c xioclose.c xioexit.c \
xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \
xio-gopen.c xio-creat.c xio-file.c xio-named.c \
xio-socket.c xio-interface.c xio-listen.c xio-unix.c \
xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \
xio-sctp.c xio-rawip.c \
xio-socks.c xio-proxy.c xio-udp.c \
xio-rawip.c \
xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
xio-pty.c xio-openssl.c xio-streams.c\
xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c
XIOOBJS = $(XIOSRCS:.c=.o)
UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c filan.c sycls.c sslcls.c
UTLOBJS = $(UTLSRCS:.c=.o)
CFILES = $(XIOSRCS) $(UTLSRCS) socat.c procan_main.c filan_main.c
OFILES = $(CFILES:.c=.o)
PROGS = socat procan filan
HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h compat.h \
xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.h \
xiomodes.h xiolayer.h xio-process.h xio-fd.h xio-fdnum.h xio-stdio.h \
xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h \
xio-socket.h xio-interface.h xio-listen.h xio-unix.h \
xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \
xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \
xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \
xio-system.h xio-termios.h xio-readline.h \
xio-pty.h xio-openssl.h xio-streams.h \
xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h
DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo doc/socat.1 doc/socat.html doc/xio.help FAQ BUGREPORTS COPYING COPYING.OpenSSL doc/dest-unreach.css doc/socat-openssltunnel.html doc/socat-multicast.html doc/socat-tun.html
SHFILES = daemon.sh mail.sh ftp.sh readline.sh
TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \
proxy.sh socks4a-echo.sh testcert.conf
OSFILES = Config/Makefile.Linux-2-6-24 Config/config.Linux-2-6-24.h \
Config/Makefile.SunOS-5-10 Config/config.SunOS-5-10.h \
Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \
Config/Makefile.NetBSD-4-0 Config/config.NetBSD-4-0.h \
Config/Makefile.OpenBSD-4-3 Config/config.OpenBSD-4-3.h
all: progs doc
scmclean: gitclean
gitclean: distclean docclean
rm -f Makefile.bak configure
doc: doc/socat.1 doc/socat.html
docclean:
rm -f doc/socat.1 doc/socat.html
doc/socat.1: doc/socat.yo
yodl2man -o $@ $+
doc/socat.html: doc/socat.yo
cd doc; yodl2html -o socat.html socat.yo; cd ..
progs: $(PROGS)
depend: $(CFILES) $(HFILES)
makedepend $(SYSDEFS) $(CFILES)
socat: socat.o libxio.a
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS)
PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o
procan: $(PROCAN_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(PROCAN_OBJS) $(CLIBS)
filan: filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o $(CLIBS)
libxio.a: $(XIOOBJS) $(UTLOBJS)
$(AR) r $@ $(XIOOBJS) $(UTLOBJS)
$(RANLIB) $@
doc: doc/xio.help
#
strip: progs
strip $(PROGS)
install: progs $(srcdir)/doc/socat.1
mkdir -p $(DESTDIR)$(BINDEST)
$(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST)
$(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST)
$(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST)
mkdir -p $(DESTDIR)$(MANDEST)/man1
$(INSTALL) -m 644 $(srcdir)/doc/socat.1 $(DESTDIR)$(MANDEST)/man1/
uninstall:
rm -f $(DESTDIR)$(BINDEST)/socat
rm -f $(DESTDIR)$(BINDEST)/procan
rm -f $(DESTDIR)$(BINDEST)/filan
rm -f $(DESTDIR)$(MANDEST)/man1/socat.1
# make a GNU-zipped tar ball of the source files
dist: socat.tar.gz socat.tar.bz2
socat.tar.gz: socat.tar
gzip -9 <socat.tar >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

522
Config/config.NetBSD-5-1.h Normal file
View File

@ -0,0 +1,522 @@
/* config.h. Generated from config.h.in by configure. */
/* source: config.h.in */
/* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __config_h_included
#define __config_h_included 1
/* Define to empty if the keyword does not work. */
/* #undef const */
/* Define to `int' if <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 if_indextoname function. */
#define HAVE_IF_INDEXTONAME 1
/* Define if you have the sigaction function */
#define HAVE_SIGACTION 1
/* Define if you have the stat64 function */
/* #undef HAVE_STAT64 */
/* Define if you have the fstat64 function */
/* #undef HAVE_FSTAT64 */
/* Define if you have the lstat64 function */
/* #undef HAVE_LSTAT64 */
/* Define if you have the lseek64 function */
/* #undef HAVE_LSEEK64 */
/* Define if you have the truncate64 function */
/* #undef HAVE_TRUNCATE64 */
/* Define if you have the ftruncate64 function */
/* #undef HAVE_FTRUNCATE64 */
/* Define if you have the strtoll function */
#define HAVE_STRTOLL 1
/* Define if you have the hstrerror function */
#define HAVE_HSTRERROR 1
/* Define if you have the inet_ntop function */
#define HAVE_INET_NTOP 1
/* Define if you have the hstrerror prototype */
#define HAVE_PROTOTYPE_HSTRERROR 1
/* Define if you have the <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 <net/if_dl.h> header file. */
#define HAVE_NET_IF_DL_H 1
/* Define if you have the <linux/types.h> header file. */
/* #undef HAVE_LINUX_TYPES_H */
/* Define if you have the <linux/errqueue.h> header file. */
/* #undef HAVE_LINUX_ERRQUEUE_H */
/* Define if you have the <linux/if_tun.h> header file. */
/* #undef HAVE_LINUX_IF_TUN_H */
/* Define if you have the <netpacket/packet.h> header file. */
/* #undef HAVE_NETPACKET_PACKET_H */
/* Define if you have the <netinet/if_ether.h> header file. */
/* #undef HAVE_NETINET_IF_ETHER_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()) */
#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/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 you have the sa_family_t */
#define HAVE_TYPE_SA_FAMILY_T 1
/* define if your struct sigaction has sa_sigaction */
#define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1
/* Define if your struct termios has component c_ispeed */
#define HAVE_TERMIOS_ISPEED 1
/* the offset of c_ispeed in struct termios - usable in an speed_t array.
Applies only when HAVE_TERMIOS_ISPEED is set */
#define ISPEED_OFFSET 9
/* the offset of c_ospeed in struct termios - see ISPEED_OFFSET */
#ifdef ISPEED_OFFSET
# define OSPEED_OFFSET (ISPEED_OFFSET+1)
#else
/* # undef OSPEED_OFFSET */
#endif
/* Define if your termios.h likes _SVID3 defined */
/* #undef _SVID3 */
/* Define if you have struct timespec (e.g. for nanosleep) */
#define HAVE_STRUCT_TIMESPEC 1
/* Define if you have struct linger */
#define HAVE_STRUCT_LINGER 1
/* Define if you have struct ip_mreq */
#define HAVE_STRUCT_IP_MREQ 1
/* Define if you have struct ip_mreqn */
/* #undef HAVE_STRUCT_IP_MREQN */
/* Define if you have struct ipv6_mreq */
#define HAVE_STRUCT_IPV6_MREQ 1
/* Define if you have struct ifreq */
#define HAVE_STRUCT_IFREQ 1
/* Define if you have struct ifreq.ifr_index */
/* #undef HAVE_STRUCT_IFREQ_IFR_INDEX */
/* Define if you have struct ifreq.ifr_ifindex; not on HPUX */
/* #undef HAVE_STRUCT_IFREQ_IFR_IFINDEX */
/* Define if your struct sockaddr has sa_len */
#define HAVE_STRUCT_SOCKADDR_SALEN 1
/* there are several implementations of sockaddr_in6 */
#define HAVE_IP6_SOCKADDR 0
/* Define if you have struct iovec */
#define HAVE_STRUCT_IOVEC 1
/* define if your struct msghdr has msg_control */
#define HAVE_STRUCT_MSGHDR_MSGCONTROL 1
/* define if your struct msghdr has msg_controllen */
#define HAVE_STRUCT_MSGHDR_MSGCONTROLLEN 1
/* define if your struct msghdr has msg_flag */
#define HAVE_STRUCT_MSGHDR_MSGFLAGS 1
/* define if you have struct cmsghdr */
#define HAVE_STRUCT_CMSGHDR 1
/* define if you have struct in_pktinfo */
/* #undef HAVE_STRUCT_IN_PKTINFO */
/* define if your struct ip has ip_hl; otherwise assume ip_vhl */
#define HAVE_STRUCT_IP_IP_HL 1
/* Define if you have the setenv function */
#define HAVE_SETENV 1
/* Define if you have the unsetenv function. not on HP-UX */
#define HAVE_UNSETENV 1
/* Define if you have the flock function */
#define HAVE_FLOCK 1
/* Define if you have the openpty function */
#define HAVE_OPENPTY 1
/* Define if you have the grantpt function */
#define HAVE_GRANTPT 1
/* Define if you have the unlockpt function */
#define HAVE_UNLOCKPT 1
/* Define if you have the ptsname function */
#define HAVE_PTSNAME 1
/* Define if you have the /dev/ptmx pseudo terminal multiplexer */
#define HAVE_DEV_PTMX 1
/* Define if you have the /dev/ptc pseudo terminal multiplexer */
/* #undef HAVE_DEV_PTC */
/* Define if you have the long long type */
#define HAVE_TYPE_LONGLONG 1
/* is socklen_t already typedef'd? */
#define HAVE_TYPE_SOCKLEN 1
/* Define if you have the struct stat64 type */
/* #undef HAVE_TYPE_STAT64 */
/* Define if you have the struct off64_t type */
/* #undef HAVE_TYPE_OFF64 */
/* is sighandler_t already typedef'd? */
/* #undef HAVE_TYPE_SIGHANDLER */
/* is uint8_t already defined? */
#define HAVE_TYPE_UINT8 1
/* is uint16_t already defined? */
#define HAVE_TYPE_UINT16 1
/* is uint32_t already defined? */
#define HAVE_TYPE_UINT32 1
/* is uint64_t already defined? */
#define HAVE_TYPE_UINT64 1
/* Define if you have the printf "Z" modifier */
/* #undef HAVE_FORMAT_Z */
/* Define the shift offset of the CRDLY mask */
#define CRDLY_SHIFT -1
/* Define the shift offset of the TABDLY mask */
#define TABDLY_SHIFT -1
/* Define the shift offset of the CSIZE mask */
#define CSIZE_SHIFT 8
/* Define if you have tcpwrappers (libwrap, tcpd) and it declares hosts_allow_table */
#define HAVE_HOSTS_ALLOW_TABLE 1
#if defined(HAVE_HOSTS_ALLOW_TABLE) && HAVE_HOSTS_ALLOW_TABLE
# define HAVE_HOSTS_DENY_TABLE 1
#else
/* # undef HAVE_HOSTS_DENY_TABLE */
#endif
/* 1..short, 3..int, 5..long; 2,4,6..unsigned */
#define HAVE_BASIC_SIZE_T 4 /* unsigned int */
#define HAVE_BASIC_MODE_T 4 /* unsigned int */
#define HAVE_BASIC_PID_T 3 /* int */
#define HAVE_BASIC_UID_T 4 /* unsigned int */
#define HAVE_BASIC_GID_T 4 /* unsigned int */
#define HAVE_BASIC_TIME_T 5 /* long */
#define HAVE_BASIC_OFF64_T 0 /* unknown, taking default */
#define HAVE_BASIC_SOCKLEN_T 4 /* unsigned int */
#define HAVE_TYPEOF_ST_DEV 4 /* unsigned int */
#define HAVE_TYPEOF_ST_INO 8 /* unsigned long long */
#define HAVE_TYPEOF_ST_NLINK 4 /* unsigned int */
#define HAVE_TYPEOF_ST_SIZE 7 /* long long */
#define HAVE_TYPEOF_ST_BLKSIZE 4 /* unsigned int */
#define HAVE_TYPEOF_ST_BLOCKS 7 /* long long */
/* #undef HAVE_TYPEOF_ST64_DEV */
/* #undef HAVE_TYPEOF_ST64_INO */
/* #undef HAVE_TYPEOF_ST64_NLINK */
/* #undef HAVE_TYPEOF_ST64_SIZE */
/* #undef HAVE_TYPEOF_ST64_BLKSIZE */
/* #undef HAVE_TYPEOF_ST64_BLOCKS */
#define HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC 5 /* long */
#define HAVE_TYPEOF_RLIM_MAX 7 /* long long */
/* Define if you have the /proc filesystem */
#define HAVE_PROC_DIR 1
/* Define if you have the /proc/$$/fd directories */
/* #undef HAVE_PROC_DIR_FD */
#define WITH_HELP 1
#define WITH_STDIO 1
#define WITH_FDNUM 1
#define WITH_FILE 1
#define WITH_CREAT 1
#define WITH_GOPEN 1
#define WITH_TERMIOS 1
#define WITH_PIPE 1
#define WITH_UNIX 1
/* #undef WITH_ABSTRACT_UNIXSOCKET */
#define WITH_IP4 1
#define WITH_IP6 1
#define WITH_RAWIP 1
#define WITH_GENERICSOCKET 1
/* #undef WITH_INTERFACE */
#define WITH_TCP 1
#define WITH_UDP 1
/* #undef WITH_SCTP */
#define WITH_LISTEN 1
#define WITH_SOCKS4 1
#define WITH_SOCKS4A 1
#define WITH_PROXY 1
#define WITH_EXEC 1
#define WITH_SYSTEM 1
/* #undef WITH_READLINE */
/* #undef WITH_TUN */
#define WITH_PTY 1
#define WITH_EXT2 1
#define WITH_OPENSSL 1
#define WITH_STREAMS 1
/* #undef WITH_FIPS */
/* #undef OPENSSL_FIPS */
#define WITH_LIBWRAP 1
#define HAVE_TCPD_H 1
#define HAVE_LIBWRAP 1
#define WITH_SYCLS 1
#define WITH_FILAN 1
#define WITH_RETRY 1
#define WITH_MSGLEVEL 0
#endif /* !defined(__config_h_included) */

View File

@ -131,13 +131,12 @@ PH_LATE FD is ready, before start of data loop
PH_LATE2 FD is ready, dropping privileges
SOCKET with LISTEN and FORK:
SOCKET with LISTEN and ACCEPT:
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()
@ -147,7 +146,9 @@ PH_PASTLISTEN after listen()
PH_PREACCEPT before accept()
PH_ACCEPT during accept()
PH_PASTACCEPT after accept()
# and the following on the new FD:
PH_FD soon after FD creation or identification
PH_PASTSOCKET after socket call
PH_CONNECTED phase common with connect
PH_PREFORK before forking
PH_FORK during fork()
@ -203,3 +204,19 @@ PH_PREFORK, PH_FORK, PH_PASTFORK # (all before/after?)
PH_LATE # chroot
PH_LATE2 # su, su-d.2
PH_PREEXEC, PH_EXEC # (all before)
===============================================================================
// Up to 1.7.2.4 socat used non async signal safe system and library calls in signal handlers, mostly for logging purposes. This problem was fixed in release 1.7.3.0 with the following concepts:
Signal handlers set on entry and unset on return the diag_in_handler global variable. The logging system, when this variable is set, queues the text message together with errno and exit info in a UNIX datagram socket. When invoked with unset diag_in_handler it first checks if there are messages in that queue and prints them first.
A async signal safe but minimal version of vsnprintf, named vsnprintf_r, was written so no value arguments need to be queued.
Because strerror is not async signal safe a new function snprinterr was written that replaces the (glibc compatible) %m format with strerror output. The original errno is passed in the message queue, snprinterr is called when dequeuing messages outside of signal handler.
// List of signal handlers in socat
socat.c:socat_signal (generic, just logs and maybe exits)
xioshutdown.c:signal_kill_pid (SIGALRM, kill child process)
xiosigchld.c:childdied (SIGCHLD: get info, log; possibly close channel)
xiosignal.c:socatsignalpass: cascades signal to channel child processes; w/ options sighup,sigint,sigquit
xio-socket.c:xiosigaction_hasread: SIGUSR1,SIGCHLD, tells parent that datagram has been consumed

View File

@ -1,5 +1,5 @@
# source: Makefile.in
# Copyright Gerhard Rieger 2001-2009
# Copyright Gerhard Rieger
# Published under the GNU General Public License V.2, see file COPYING
# note: @...@ forms are filled in by configure script
@ -54,13 +54,13 @@ XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \
xio-pty.c xio-openssl.c xio-streams.c\
xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c
XIOOBJS = $(XIOSRCS:.c=.o)
UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c @FILAN@ @SYCLS@ @SSLCLS@
UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c vsnprintf_r.c snprinterr.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 \
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 vsnprintf_r.h snprinterr.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 \
@ -74,17 +74,19 @@ HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.
DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo doc/socat.1 doc/socat.html doc/xio.help FAQ BUGREPORTS COPYING COPYING.OpenSSL doc/dest-unreach.css doc/socat-openssltunnel.html doc/socat-multicast.html doc/socat-tun.html doc/socat-genericsocket.html
SHFILES = daemon.sh mail.sh ftp.sh readline.sh
SHFILES = daemon.sh mail.sh ftp.sh readline.sh \
socat_buildscript_for_android.sh
TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \
proxy.sh socks4a-echo.sh testcert.conf
proxy.sh socks4a-echo.sh
OSFILES = Config/Makefile.Linux-2-6-24 Config/config.Linux-2-6-24.h \
Config/Makefile.SunOS-5-10 Config/config.SunOS-5-10.h \
Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \
Config/Makefile.NetBSD-4-0 Config/config.NetBSD-4-0.h \
Config/Makefile.NetBSD-5-1 Config/config.NetBSD-5-1.h \
Config/Makefile.OpenBSD-4-3 Config/config.OpenBSD-4-3.h \
Config/Makefile.AIX-5-3 Config/config.AIX-5-3.h \
Config/Makefile.Cygwin-1-5-25 Config/config.Cygwin-1-5-25.h \
Config/Makefile.MacOSX-10-5 Config/config.MacOSX-10-5.h
Config/Makefile.MacOSX-10-5 Config/config.MacOSX-10-5.h \
Config/Makefile.DragonFly-2-8-2 Config/config.DragonFly-2-8-2.h
all: progs doc
@ -112,12 +114,12 @@ depend: $(CFILES) $(HFILES)
socat: socat.o libxio.a
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS)
PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o
PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o vsnprintf_r.o snprinterr.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)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o vsnprintf_r.o snprinterr.o $(CLIBS)
libxio.a: $(XIOOBJS) $(UTLOBJS)
$(AR) r $@ $(XIOOBJS) $(UTLOBJS)
@ -154,7 +156,8 @@ socat.tar.bz2: socat.tar
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
socat.tar: configure.in configure Makefile.in config.h.in install-sh VERSION $(CFILES) $(HFILES) $(DOCFILES) $(SHFILES) $(OSFILES) $(TESTFILES) socat.spec \
configure.ac
if [ ! -d $(TARDIR) ]; then mkdir $(TARDIR); fi
tar cf - $+ |(cd $(TARDIR); tar xf -)
tar cvf socat.tar $(TARDIR)

13
README
View File

@ -74,8 +74,8 @@ install
-------
Get the tarball and extract it:
gtar xzf socat.tar.gz
cd socat-1.7.1.2
tar xzf socat.tar.gz
cd socat-1.7.3.0
./configure
make
su
@ -132,6 +132,11 @@ the file PORTING.
platform specifics - redhat
---------------------------
Install the following packages before building socat:
tcp_wrappers-devel
readline-devel
openssl-devel
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:
@ -190,7 +195,7 @@ platform specifics - hp-ux
--------------------------
Ancillary messages cannot be compiled in with socat: both struct msghdr and
strutc cmsghdr are required. Compiling with -D_XOPEN_SOURCE_EXTENDED provides
struct cmsghdr are required. Compiling with -D_XOPEN_SOURCE_EXTENDED provides
struct msghdr but disables struct cmsghdr while -D_OPEN_SOURCE disables struct
msghdr but disables struct cmsghdr. Please contact socat development if you
know a solution.
@ -252,7 +257,7 @@ correction must be performed in /usr/share/yodl/shared.yo in two places:
license
-------
socat is distributed under the terms of the GNU GPL;
socat is distributed under the terms of the GNU GPLv2;
except for install-sh, which is copyright MIT, with its own license;
In addition, as a special exception, the copyright holder

View File

@ -1 +1 @@
"1.7.1.3"
"1.7.3.0"

161
compat.h
View File

@ -1,10 +1,14 @@
/* source: compat.h */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __compat_h_included
#define __compat_h_included 1
#if !HAVE_DECL_ENVIRON && HAVE_VAR_ENVIRON
extern char **environ;
#endif
/*****************************************************************************/
/* I dont like this system dependent part, but it would be quite a challenge
for configure */
@ -31,6 +35,10 @@
/* substitute some features that might be missing on some platforms */
#if !HAVE_TYPE_SIG_ATOMIC_T
typedef int sig_atomic_t;
#endif
#ifndef SHUT_RD
# define SHUT_RD 0
#endif
@ -72,7 +80,9 @@
/* SOL_TCP: AIX 4.3.3 */
#ifndef SOL_TCP
# define SOL_TCP IPPROTO_TCP
# ifdef IPPROTO_TCP
# define SOL_TCP IPPROTO_TCP
# endif
#endif
/* POSIX.1 doesn't seem to know sockets */
@ -99,7 +109,7 @@
# define SIZET_MAX UINT_MAX
# define SSIZET_MIN INT_MIN
# define SSIZET_MAX INT_MAX
# define F_Zd "%d"
# define F_Zd "%""d"
# define F_Zu "%u"
#elif HAVE_BASIC_SIZE_T==6
# define SIZET_MAX ULONG_MAX
@ -153,7 +163,7 @@
# elif HAVE_BASIC_PID_T==2
#define F_pid "%hu"
# elif HAVE_BASIC_PID_T==3
#define F_pid "%d"
#define F_pid "%""d"
# elif HAVE_BASIC_PID_T==4
#define F_pid "%u"
# elif HAVE_BASIC_PID_T==5
@ -177,7 +187,7 @@
# elif HAVE_BASIC_UID_T==2
#define F_uid "%hu"
# elif HAVE_BASIC_UID_T==3
#define F_uid "%d"
#define F_uid "%""d"
# elif HAVE_BASIC_UID_T==4
#define F_uid "%u"
# elif HAVE_BASIC_UID_T==5
@ -201,7 +211,7 @@
# elif HAVE_BASIC_GID_T==2
#define F_gid "%hu"
# elif HAVE_BASIC_GID_T==3
#define F_gid "%d"
#define F_gid "%""d"
# elif HAVE_BASIC_GID_T==4
#define F_gid "%u"
# elif HAVE_BASIC_GID_T==5
@ -225,13 +235,17 @@
# elif HAVE_BASIC_TIME_T==2
#define F_time "%hu"
# elif HAVE_BASIC_TIME_T==3
#define F_time "%d"
#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"
# elif HAVE_BASIC_TIME_T==7
#define F_time "%Ld"
# elif HAVE_BASIC_TIME_T==8
#define F_time "%Lu"
# else
#error "HAVE_BASIC_TIME_T is out of range:" HAVE_BASIC_TIME_T
# endif
@ -249,13 +263,17 @@
# elif HAVE_BASIC_SOCKLEN_T==2
#define F_socklen "%hu"
# elif HAVE_BASIC_SOCKLEN_T==3
#define F_socklen "%d"
#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"
# elif HAVE_BASIC_SOCKLEN_T==7
#define F_socklen "%Ld"
# elif HAVE_BASIC_SOCKLEN_T==8
#define F_socklen "%Lu"
# else
#error "HAVE_BASIC_SOCKLEN_T is out of range:" HAVE_BASIC_SOCKLEN_T
# endif
@ -267,7 +285,7 @@
#endif
#ifndef F_off
# if HAVE_BASIC_OFF_T==3
# define F_off "%d"
# define F_off "%""d"
# elif HAVE_BASIC_OFF_T==5
# define F_off "%ld"
# elif HAVE_BASIC_OFF_T==7
@ -288,7 +306,7 @@
# elif HAVE_BASIC_OFF64_T==2
#define F_off64 "%hu"
# elif HAVE_BASIC_OFF64_T==3
#define F_off64 "%d"
#define F_off64 "%""d"
# elif HAVE_BASIC_OFF64_T==4
#define F_off64 "%u"
# elif HAVE_BASIC_OFF64_T==5
@ -306,29 +324,29 @@
/* 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
#if !defined(HAVE_BASIC_DEV_T) || !HAVE_BASIC_DEV_T
# undef HAVE_BASIC_DEV_T
# define HAVE_BASIC_DEV_T 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"
#ifndef F_dev
# if HAVE_BASIC_DEV_T==1
#define F_dev "%hd"
# elif HAVE_BASIC_DEV_T==2
#define F_dev "%hu"
# elif HAVE_BASIC_DEV_T==3
#define F_dev "%""d"
# elif HAVE_BASIC_DEV_T==4
#define F_dev "%u"
# elif HAVE_BASIC_DEV_T==5
#define F_dev "%ld"
# elif HAVE_BASIC_DEV_T==6
#define F_dev "%lu"
# elif HAVE_BASIC_DEV_T==7
#define F_dev "%Ld"
# elif HAVE_BASIC_DEV_T==8
#define F_dev "%Lu"
# else
#error "HAVE_TYPEOF_ST_DEV is out of range:" HAVE_TYPEOF_ST_DEV
#error "HAVE_BASIC_DEV_T is out of range:" HAVE_BASIC_DEV_T
# endif
#endif
@ -343,7 +361,7 @@
# elif HAVE_TYPEOF_ST_INO==2
#define F_st_ino "%hu"
# elif HAVE_TYPEOF_ST_INO==3
#define F_st_ino "%d"
#define F_st_ino "%""d"
# elif HAVE_TYPEOF_ST_INO==4
#define F_st_ino "%u"
# elif HAVE_TYPEOF_ST_INO==5
@ -370,7 +388,7 @@
# elif HAVE_TYPEOF_ST64_INO==2
#define F_st64_ino "%hu"
# elif HAVE_TYPEOF_ST64_INO==3
#define F_st64_ino "%d"
#define F_st64_ino "%""d"
# elif HAVE_TYPEOF_ST64_INO==4
#define F_st64_ino "%u"
# elif HAVE_TYPEOF_ST64_INO==5
@ -397,13 +415,17 @@
# elif HAVE_TYPEOF_ST_NLINK==2
#define F_st_nlink "%hu"
# elif HAVE_TYPEOF_ST_NLINK==3
#define F_st_nlink "%d"
#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"
# elif HAVE_TYPEOF_ST_NLINK==7
#define F_st_nlink "%Ld"
# elif HAVE_TYPEOF_ST_NLINK==8
#define F_st_nlink "%Lu"
# else
#error "HAVE_TYPEOF_ST_NLINK is out of range:" HAVE_TYPEOF_ST_NLINK
# endif
@ -420,7 +442,7 @@
# elif HAVE_TYPEOF_ST_SIZE==2
#define F_st_size "%hu"
# elif HAVE_TYPEOF_ST_SIZE==3
#define F_st_size "%d"
#define F_st_size "%""d"
# elif HAVE_TYPEOF_ST_SIZE==4
#define F_st_size "%u"
# elif HAVE_TYPEOF_ST_SIZE==5
@ -447,7 +469,7 @@
# elif HAVE_TYPEOF_ST64_SIZE==2
#define F_st64_size "%hu"
# elif HAVE_TYPEOF_ST64_SIZE==3
#define F_st64_size "%d"
#define F_st64_size "%""d"
# elif HAVE_TYPEOF_ST64_SIZE==4
#define F_st64_size "%u"
# elif HAVE_TYPEOF_ST64_SIZE==5
@ -474,13 +496,17 @@
# elif HAVE_TYPEOF_ST_BLKSIZE==2
#define F_st_blksize "%hu"
# elif HAVE_TYPEOF_ST_BLKSIZE==3
#define F_st_blksize "%d"
#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"
# elif HAVE_TYPEOF_ST_BLKSIZE==7
#define F_st_blksize "%Ld"
# elif HAVE_TYPEOF_ST_BLKSIZE==8
#define F_st_blksize "%Lu"
# else
#error "HAVE_TYPEOF_ST_BLKSIZE is out of range:" HAVE_TYPEOF_ST_BLKSIZE
# endif
@ -497,7 +523,7 @@
# elif HAVE_TYPEOF_ST_BLOCKS==2
#define F_st_blocks "%hu"
# elif HAVE_TYPEOF_ST_BLOCKS==3
#define F_st_blocks "%d"
#define F_st_blocks "%""d"
# elif HAVE_TYPEOF_ST_BLOCKS==4
#define F_st_blocks "%u"
# elif HAVE_TYPEOF_ST_BLOCKS==5
@ -524,7 +550,7 @@
# elif HAVE_TYPEOF_ST64_BLOCKS==2
#define F_st64_blocks "%hu"
# elif HAVE_TYPEOF_ST64_BLOCKS==3
#define F_st64_blocks "%d"
#define F_st64_blocks "%""d"
# elif HAVE_TYPEOF_ST64_BLOCKS==4
#define F_st64_blocks "%u"
# elif HAVE_TYPEOF_ST64_BLOCKS==5
@ -598,6 +624,33 @@
# endif
#endif
/* default: socklen_t */
#if !defined(HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN) || !HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN
# undef HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN
# define HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN HAVE_BASIC_SOCKLEN_T
#endif
#ifndef F_cmsg_len
# if HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==1
#define F_cmsg_len "%""hd"
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==2
#define F_cmsg_len "%""hu"
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==3
#define F_cmsg_len "%""d"
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==4
#define F_cmsg_len "%""u"
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==5
#define F_cmsg_len "%""ld"
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==6
#define F_cmsg_len "%""lu"
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==7
#define F_cmsg_len "%""Ld"
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==8
#define F_cmsg_len "%""Lu"
# else
#error "HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN is out of range:" HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN
# endif
#endif
/* Cygwin 1.3.22 has the prototypes, but not the type... */
#ifndef HAVE_TYPE_STAT64
# undef HAVE_STAT64
@ -622,34 +675,4 @@
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) */

View File

@ -1,5 +1,5 @@
/* source: config.h.in */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __config_h_included
@ -53,6 +53,13 @@
/* Define if you have the putenv function. */
#undef HAVE_PUTENV
/* Define if your cc provides char **environ declaration.
This implies HAVE_VAR_ENVIRON */
#undef HAVE_DECL_ENVIRON
/* Define if you have the char **environ variable */
#undef HAVE_VAR_ENVIRON
/* Define if you have the select function. */
#undef HAVE_SELECT
@ -63,13 +70,13 @@
#undef HAVE_SOCKET
/* Define if you have the strdup function. */
#undef HAVE_STRDUP
#undef HAVE_PROTOTYPE_LIB_strdup
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
#undef HAVE_PROTOTYPE_LIB_strerror
/* Define if you have the strstr function. */
#undef HAVE_STRSTR
#undef HAVE_PROTOTYPE_LIB_strstr
/* Define if you have the strtod function. */
#undef HAVE_STRTOD
@ -96,7 +103,7 @@
#undef HAVE_GETADDRINFO
/* Define if you have the getipnodebyname function. */
#undef HAVE_GETIPNODEBYNAME
#undef HAVE_PROTOTYPE_LIB_getipnodebyname
/* Define if you have the setgroups function. */
#undef HAVE_SETGROUPS
@ -105,10 +112,10 @@
#undef HAVE_INET_ATON
/* Define if you have the memrchr function. */
#undef HAVE_MEMRCHR
#undef HAVE_PROTOTYPE_LIB_memrchr
/* Define if you have the if_indextoname function. */
#undef HAVE_IF_INDEXTONAME
#undef HAVE_PROTOTYPE_LIB_if_indextoname
/* Define if you have the sigaction function */
#undef HAVE_SIGACTION
@ -131,6 +138,9 @@
/* Define if you have the ftruncate64 function */
#undef HAVE_FTRUNCATE64
/* Define if you have the clock_gettime function */
#undef HAVE_CLOCK_GETTIME
/* Define if you have the strtoll function */
#undef HAVE_STRTOLL
@ -143,6 +153,12 @@
/* Define if you have the hstrerror prototype */
#undef HAVE_PROTOTYPE_HSTRERROR
/* Define if you have the <stdbool.h> header file. */
#undef HAVE_STDBOOL_H
/* Define if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
@ -179,6 +195,9 @@
/* Define if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define if you have the <poll.h> header file. */
#undef HAVE_POLL_H
/* Define if you have the <sys/poll.h> header file. */
#undef HAVE_SYS_POLL_H
@ -215,6 +234,9 @@
/* Define if you have the <netinet/ip6.h> header file. */
#undef HAVE_NETINET_IP6_H
/* Define if you have the <netinet6/in6.h> header file. */
#undef HAVE_NETINET6_IN6_H
/* Define if you have the <arpa/nameser.h> header file. */
#undef HAVE_ARPA_NAMESER_H
@ -257,6 +279,9 @@
/* Define if you have the <util.h> header file. (NetBSD, OpenBSD: openpty()) */
#undef HAVE_UTIL_H
/* Define if you have the <bsd/libutil.h> header file. */
#undef HAVE_BSD_LIBUTIL_H
/* Define if you have the <libutil.h> header file. (FreeBSD: openpty()) */
#undef HAVE_LIBUTIL_H
@ -299,6 +324,9 @@
/* define if your struct sigaction has sa_sigaction */
#undef HAVE_STRUCT_SIGACTION_SA_SIGACTION
/* define if you have struct sock_extended_err */
#undef HAVE_STRUCT_SOCK_EXTENDED_ERR
/* Define if your struct termios has component c_ispeed */
#undef HAVE_TERMIOS_ISPEED
@ -316,6 +344,15 @@
/* Define if your termios.h likes _SVID3 defined */
#undef _SVID3
/* Define if your sys/socket.h likes _XPG4_2 defined */
#undef _XPG4_2
/* Define if your ctime_r() choices need _POSIX_PTHREAD_SEMANTICS */
#undef _POSIX_PTHREAD_SEMANTICS
/* Define if you need __EXTENSIONS__ */
#undef __EXTENSIONS__
/* Define if you have struct timespec (e.g. for nanosleep) */
#undef HAVE_STRUCT_TIMESPEC
@ -364,6 +401,12 @@
/* define if you have struct in_pktinfo */
#undef HAVE_STRUCT_IN_PKTINFO
/* define if your struct in_pktinfo has component ipi_spec_dst */
#undef HAVE_PKTINFO_IPI_SPEC_DST
/* define if you have struct in6_pktinfo */
#undef HAVE_STRUCT_IN6_PKTINFO
/* define if your struct ip has ip_hl; otherwise assume ip_vhl */
#undef HAVE_STRUCT_IP_IP_HL
@ -373,6 +416,37 @@
/* Define if you have the unsetenv function. not on HP-UX */
#undef HAVE_UNSETENV
/* Define if you have the SSLv2 client and server method functions. not in new openssl */
#undef HAVE_SSLv2_client_method
#undef HAVE_SSLv2_server_method
/* Define if you have the HAVE_SSL_CTX_set_default_verify_paths function */
#undef HAVE_SSL_CTX_set_default_verify_paths
/* Define if you have the SSLv3 client and server method functions. not in new openssl */
#undef HAVE_SSLv3_client_method
#undef HAVE_SSLv3_server_method
/* Define if you have the SSLv3 client and server method functions with rollback to v2 */
#undef HAVE_SSLv23_client_method
#undef HAVE_SSLv23_server_method
/* Define if you have the TLSv1.0 client and server method functions */
#undef HAVE_TLSv1_client_method
#undef HAVE_TLSv1_server_method
/* Define if you have the TLSv1.1 client and server method functions */
#undef HAVE_TLSv1_1_client_method
#undef HAVE_TLSv1_1_server_method
/* Define if you have the TLSv1.2 client and server method functions */
#undef HAVE_TLSv1_2_client_method
#undef HAVE_TLSv1_2_server_method
/* Define if you have the DTLSv1 client and server method functions */
#undef HAVE_DTLSv1_client_method
#undef HAVE_DTLSv1_server_method
/* Define if you have the flock function */
#undef HAVE_FLOCK
@ -386,7 +460,7 @@
#undef HAVE_UNLOCKPT
/* Define if you have the ptsname function */
#undef HAVE_PTSNAME
#undef HAVE_PROTOTYPE_LIB_ptsname
/* Define if you have the /dev/ptmx pseudo terminal multiplexer */
#undef HAVE_DEV_PTMX
@ -394,9 +468,18 @@
/* Define if you have the /dev/ptc pseudo terminal multiplexer */
#undef HAVE_DEV_PTC
/* Define if you have the cfmakeraw() function */
#undef HAVE_CFMAKERAW
/* Define if you have the long long type */
#undef HAVE_TYPE_LONGLONG
/* is sig_atomic_t declared */
#undef HAVE_TYPE_SIG_ATOMIC_T
/* is bool already typedef'd? */
#undef HAVE_TYPE_BOOL
/* is socklen_t already typedef'd? */
#undef HAVE_TYPE_SOCKLEN
@ -421,6 +504,9 @@
/* is uint64_t already defined? */
#undef HAVE_TYPE_UINT64
/* Define if snprintf() returns required len on truncation (C-99 conform) */
#undef HAVE_C99_SNPRINTF
/* Define if you have the printf "Z" modifier */
#undef HAVE_FORMAT_Z
@ -450,10 +536,10 @@
#undef HAVE_BASIC_TIME_T
#undef HAVE_BASIC_OFF_T
#undef HAVE_BASIC_OFF64_T
#undef HAVE_BASIC_DEV_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
@ -471,12 +557,19 @@
#undef HAVE_TYPEOF_RLIM_MAX
#undef HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN
/* 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 HAVE_SETGRENT
#undef HAVE_GETGRENT
#undef HAVE_ENDGRENT
#undef HAVE_GETGROUPLIST
#undef WITH_HELP
#undef WITH_STDIO
#undef WITH_FDNUM
@ -519,4 +612,6 @@
#undef WITH_MSGLEVEL
#define BUILD_DATE __DATE__ " " __TIME__
#endif /* !defined(__config_h_included) */

1
configure.ac Symbolic link
View File

@ -0,0 +1 @@
configure.in

View File

@ -1,5 +1,5 @@
nl source: configure.in
dnl Copyright Gerhard Rieger 2001-2009
dnl source: configure.in
dnl Copyright Gerhard Rieger
dnl Published under the GNU General Public License V.2, see file COPYING
dnl Process this file with autoconf to produce a configure script.
@ -44,18 +44,24 @@ AC_LANG_COMPILER_REQUIRE()
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -D_GNU_SOURCE -Wall -Wno-parentheses"
ERRONWARN="-Werror -O0"
elif test "$CC" = "clang"; then
CFLAGS="$CFLAGS -D_GNU_SOURCE -Wall -Wno-parentheses"
ERRONWARN="-Werror -O0"
#elif Sun Studio
# ERRONWARN="-errwarn"
else
# Sun Studio?
ERRONWARN="-errwarn"
ERRONWARN=
fi
export CFLAGS
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(stdbool.h)
AC_CHECK_HEADERS(inttypes.h)
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(pwd.h grp.h stdint.h sys/types.h poll.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)
AC_CHECK_HEADERS(netinet/ip.h, [], [], [AC_INCLUDES_DEFAULT
@ -64,8 +70,7 @@ AC_CHECK_HEADERS(netinet/ip.h, [], [], [AC_INCLUDES_DEFAULT
#include <netinet/in_systm.h>
#endif]) # Solaris prerequisites for netinet/ip.h
AC_CHECK_HEADERS(netinet/tcp.h)
AC_CHECK_HEADERS(netinet6/in6.h) # found on OpenBSD, used for IPV6_*
AC_CHECK_HEADER(net/if.h, [], [], [AC_INCLUDES_DEFAULT
AC_CHECK_HEADER(net/if.h, AC_DEFINE(HAVE_NET_IF_H), [], [AC_INCLUDES_DEFAULT
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif]) # Mac OS X requires including sys/socket.h
@ -75,11 +80,18 @@ AC_HEADER_RESOLV()
AC_CHECK_HEADERS(termios.h linux/if_tun.h)
AC_CHECK_HEADERS(net/if_dl.h)
AC_CHECK_HEADERS(linux/types.h linux/errqueue.h)
AC_CHECK_HEADERS(linux/types.h)
AC_CHECK_HEADER(linux/errqueue.h, AC_DEFINE(HAVE_LINUX_ERRQUEUE_H), [], [#include <sys/time.h>
#include <linux/types.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(util.h bsd/libutil.h libutil.h sys/stropts.h regex.h)
AC_CHECK_HEADERS(linux/fs.h linux/ext2_fs.h)
dnl Checks for setgrent, getgrent and endgrent.
AC_CHECK_FUNCS(setgrent getgrent endgrent)
dnl Checks for getgrouplist() /* BSD */
AC_CHECK_FUNCS(getgrouplist)
AC_CHECK_FUNCS(cfmakeraw)
dnl Link libresolv if necessary (for Mac OS X)
AC_SEARCH_LIBS([res_9_init], [resolv])
@ -90,6 +102,24 @@ AC_CHECK_FUNC(hstrerror, , AC_CHECK_LIB(resolv, hstrerror, [LIBS="$LIBS -lresol
AC_CHECK_FUNC(gethostent, , AC_CHECK_LIB(nsl, gethostent))
AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt))
dnl Check for function prototype and in lib
dnl arg1: function name
dnl arg2: required include files beyond sysincludes.h
define(AC_CHECK_PROTOTYPE_LIB,[
AC_MSG_CHECKING(for $1 prototype)
AC_CACHE_VAL(sc_cv_have_prototype_lib_$1,
[CFLAGS1="$CFLAGS"; CFLAGS="$ERRONWARN -Wall $CFLAGS1";
AC_TRY_LINK([#include "sysincludes.h"
$2],[return(&$1==(void *)&$1);],
[sc_cv_have_prototype_lib_$1=yes],
[sc_cv_have_prototype_lib_$1=no]);
CFLAGS="$CFLAGS1"])
if test $sc_cv_have_prototype_lib_$1 = yes; then
AC_DEFINE(HAVE_PROTOTYPE_LIB_$1)
fi
AC_MSG_RESULT($sc_cv_have_prototype_lib_$1)
])
dnl Check for hstrerror prototype
AC_MSG_CHECKING(for hstrerror prototype)
@ -213,6 +243,27 @@ if test "$WITH_IP6"; then
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif])
AC_CHECK_HEADERS(netinet6/in6.h) # found on OpenBSD and Lion, used for IPV6_*
AC_MSG_CHECKING(if __APPLE_USE_RFC_2292 is helpful)
AC_CACHE_VAL(ac_cv_apple_use_rfc_2292,
[AC_TRY_COMPILE(,[#ifndef IPV6_HOPOPTS
murks;
#endif],
[ac_cv_apple_use_rfc_2292=no],
[AC_TRY_COMPILE([#define __APPLE_USE_RFC_2292],
[#ifndef IPV6_HOPOPTS
murks;
#endif],
[ac_cv_apple_use_rfc_2292=yes],
[ac_cv_apple_use_rfc_2292=no]
)]
)])
if test "$ac_cv_apple_use_rfc_2292" = yes; then
AC_DEFINE(__APPLE_USE_RFC_2292)
fi
AC_MSG_RESULT($ac_cv_apple_use_rfc_2292)
fi
AC_MSG_CHECKING(whether to include raw IP support)
@ -224,13 +275,13 @@ AC_ARG_ENABLE(rawip, [ --disable-rawip disable raw IP support],
[AC_DEFINE(WITH_RAWIP) AC_MSG_RESULT(yes)])
AC_MSG_CHECKING(whether to include generic socket support)
AC_ARG_ENABLE(rawsocket, [ --disable-genericsocket disable generic socket support],
AC_ARG_ENABLE(genericsocket, [ --disable-genericsocket disable generic socket support],
[case "$enableval" in
no) AC_MSG_RESULT(no);;
*) AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes);;
esac],
[AC_DEFINE(WITH_GENERICSOCKET) AC_MSG_RESULT(yes)])
AC_MSG_CHECKING(whether to include raw network interface support)
AC_MSG_CHECKING(whether to include generic network interface support)
AC_ARG_ENABLE(interface, [ --disable-interface disable network interface support],
[case "$enableval" in
no) AC_MSG_RESULT(no); WITH_INTERFACE= ;;
@ -247,7 +298,12 @@ if test "$WITH_INTERFACE"; then
AC_CHECK_HEADER(netinet/if_ether.h,
AC_DEFINE(HAVE_NETINET_IF_ETHER_H),
[WITH_INTERFACE=;
AC_MSG_WARN([include file netinet/if_ether.h not found, disabling interface])])
AC_MSG_WARN([include file netinet/if_ether.h not found, disabling interface])],
[AC_INCLUDES_DEFAULT
#if HAVE_NET_IF_H && HAVE_NETINET_IN_H
#include <net/if.h>
#include <netinet/in.h>
#endif])
fi
if test "$WITH_INTERFACE"; then
AC_DEFINE(WITH_INTERFACE)
@ -514,16 +570,18 @@ fi
# check for fips support
AC_MSG_CHECKING(whether to include openssl fips support)
AC_ARG_ENABLE(fips, [ --disable-fips disable OpenSSL FIPS support],
AC_ARG_ENABLE(fips, [ --enable-fips enable OpenSSL FIPS support],
[ case "$enableval" in
no) AC_MSG_RESULT(no); WITH_FIPS= ;;
*) AC_MSG_RESULT(yes); WITH_FIPS=1 ;;
yes) AC_MSG_RESULT(yes); WITH_FIPS=1 ;;
*) AC_MSG_RESULT(no); WITH_FIPS= ;;
esac],
[ AC_MSG_RESULT(yes); WITH_FIPS=1 ])
[ AC_MSG_RESULT(no); WITH_FIPS= ])
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_CHECK_PROG(HAVE_FIPSLD, fipsld, 1)
if test "$sc_cv_have_openssl_ssl_h" != "yes" -o "$sc_cv_have_libssl" != "yes" -o ! "$HAVE_FIPSLD";
then
AC_MSG_WARN([not all components of OpenSSL found, disabling FIPS]);
WITH_FIPS=
fi
@ -533,10 +591,11 @@ if test -n "$WITH_FIPS"; then
fi
if test -n "$WITH_FIPS"; then
AC_MSG_NOTICE(checking for components of OpenSSL FIPS)
AC_MSG_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 <stddef.h>
#include <openssl/fips.h>],[;],
[sc_cv_have_openssl_fips_h=yes; ],
[sv_cv_have_openssl_fips_h=no
@ -680,12 +739,26 @@ 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(putenv select poll socket strtod strtol)
AC_CHECK_FUNCS(strtoul uname getpgid getsid getaddrinfo)
AC_CHECK_FUNCS(getipnodebyname setgroups inet_aton memrchr)
AC_CHECK_FUNCS(if_indextoname)
AC_CHECK_FUNCS(setgroups inet_aton)
AC_CHECK_FUNCS()
AC_CHECK_FUNCS(grantpt unlockpt ptsname)
AC_CHECK_FUNCS(grantpt unlockpt)
# GR AC_CHECK_FUNCS only checks linking, not prototype. This may lead to implicit
# function declarations and to SIGSEGV on systems with 32bit int and 64bit pointer
###################################
# check for prototype and existence of functions that return a pointer
# defines in config.h: HAVE_PROTOTYPE_LIB_$1
AC_CHECK_PROTOTYPE_LIB(strdup)
AC_CHECK_PROTOTYPE_LIB(strerror)
AC_CHECK_PROTOTYPE_LIB(strstr)
AC_CHECK_PROTOTYPE_LIB(getipnodebyname)
AC_CHECK_PROTOTYPE_LIB(memrchr)
AC_CHECK_PROTOTYPE_LIB(if_indextoname)
AC_CHECK_PROTOTYPE_LIB(ptsname)
AC_MSG_CHECKING(for long long)
@ -698,6 +771,21 @@ if test $sc_cv_type_longlong = yes; then
fi
AC_MSG_RESULT($sc_cv_type_longlong)
AC_CHECK_TYPE(sig_atomic_t,AC_DEFINE(HAVE_TYPE_SIG_ATOMIC_T),,[#include "sysincludes.h"])
AC_MSG_CHECKING(for bool)
AC_CACHE_VAL(sc_cv_type_bool,
[AC_TRY_COMPILE([#ifdef HAVE_STDBOOL_H
#include <stdbool.h>
#endif],
[bool b;],
[sc_cv_type_bool=yes],
[sc_cv_type_bool=no])])
if test $sc_cv_type_bool = yes; then
AC_DEFINE(HAVE_TYPE_BOOL)
fi
AC_MSG_RESULT($sc_cv_type_bool)
# following builtin macro does not check unistd.h and sys/socket.h where
# socklen_t might be defined
#AC_CHECK_TYPE(socklen_t, int)
@ -840,6 +928,7 @@ AC_TRY_COMPILE([#include <sys/types.h>
AC_MSG_CHECKING(for sa_family_t)
AC_CACHE_VAL(sc_cv_type_sa_family_t,
[AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>],[sa_family_t s;],
[sc_cv_type_sa_family_t=yes],
[sc_cv_type_sa_family_t=no])])
@ -848,6 +937,22 @@ if test $sc_cv_type_sa_family_t = yes; then
fi
AC_MSG_RESULT($sc_cv_type_sa_family_t)
AC_MSG_CHECKING(for struct sock_extended_err)
AC_CACHE_VAL(sc_cv_struct_sock_extended_err,
[AC_TRY_COMPILE([#include <linux/types.h>
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#endif
#if HAVE_LINUX_ERRQUEUE_H
#include <linux/errqueue.h>
#endif],[struct sock_extended_err s;],
[sc_cv_struct_sock_extended_err=yes],
[sc_cv_struct_sock_extended_err=no])])
if test $sc_cv_struct_sock_extended_err = yes; then
AC_DEFINE(HAVE_STRUCT_SOCK_EXTENDED_ERR)
fi
AC_MSG_RESULT($sc_cv_struct_sock_extended_err)
AC_MSG_CHECKING(for struct sigaction.sa_sigaction)
AC_CACHE_VAL(sc_cv_struct_sigaction_sa_sigaction,
[AC_TRY_COMPILE([#include <signal.h>],[struct sigaction s;s.sa_sigaction=0;],
@ -877,10 +982,11 @@ AC_CACHE_VAL(ac_cv_ispeed_offset,
[conftestspeedoff="conftestspeedoff.out"
AC_TRY_RUN([
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <termios.h>
#include <string.h>
main(){
int main(){
struct termios t;
FILE *f;
if ((f=fopen("$conftestspeedoff","w"))==NULL){
@ -920,6 +1026,69 @@ if test $ac_cv_svid3 = yes; then
fi
AC_MSG_RESULT($ac_cv_svid3)
# Openindiana needs _XPG4_2 for CMSG stuff
AC_MSG_CHECKING(if _XPG4_2 is helpful)
AC_CACHE_VAL(ac_cv_xpg4_2,
[AC_TRY_LINK([#include <sys/socket.h>],
[int i=CMSG_DATA(0)],
[ac_cv_xpg4_2=no],
[AC_TRY_LINK([#define _XPG4_2 1
#include <sys/socket.h>],
[int i=CMSG_DATA(0)],
[ac_cv_xpg4_2=yes],
[ac_cv_xpg4_2=no]
)]
)])
if test $ac_cv_xpg4_2 = yes; then
AC_DEFINE(_XPG4_2)
fi
AC_MSG_RESULT($ac_cv_xpg4_2)
# When on Openindiana _XPG4_2 is defined (see above)
# we also need to define __EXTENSIONS__ for basic stuff.
# Note that <sys/procset.h> is important on Openindiana
# but does not exist on Linux
if test "$ac_cv_xpg4_2" = yes; then
AC_MSG_CHECKING(if __EXTENSIONS__ is helpful)
AC_CACHE_VAL(ac_cv___extensions__,
[AC_TRY_COMPILE([#include <sys/procset.h>],
[procset_t *s=0;],
[ac_cv___extensions__=no],
[AC_TRY_COMPILE([#define __EXTENSIONS__ 1
#include <sys/procset.h>],
[procset_t *s=0;],
[ac_cv___extensions__=yes],
[ac_cv___extensions__=no]
)]
)])
if test $ac_cv___extensions__ = yes; then
AC_DEFINE(__EXTENSIONS__)
fi
AC_MSG_RESULT($ac_cv___extensions__)
fi
# When on Openindiana __EXTENSIONS__ is defined (see above)
# _POSIX_PTHREAD_SEMANTICS must be defined for standard ctime_r()
if test "$ac_cv___extensions__" = yes; then
AC_MSG_CHECKING(if _POSIX_PTHREAD_SEMANTICS is helpful)
AC_CACHE_VAL(ac_cv__posix_pthread_semantics,
[AC_TRY_COMPILE([#include <time.h>],
[char *s = ctime_r(0,0);],
[ac_cv__posix_pthread_semantics=no],
[AC_TRY_COMPILE([#define _POSIX_PTHREAD_SEMANTICS 1
#include <time.h>],
[char *s = ctime_r(0,0);],
[ac_cv__posix_pthread_semantics=yes],
[ac_cv__posix_pthread_semantics=no]
)]
)])
if test $ac_cv__posix_pthread_semantics = yes; then
AC_DEFINE(_POSIX_PTHREAD_SEMANTICS)
fi
AC_MSG_RESULT($ac_cv__posix_pthread_semantics)
fi
# struct timespec
AC_MSG_CHECKING(for struct timespec)
@ -1159,6 +1328,33 @@ if test $sc_cv_struct_in_pktinfo = yes; then
fi
AC_MSG_RESULT($sc_cv_struct_in_pktinfo)
if test $sc_cv_struct_in_pktinfo = 'yes'; then
dnl check for component ipi_spec_dst in struct in_pktinfo
AC_MSG_CHECKING(for ipi_spec_dst in struct in_pktinfo)
AC_CACHE_VAL(sc_cv_pktinfo_ipi_spec_dst,
[AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>],[struct in_pktinfo s; s.ipi_spec_dst],
[sc_cv_pktinfo_ipi_spec_dst=yes],
[sc_cv_pktinfo_ipi_spec_dst=no])])
if test $sc_cv_pktinfo_ipi_spec_dst = yes; then
AC_DEFINE(HAVE_PKTINFO_IPI_SPEC_DST)
fi
AC_MSG_RESULT($sc_cv_pktinfo_ipi_spec_dst)
fi
dnl check for struct in6_pktinfo
AC_MSG_CHECKING(for struct in6_pktinfo)
AC_CACHE_VAL(sc_cv_struct_in6_pktinfo,
[AC_TRY_COMPILE([#include "sysincludes.h"],
[struct in6_pktinfo s;],
[sc_cv_struct_in6_pktinfo=yes],
[sc_cv_struct_in6_pktinfo=no])])
if test $sc_cv_struct_in6_pktinfo = yes; then
AC_DEFINE(HAVE_STRUCT_IN6_PKTINFO)
fi
AC_MSG_RESULT($sc_cv_struct_in6_pktinfo)
dnl check for ip_hl in struct ip
AC_MSG_CHECKING(for struct ip.ip_hl)
AC_CACHE_VAL(sc_cv_struct_ip_ip_hl,
@ -1221,6 +1417,9 @@ AC_CHECK_LIB(bsd, openpty,
AC_CHECK_LIB(util, openpty,
[LIBS="-lutil $LIBS"; AC_DEFINE(HAVE_OPENPTY)])
AC_CHECK_LIB(rt, clock_gettime,
[LIBS="-lrt $LIBS"; AC_DEFINE(HAVE_CLOCK_GETTIME)])
dnl Search for flock()
# with Linux it's in libc, with AIX in libbsd
AC_CHECK_FUNC(flock, AC_DEFINE(HAVE_FLOCK),
@ -1233,22 +1432,63 @@ AC_CHECK_FUNC(setenv, AC_DEFINE(HAVE_SETENV),
dnl Search for unsetenv()
AC_CHECK_FUNC(unsetenv, AC_DEFINE(HAVE_UNSETENV))
dnl Search for SSLv2_client_method, SSLv2_server_method
AC_CHECK_FUNC(SSLv2_client_method, AC_DEFINE(HAVE_SSLv2_client_method), AC_CHECK_LIB(crypt, SSLv2_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(SSLv2_server_method, AC_DEFINE(HAVE_SSLv2_server_method), AC_CHECK_LIB(crypt, SSLv2_server_method, [LIBS=-lcrypt $LIBS]))
dnl
AC_CHECK_FUNC(SSL_CTX_set_default_verify_paths, AC_DEFINE(HAVE_SSL_CTX_set_default_verify_paths))
AC_CHECK_FUNC(SSLv3_client_method, AC_DEFINE(HAVE_SSLv3_client_method), AC_CHECK_LIB(crypt, SSLv3_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(SSLv3_server_method, AC_DEFINE(HAVE_SSLv3_server_method), AC_CHECK_LIB(crypt, SSLv3_server_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(SSLv23_client_method, AC_DEFINE(HAVE_SSLv23_client_method), AC_CHECK_LIB(crypt, SSLv23_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(SSLv23_server_method, AC_DEFINE(HAVE_SSLv23_server_method), AC_CHECK_LIB(crypt, SSLv23_server_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_client_method, AC_DEFINE(HAVE_TLSv1_client_method), AC_CHECK_LIB(crypt, TLSv1_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_server_method, AC_DEFINE(HAVE_TLSv1_server_method), AC_CHECK_LIB(crypt, TLSv1_server_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_1_client_method, AC_DEFINE(HAVE_TLSv1_1_client_method), AC_CHECK_LIB(crypt, TLSv1_1_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_1_server_method, AC_DEFINE(HAVE_TLSv1_1_server_method), AC_CHECK_LIB(crypt, TLSv1_1_server_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_2_client_method, AC_DEFINE(HAVE_TLSv1_2_client_method), AC_CHECK_LIB(crypt, TLSv1_2_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(TLSv1_2_server_method, AC_DEFINE(HAVE_TLSv1_2_server_method), AC_CHECK_LIB(crypt, TLSv1_2_server_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(DTLSv1_client_method, AC_DEFINE(HAVE_DTLSv1_client_method), AC_CHECK_LIB(crypt, DTLSv1_client_method, [LIBS=-lcrypt $LIBS]))
AC_CHECK_FUNC(DTLSv1_server_method, AC_DEFINE(HAVE_DTLSv1_server_method), AC_CHECK_LIB(crypt, DTLSv1_server_method, [LIBS=-lcrypt $LIBS]))
dnl Run time checks
AC_MSG_CHECKING(if printf has Z modifier)
AC_CACHE_VAL(ac_cv_have_z_modifier,
AC_MSG_CHECKING(if snprintf conforms to C99)
AC_CACHE_VAL(ac_cv_have_c99_snprintf,
[AC_TRY_RUN([
#include <stdio.h>
main(){
#include <stdlib.h>
int main(void){
char s[2];
exit(snprintf(s,2,"ab")!=2);
}],
[ac_cv_have_c99_snprintf=yes],
[ac_cv_have_c99_snprintf=no],
[ac_cv_have_c99_snprintf=no])])
if test $ac_cv_have_c99_snprintf = yes; then
AC_DEFINE(HAVE_C99_SNPRINTF)
fi
AC_MSG_RESULT($ac_cv_have_c99_snprintf)
AC_MSG_CHECKING(if printf has Z modifier)
AC_CACHE_VAL(ac_cv_have_z_modifier,
if test "$cc" = gcc; then
[AC_TRY_RUN([
#include <stdlib.h>
#include <stdio.h>
int main(void){
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])])
[ac_cv_have_z_modifier=no])]
else ac_cv_have_z_modifier=no
fi
)
if test $ac_cv_have_z_modifier = yes; then
AC_DEFINE(HAVE_FORMAT_Z)
fi
@ -1264,10 +1504,11 @@ AC_CACHE_CHECK(shift offset of $1, $2,
conftestoffset="conftestoffset.out"
AC_TRY_RUN([
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <termios.h>
#include <string.h>
main(){
int main(){
unsigned int i,n=$1;
FILE *f;
if ((f=fopen("$conftestoffset","w"))==NULL){
@ -1286,10 +1527,13 @@ AC_CACHE_CHECK(shift offset of $1, $2,
],
[$2=`cat $conftestoffset`],
[$2=-1],
[AC_MSG_RESULT(please determine $1_SHIFT manually)]
[$2=-1]
)
LIBS="$LIBS1"])
AC_DEFINE_UNQUOTED($1_SHIFT, ${$2})
if test "$2" = -1; then
AC_MSG_WARN(please determine $1_SHIFT manually)
fi
])
AC_SHIFT_OFFSET(CRDLY, sc_cv_sys_crdly_shift)
@ -1297,6 +1541,116 @@ 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 If possible we try to compile simple test code and get no warning only with
dnl the matching type.
dnl If this method does not seem to work we run test programs that print the
dnl length and signedness of the type.
dnl do we have a -Werror option?
dnl Does the test code compile with -Werror when types fit?
CHANCE_TO_TYPECHECK=1
CFLAGS1="$CFLAGS"; CFLAGS="$ERRONWARN $(echo "$CFLAGS1" | sed -e 's@-Wall@@g')"
AC_TRY_COMPILE([#include <stdlib.h>],[int u; int v; exit(&u==&v);],,CHANCE_TO_TYPECHECK=0)
CFLAGS="$CFLAGS1"
dnl Does the test code compile without -Werror when types do not fit?
if test "$CHANCE_TO_TYPECHECK" -ne 0; then
AC_TRY_COMPILE([#include <stdlib.h>],[int u; unsigned int v; exit(&u==&v);],,CHANCE_TO_TYPECHECK=0)
fi
dnl Does the test code fail to compile with -Werror when types do not fit?
if test "$CHANCE_TO_TYPECHECK" -ne 0; then
CFLAGS1="$CFLAGS"; CFLAGS="$ERRONWARN $(echo "$CFLAGS1" | sed -e 's@-Wall@@g')"
AC_TRY_COMPILE([#include <stdlib.h>],[int u; unsigned int v; exit(&u==&v);],CHANCE_TO_TYPECHECK=0,)
CFLAGS="$CFLAGS1"
fi
if test "$CHANCE_TO_TYPECHECK" -ne 0; then
AC_MSG_NOTICE(using compile -Werror method to find basic types)
else
AC_MSG_NOTICE(using code run method to find basic types)
fi
dnl see AC_BASIC_TYPE
define(AC_BASIC_TYPE_GCC,[
AC_CACHE_CHECK(for equivalent simple type of $2, $4,
[CFLAGS1="$CFLAGS"; CFLAGS="$ERRONWARN $(echo "$CFLAGS1" | sed -e 's@-Wall@@g')"
dnl echo "echo: trying short for $2" >&2
AC_TRY_COMPILE([$1],[$2 u; short v; return(&u==&v);],
[$4="1 /* short */"],
[AC_TRY_COMPILE([$1],[$2 u; unsigned short v; return(&u==&v);],
[$4="2 /* unsigned short */"],
[AC_TRY_COMPILE([$1],[$2 u; int v; return(&u==&v);],
[$4="3 /* int */"],
[AC_TRY_COMPILE([$1],[$2 u; unsigned int v; return(&u==&v);],
[$4="4 /* unsigned int */"],
[AC_TRY_COMPILE([$1],[$2 u; long v; return(&u==&v);],
[$4="5 /* long */"],
[AC_TRY_COMPILE([$1],[$2 u; unsigned long v; return(&u==&v);],
[$4="6 /* unsigned long */"],
[AC_TRY_COMPILE([$1],[$2 u; long long v; return(&u==&v);],
[$4="7 /* long long */"],
[AC_TRY_COMPILE([$1],[$2 u; unsigned long long v; return(&u==&v);],
[$4="8 /* unsigned long long */"],
[$4="0 /* unknown, taking default */"
]) ]) ]) ]) ]) ]) ]) ])
CFLAGS="$CFLAGS1" ])
AC_DEFINE_UNQUOTED($3, ${$4})
])
dnl see AC_BASIC_TYPE
define(AC_BASIC_TYPE_OTHER,[
AC_CACHE_CHECK(for equivalent simple type of $2, $4,
[AC_TRY_RUN([
$1
int main() { return!(sizeof($2)==sizeof(short));}],
# same length as short
AC_TRY_RUN([
$1
int main() { $2 x=-1; return !(x<0);}],
[$4="1 /* short */"],
[$4="2 /* unsigned short */"]),
# length differs from short, try others
AC_TRY_RUN([
$1
int main() { return!(sizeof($2)==sizeof(int));}],
# same length as int
AC_TRY_RUN([
$1
int main() { $2 x=-1; return !(x<0);}],
[$4="3 /* int */"],
[$4="4 /* unsigned int */"]),
# length differs from int, try others
AC_TRY_RUN([
$1
int main() { return !(sizeof($2)==sizeof(long));}],
# same length as long
AC_TRY_RUN([
$1
int main() { $2 x=-1; return !(x<0);}],
[$4="5 /* long */"],
[$4="6 /* unsigned long */"] ),
# length differs from long, try others
AC_TRY_RUN([
$1
int main() { return !(sizeof($2)==sizeof(long long));}],
# same length as long long
AC_TRY_RUN([
$1
int main() { $2 x=-1; return !(x<0);}],
[$4="7 /* long long */"],
[$4="8 /* unsigned long long */"] ),
[$4="0 /* unknown */"]
)
)
)
)
])
AC_DEFINE_UNQUOTED($3, ${$4})
])
dnl find what physical type (basic C type) is equivalent to the given type.
dnl arg1: include file(s)
dnl arg2: type name
@ -1305,28 +1659,91 @@ 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,
if test "$CHANCE_TO_TYPECHECK" -ne 0; then
AC_BASIC_TYPE_GCC([$1],[$2],[$3],[$4])
else
AC_BASIC_TYPE_OTHER([$1],[$2],[$3],[$4])
fi
])
dnl See AC_TYPEOF_COMPONENT
dnl This version is for compilers with -Werror or so: gcc, clang, Sun Studio?
define(AC_TYPEOF_COMPONENT_GCC,[
AC_CACHE_CHECK(for basic type of $2.$3, $5,
[CFLAGS1="$CFLAGS"; CFLAGS="$ERRONWARN $(echo "$CFLAGS1" | sed -e 's@-Wall@@g')"
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 */"
AC_TRY_COMPILE([$1],[$2 u;short v; return(&u.$3==&v);],
[$5="1 /* short */"],
[AC_TRY_COMPILE([$1],[$2 u; unsigned short v; return(&u.$3==&v);],
[$5="2 /* unsigned short */"],
[AC_TRY_COMPILE([$1],[$2 u; int v; return(&u.$3==&v);],
[$5="3 /* int */"],
[AC_TRY_COMPILE([$1],[$2 u; unsigned int v; return(&u.$3==&v);],
[$5="4 /* unsigned int */"],
[AC_TRY_COMPILE([$1],[$2 u; long v; return(&u.$3==&v);],
[$5="5 /* long */"],
[AC_TRY_COMPILE([$1],[$2 u; unsigned long v; return(&u.$3==&v);],
[$5="6 /* unsigned long */"],
[AC_TRY_COMPILE([$1],[$2 u; long long v; return(&u.$3==&v);],
[$5="7 /* long long */"],
[AC_TRY_COMPILE([$1],[$2 u; unsigned long long v; return(&u.$3==&v);],
[$5="8 /* unsigned long long */"],
[$5="0 /* unknown, taking default */"
]) ]) ]) ]) ]) ]) ]) ])
CFLAGS="$CFLAGS1" ])
AC_DEFINE_UNQUOTED($3, ${$4})
AC_DEFINE_UNQUOTED($4, ${$5})
])
dnl See AC_TYPEOF_COMPONENT
dnl This version is for compilers with no -Werror or so
define(AC_TYPEOF_COMPONENT_OTHER,[
AC_CACHE_CHECK(for basic type of $2.$3, $5,
[AC_TRY_RUN([
$1
int main() { $2 x; return!(sizeof(x.$3)==sizeof(short));}],
# same length as short
AC_TRY_RUN([
$1
int main() { $2 x; x.$3=-1; return !(x.$3<0);}],
[$5="1 /* short */"],
[$5="2 /* unsigned short */"]),
# length differs from short, try others
AC_TRY_RUN([
$1
int main() { $2 x; return!(sizeof(x.$3)==sizeof(int));}],
# same length as int
AC_TRY_RUN([
$1
int main() { $2 x; x.$3=-1; return !(x.$3<0);}],
[$5="3 /* int */"],
[$5="4 /* unsigned int */"]),
# length differs from int, try others
AC_TRY_RUN([
$1
int main() { $2 x; return !(sizeof(x.$3)==sizeof(long));}],
# same length as long
AC_TRY_RUN([
$1
int main() { $2 x; x.$3=-1; return !(x.$3<0);}],
[$5="5 /* long */"],
[$5="6 /* unsigned long */"] ),
# length differs from long, try others
AC_TRY_RUN([
$1
int main() { $2 x; return !(sizeof(x.$3)==sizeof(long long));}],
# same length as long long
AC_TRY_RUN([
$1
int main() { x $2; x.$3=-1; return !(x.$3<0);}],
[$5="7 /* long long */"],
[$5="8 /* unsigned long long */"] ),
[$5="0 /* unknown */"]
)
)
)
)
])
AC_DEFINE_UNQUOTED($4, ${$5})
])
dnl find what physical type (basic C type) describes the given struct or union
@ -1337,28 +1754,11 @@ 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="$ERRONWARN $(echo "$CFLAGS1" | sed -e 's@-Wall@@g')"
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})
if test "$CHANCE_TO_TYPECHECK" -ne 0; then
AC_TYPEOF_COMPONENT_GCC([$1],[$2],[$3],[$4],[$5])
else
AC_TYPEOF_COMPONENT_OTHER([$1],[$2],[$3],[$4],[$5])
fi
])
AC_BASIC_TYPE([#include <stdlib.h>], size_t, HAVE_BASIC_SIZE_T, sc_cv_type_sizet_basic)
@ -1388,7 +1788,8 @@ 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_BASIC_TYPE([#include <sys/stat.h>], dev_t, HAVE_BASIC_DEV_T, sc_cv_type_dev_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)
@ -1411,6 +1812,8 @@ AC_TYPEOF_COMPONENT([#include <sys/types.h>
#include <sys/resource.h>],
struct rlimit, rlim_max, HAVE_TYPEOF_RLIM_MAX, sc_cv_type_rlimit_rlimmax_basic)
# Fedora-19 doc says it is socklen_t which is equivalent to unsigned int, but it is equivalent to size_t (x86_64)
AC_TYPEOF_COMPONENT([#include "sysincludes.h"], struct cmsghdr, cmsg_len, HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN, sc_cv_typeof_struct_cmsghdr_cmsg_len)
### snprintf, vsnprintf
@ -1459,7 +1862,7 @@ AC_ARG_ENABLE(libwrap, [ --disable-libwrap disable libwrap support],
#
# check if we find the components of libwrap ("tcpd" "tcpwrappers")
if test -n "$WITH_LIBWRAP"; then
AC_MSG_NOTICE(checking for components of libwrap)
AC_MSG_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>
@ -1527,7 +1930,7 @@ fi
# check of hosts_allow_table
if test -n "$WITH_LIBWRAP"; then
AC_MSG_CHECKING(checking for hosts_allow_table)
AC_MSG_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="";],
@ -1559,4 +1962,34 @@ if test -n "$WITH_FIPS"; then
fi
AC_SUBST(FIPSLD_CC)
# autoconf does not seem to provide AC_CHECK_VAR or so
# thus we have to check by foot
AC_MSG_CHECKING(for declaration of environ)
AC_CACHE_VAL(sc_cv_decl_environ,
[AC_TRY_COMPILE([#include <unistd.h>],[char **s = environ;],
[sc_cv_decl_environ=yes],
[sc_cv_decl_environ=no])])
if test $sc_cv_decl_environ = yes; then
AC_DEFINE(HAVE_DECL_ENVIRON)
fi
AC_MSG_RESULT($sc_cv_decl_environ)
# on some systems environ exists but not the declaration
AC_MSG_CHECKING(for var environ)
AC_CACHE_VAL(sc_cv_var_environ,
[AC_TRY_COMPILE([],[extern char **environ; char **s = environ;],
[sc_cv_var_environ=yes],
[sc_cv_var_environ=no])])
if test $sc_cv_var_environ = yes; then
AC_DEFINE(HAVE_VAR_ENVIRON)
fi
AC_MSG_RESULT($sc_cv_var_environ)
# allow BUILD_DATE to be externally set for build reproducibility
if test "$BUILD_DATE"; then
AC_DEFINE_UNQUOTED(BUILD_DATE, ["$BUILD_DATE"])
else
AC_DEFINE(BUILD_DATE, [__DATE__" "__TIME__])
fi
AC_OUTPUT(Makefile)

View File

@ -1,12 +1,16 @@
/* source: dalan.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#if HAVE_STDBOOL_H
#include <stdbool.h>
#endif
#include <ctype.h>
#include "dalan.h"

View File

@ -93,8 +93,12 @@ reasons: you are not on Linux or are using an older version of socat.
<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
<p>indicates that your kernel either needs to load the tun module or does not
have TUN/TAP support compiled in. Try to load the module:</p>
<span class="frame"><span class="shell">modprobe tun</span></span>
<p>and check
for /dev/net/tun. If that does not succeed you need to
rebuild your kernel with the appropriate configuration (probably under
<b>Device driver / Network device support / Network device / Universal TUN/TAP</b>).
</p>
@ -140,7 +144,7 @@ transfer.<p>
<p>
Linux TUN/TAP support was added to socat in version 1.6.0.</p>
<p>This document was last modified in April 2009.</p>
<p>This document was last modified in February 2010.</p>
<h2>More info about socat TUN/TAP support</h2>
@ -157,7 +161,7 @@ Linux TUN/TAP support was added to socat in version 1.6.0.</p>
<a href="http://en.wikipedia.org/wiki/TUN/TAP">TUN/TAP on Wikipedia</a><br>
<p>
<small>Copyright: Gerhard Rieger 2007-2009</small><br>
<small>Copyright: Gerhard Rieger 2007-2010</small><br>
<small>License: <a href="http://www.fsf.org/licensing/licenses/fdl.html">GNU Free Documentation License (FDL)</a></small>
</p>

View File

@ -10,7 +10,7 @@ def(Filan)(0)(bf(Filan))
def(procan)(0)(bf(procan))
def(Procan)(0)(bf(Procan))
manpage(socat)(1)(Jan 2010)()()
manpage(socat)(1)()()()
whenhtml(
label(CONTENTS)
@ -119,12 +119,16 @@ dit(bf(tt(-D)))
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".
be selected, default is "daemon". Third party libraries might not obey this
option.
dit(bf(tt(-lf))tt( <logfile>))
Writes messages to <logfile> [link(filename)(TYPE_FILENAME)] instead of
stderr.
stderr. Some third party libraries, in particular libwrap, might not obey
this option.
dit(bf(tt(-ls)))
Writes messages to stderr (this is the default).
Writes messages to stderr (this is the default). Some third party libraries
might not obey this option, in particular libwrap appears to only log to
syslog.
label(option_lp)dit(bf(tt(-lp))tt(<progname>))
Overrides the program name printed in error messages and used for
constructing environment variable names.
@ -261,7 +265,10 @@ 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.
code(creat) cannot be read from. nl()
Flags like O_LARGEFILE cannot be applied. If you need them use
link(OPEN)(ADDRESS_OPEN) with options
link(create)(OPTION_O_CREAT),link(create)(OPTION_O_TRUNC). nl()
<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()
@ -330,7 +337,7 @@ label(ADDRESS_GOPEN)dit(bf(tt(GOPEN:<filename>)))
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
Opens a raw IP socket. Depending on host specification or option link(pf)(OPTION_PROTOCOL_FAMILY), IP protocol 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.
@ -401,7 +408,7 @@ label(ADDRESS_IP6_DATAGRAM)dit(bf(tt(IP6-DATAGRAM:<host>:<protocol>)))
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
Opens a raw IP socket of link(<protocol>)(TYPE_PROTOCOL). Depending on option link(pf)(OPTION_PROTOCOL_FAMILY), IP protocol 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
@ -434,7 +441,7 @@ label(ADDRESS_IP6_RECVFROM)dit(bf(tt(IP6-RECVFROM:<protocol>)))
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
Opens a raw IP socket of link(<protocol>)(TYPE_PROTOCOL). Depending on option link(pf)(OPTION_PROTOCOL_FAMILY), IP protocol 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.
@ -465,7 +472,7 @@ label(ADDRESS_OPEN)dit(bf(tt(OPEN:<filename>)))
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(creat)(OPTION_O_CREAT),
link(excl)(OPTION_EXCL),
link(noatime)(OPTION_O_NOATIME),
link(nofollow)(OPTION_NOFOLLOW),
@ -485,18 +492,30 @@ label(ADDRESS_OPENSSL_CONNECT)dit(bf(tt(OPENSSL:<host>:<port>)))
<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()
NOTE: Up to version 1.7.2.4
the server certificate was only checked for validity against the system
certificate store or link(cafile)(OPTION_OPENSSL_CAFILE) or
link(capath)(OPTION_OPENSSL_CAPATH),
but not for match with the server's name or its IP address.
Since version 1.7.3.0 socat checks the peer certificate for match with the
<host> parameter or the value of the
link(openssl-commonname)(OPTION_OPENSSL_COMMONNAME) option.
Socat tries to match it against the certificates subject commonName,
and the certifications extension subjectAltName DNS names. Wildcards in the
certificate are supported. To specify the TLS SNI hostname to set use the
link(snihost)(OPTION_OPENSSL_SNIHOST) option.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(commonname)(OPTION_OPENSSL_COMMONNAME),
link(snihost)(OPTION_OPENSSL_SNIHOST),
link(cafile)(OPTION_OPENSSL_CAFILE),
link(capath)(OPTION_OPENSSL_CAPATH),
link(certificate)(OPTION_OPENSSL_CERTIFICATE),
link(key)(OPTION_OPENSSL_KEY),
link(compress)(OPTION_OPENSSL_COMPRESS),
link(bind)(OPTION_BIND),
link(pf)(OPTION_PROTOCOL_FAMILY),
link(connect-timeout)(OPTION_CONNECT_TIMEOUT),
@ -520,10 +539,12 @@ label(ADDRESS_OPENSSL_LISTEN)dit(bf(tt(OPENSSL-LISTEN:<port>)))
link(cipher)(OPTION_OPENSSL_CIPHERLIST),
link(method)(OPTION_OPENSSL_METHOD),
link(verify)(OPTION_OPENSSL_VERIFY),
link(commonname)(OPTION_OPENSSL_COMMONNAME)
link(cafile)(OPTION_OPENSSL_CAFILE),
link(capath)(OPTION_OPENSSL_CAPATH),
link(certificate)(OPTION_OPENSSL_CERTIFICATE),
link(key)(OPTION_OPENSSL_KEY),
link(compress)(OPTION_OPENSSL_COMPRESS),
link(fork)(OPTION_FORK),
link(bind)(OPTION_BIND),
link(range)(OPTION_RANGE),
@ -533,7 +554,7 @@ label(ADDRESS_OPENSSL_LISTEN)dit(bf(tt(OPENSSL-LISTEN:<port>)))
link(retry)(OPTION_RETRY)nl()
See also:
link(OPENSSL)(ADDRESS_OPENSSL_CONNECT),
link(TCP)(ADDRESS_TCP_CONNECT)
link(TCP-LISTEN)(ADDRESS_TCP_LISTEN)
label(ADDRESS_NAMED_PIPE)dit(bf(tt(PIPE:<filename>)))
If link(<filename>)(TYPE_FILENAME) already exists, it is opened.
If it does not exist, a named pipe is created and opened. Beginning with
@ -656,6 +677,7 @@ label(ADDRESS_SCTP_LISTEN)dit(bf(tt(SCTP-LISTEN:<port>)))
link(range)(OPTION_RANGE),
link(tcpwrap)(OPTION_TCPWRAPPERS),
link(pf)(OPTION_PROTOCOL_FAMILY),
link(max-children)(OPTION_MAX_CHILDREN),
link(backlog)(OPTION_BACKLOG),
link(sctp-maxseg)(OPTION_SCTP_MAXSEG),
link(sctp-nodelay)(OPTION_SCTP_NODELAY),
@ -928,6 +950,7 @@ label(ADDRESS_TCP_LISTEN)dit(bf(tt(TCP-LISTEN:<port>)))
link(range)(OPTION_RANGE),
link(tcpwrap)(OPTION_TCPWRAPPERS),
link(pf)(OPTION_PROTOCOL_FAMILY),
link(max-children)(OPTION_MAX_CHILDREN),
link(backlog)(OPTION_BACKLOG),
link(mss)(OPTION_MSS),
link(su)(OPTION_SUBSTUSER),
@ -952,12 +975,13 @@ label(ADDRESS_TCP6_LISTEN)dit(bf(tt(TCP6-LISTEN:<port>)))
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()
label(ADDRESS_TUN)dit(bf(tt(TUN[:<if-addr>/<bits>])))
Creates a Linux TUN/TAP device and optionally assignes it the address and
netmask given by the parameters. The resulting network interface is almost
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), as well as permission to set some tt(ioctl()s).
bf(Option iff-up is required to immediately activate the interface!)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),
@ -1573,7 +1597,7 @@ 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>)))
label(OPTION_O_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.
@ -1608,7 +1632,7 @@ 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)))
label(OPTION_O_TRUNC)dit(bf(tt(trunc)))
Truncates the file to size 0 during opening it.
enddit()
@ -1696,7 +1720,8 @@ 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)).
Short name for tt(substuser-delayed).
COMMENT(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
@ -2279,6 +2304,9 @@ 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.
label(OPTION_MAX_CHILDREN)dit(bf(tt(max-children=<count>)))
Limits the number of concurrent child processes [link(int)(TYPE_INT)].
Default is no limit.
enddit()
startdit()enddit()nl()
@ -2295,6 +2323,8 @@ label(OPTION_FORK)dit(bf(tt(fork)))
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()
On some operating systems (e.g. FreeBSD) this option does not work for
UDP-LISTEN addresses.nl()
enddit()
startdit()enddit()nl()
@ -2398,12 +2428,16 @@ 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)).
Enables or disables local 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)).
Sets raw mode, thus passing input and output almost unprocessed. This option is obsolete, use option link(rawer)(OPTION_TERMIOS_RAWER) or link(cfmakeraw)(OPTION_TERMIOS_CFMAKERAW) instead.
label(OPTION_TERMIOS_RAWER)dit(bf(tt(rawer)))
Makes terminal rawer than link(raw)(OPTION_RAW) option. This option implicitly turns off echo. (link(example)(EXAMPLE_OPTION_TERMIOS_RAWER)).
label(OPTION_TERMIOS_CFMAKERAW)dit(bf(tt(cfmakeraw)))
Sets raw mode by invoking tt(cfmakeraw()) or by simulating this call. This option implicitly turns off echo.
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>)))
@ -2607,11 +2641,14 @@ 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
dit(tt(SSL2)) Select SSL protocol version 2.
dit(tt(SSL3)) Select SSL protocol version 3.
dit(tt(SSL23)) Select the best available SSL or TLS protocol. This is the default when
this option is not provided.
dit(tt(TLSv1)) Select TLS protocol version 1.
dit(tt(TLS1)) Select TLS protocol version 1.
dit(tt(TLS1.1)) Select TLS protocol version 1.1.
dit(tt(TLS1.2)) Select TLS protocol version 1.2.
dit(tt(DTLS1)) Select DTLS 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
@ -2650,6 +2687,24 @@ label(OPTION_OPENSSL_PSEUDO)dit(bf(tt(pseudo)))
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_COMPRESS)dit(bf(tt(compress)))
Enable or disable the use of compression for a connection. Setting this to
"none" disables compression, setting it to "auto" lets OpenSSL choose the best
available algorithm supported by both parties. The default is to not touch any
compression-related settings.
NOTE: Requires OpenSSL 0.9.8 or higher and disabling compression with
OpenSSL 0.9.8 affects all new connections in the process.
label(OPTION_OPENSSL_COMMONNAME)dit(bf(tt(commonname=<string>)))
Specify the commonname that the peer certificate must match. With
link(OPENSSL-CONNECT)(ADDRESS_OPENSSL_CONNECT) address this overrides the
given hostname or IP target address; with
link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN) this turns on check of peer
certificates commonname. This option has only meaning when option
link(verify)(OPTION_OPENSSL_VERIFY) is not disabled and the choosen cipher
provides a peer certificate.
label(OPTION_OPENSSL_SNIHOST)dit(bf(tt(snihost=<string>)))
Specify the SNI hostname for the TLS request. The server can use this TLS
extension to choose which certificate to send.
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).
@ -2975,13 +3030,12 @@ at most 512 data bytes per packet (link(mss)(OPTION_MSS)).
label(EXAMPLE_ADDRESS_GOPEN)
label(EXAMPLE_OPTION_RAW)
label(EXAMPLE_OPTION_ECHO)
label(EXAMPLE_OPTION_TERMIOS_RAWER)
label(EXAMPLE_OPTION_ESCAPE)
dit(bf(tt(socat -,raw,echo=0,escape=0x0f /dev/ttyS0,raw,echo=0,crnl)))
dit(bf(tt(socat -,escape=0x0f /dev/ttyS0,rawer,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 the console's and
modem. link(rawer)(OPTION_TERMIOS_RAWER) sets the console's and
ttyS0's terminal parameters to practicable values, link(crnl)(OPTION_CRNL)
converts to correct newline characters. link(escape)(OPTION_ESCAPE) allows to
terminate the socat process with character control-O.
@ -3063,7 +3117,7 @@ htmlcommand(<dt><code><strong>socat -u TCP4-LISTEN:3334,reuseaddr,fork \</strong
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.
If the file does not exist, socat link(creat)(OPTION_O_CREAT)'s it.
Option link(reuseaddr)(OPTION_REUSEADDR) allows immediate restart of the server
process.
@ -3102,14 +3156,21 @@ label(EXAMPLE_ADDRESS_PTY)
label(EXAMPLE_OPTION_SYMBOLIC_LINK)
label(EXAMPLE_OPTION_WAIT_SLAVE)
label(EXAMPLE_OPTION_NONBLOCK)
(bf(tt(socat PTY,link=$HOME/dev/vmodem0,raw,echo=0,wait-slave EXEC:'"ssh modemserver.us.org socat - /dev/ttyS0,nonblock,raw,echo=0"')))
mancommand(\.LP)
mancommand(\.nf)
mancommand(\fBsocat PTY,link=$HOME/dev/vmodem0,rawer,wait-slave \\\bf)
mancommand(\fBEXEC:"ssh modemserver.us.org socat - /dev/ttyS0,nonblock,rawer"\fP)
mancommand(\.fi)
htmlcommand(<dt><code><strong>socat PTY,link=$HOME/dev/vmodem0,rawer,wait-slave \</strong><br>
<strong>EXEC:'"ssh modemserver.us.org socat - /dev/ttyS0,nonblock,rawer"'</strong></code><dd>)
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
to a modemserver via ssh where another socat instance links it to
file(/dev/ttyS0).
@ -3234,16 +3295,14 @@ 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)).
similar process might run, with UDP-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. Note that
streaming eg. via TCP or SSL does not guarantee to retain packet boundaries and
may thus cause packet loss.
label(EXAMPLE_INTERFACE)
dit(bf(tt(socat PTY,link=/var/run/ppp,raw,echo=0 INTERFACE:hdlc0)))
dit(bf(tt(socat PTY,link=/var/run/ppp,rawer INTERFACE:hdlc0)))
circumvents the problem that pppd requires a serial device and thus might not
be able to work on a synchronous line that is represented by a network device.
@ -3417,6 +3476,16 @@ dit(bf(SOCAT_IPV6_TCLASS) (output)) With all IPv6 based RECVFROM addresses
where address option link(ipv6-recvtclass)(OPTION_IPV6_RECVTCLASS) is applied,
socat sets this variable to the transfer class of the received packet.
dit(bf(SOCAT_OPENSSL_X509_ISSUER) (output)) Issuer field from peer certificate
dit(bf(SOCAT_OPENSSL_X509_SUBJECT) (output)) Subject field from peer certificate
dit(bf(SOCAT_OPENSSL_X509_COMMONNAME) (output)) commonName entries from peer certificates subject. Multiple values are separated by " // ".
dit(bf(SOCAT_OPENSSL_X509_*) (output)) all other entries from peer certificates subject
dit(bf(SOCAT_OPENSSL_X509V3_DNS) (output)) DNS entries from peer certificates extensions - subjectAltName field. Multiple values are separated by " // ".
dit(bf(HOSTNAME) (input)) Is used to determine the hostname for logging (see
link(-lh)(option_lh)).
@ -3466,7 +3535,7 @@ standard specifications available on the Internet for free.
label(VERSION)
manpagesection(VERSION)
This man page describes version 1.7.1 of socat().
This man page describes version 1.7.3 of socat().
label(BUGS)

View File

@ -1,5 +1,5 @@
# source: xio.help
# Copyright Gerhard Rieger 2001-2007
# Copyright Gerhard Rieger 2001-2010
Operating systems:
@ -4610,6 +4610,23 @@ FIPS enabled version of openssl. Setting or clearing this option on one
socat address affects all OpenSSL addresses of this process.
Option: openssl-compress
Aliases: compress
Type: STRING
Option group: OPENSSL
Phase: SPEC
Platforms: (depends on openssl installation)
Enable or disable the use of compression for a connection. Setting this to
"none" disables compression, setting it to "auto" lets OpenSSL choose the best
available algorithm supported by both parties. The default is to not touch any
compression-related settings.
NOTE: Requires OpenSSL 0.9.8 or higher.
NOTE: Disabling compression with OpenSSL 0.9.8 affects all new connections in
the same process.
===============================================================================
Application specific address options

294
error.c
View File

@ -1,30 +1,21 @@
/* source: error.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* the logging subsystem */
#include "config.h"
#include "sysincludes.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 "vsnprintf_r.h"
#include "snprinterr.h"
#include "error.h"
#include "sysincludes.h"
#include "sycls.h"
/* translate MSG level to SYSLOG level */
int syslevel[] = {
@ -49,11 +40,27 @@ struct diag_opts {
} ;
static void _diag_exit(int status);
struct diag_opts diagopts =
{ NULL, E_ERROR, E_ERROR, 0, NULL, LOG_DAEMON, false, 0 } ;
static void msg2(
#if HAVE_CLOCK_GETTIME
struct timespec *now,
#elif HAVE_GETTIMEOFDAY
struct timeval *now,
#else
time_t *now,
#endif
int level, int exitcode, int handler, const char *text);
static void _msg(int level, const char *buff, const char *syslp);
sig_atomic_t diag_in_handler; /* !=0 indicates to msg() that in signal handler */
sig_atomic_t diag_immediate_msg; /* !=0 prints messages even from within signal handler instead of deferring them */
sig_atomic_t diag_immediate_exit; /* !=0 calls exit() from diag_exit() even when in signal handler. For system() */
static struct wordent facilitynames[] = {
{"auth", (void *)LOG_AUTH},
#ifdef LOG_AUTHPRIV
@ -87,15 +94,38 @@ static struct wordent facilitynames[] = {
{"uucp", (void *)LOG_UUCP}
} ;
/* serialize message for sending from signal handlers */
struct sermsg {
int severity;
#if HAVE_CLOCK_GETTIME
struct timespec ts;
#else
struct timeval tv;
#endif
} ;
static int diaginitialized;
static int diag_sock_send = -1;
static int diag_sock_recv = -1;
static int diag_msg_avail = 0; /* !=0: messages from within signal handler may be waiting */
static int diag_init(void) {
int handlersocks[2];
if (diaginitialized) {
return 0;
}
diaginitialized = 1;
/* gcc with GNU libc refuses to set this in the initializer */
diagopts.logfile = stderr;
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, handlersocks) < 0) {
diag_sock_send = -1;
diag_sock_recv = -1;
return -1;
}
diag_sock_send = handlersocks[1];
diag_sock_recv = handlersocks[0];
return 0;
}
#define DIAG_INIT ((void)(diaginitialized || diag_init()))
@ -180,64 +210,108 @@ const char *diag_get_string(char what) {
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 */
struct diag_dgram diag_dgram;
va_list ap;
/* does not perform a system call if nothing todo, thanks diag_msg_avail */
diag_dgram._errno = errno; /* keep for passing from signal handler to sock.
reason is that strerror is definitely not
async-signal-safe */
DIAG_INIT;
/* in normal program flow (not in signal handler) */
/* first flush the queue of datagrams from the socket */
if (diag_msg_avail && !diag_in_handler) {
diag_msg_avail = 0; /* _before_ flush to prevent inconsistent state when signal occurs inbetween */
diag_flush();
}
if (level < diagopts.msglevel) { va_end(ap); return; }
va_start(ap, format);
/* we do only a minimum in the outer parts which may run in a signal handler
these are: get actual time, level, serialized message and write them to socket
*/
diag_dgram.op = DIAG_OP_MSG;
#if HAVE_CLOCK_GETTIME
clock_gettime(CLOCK_REALTIME, &diag_dgram.now);
#elif HAVE_GETTIMEOFDAY
gettimeofday(&diag_dgram.now, NULL);
#else
diag_dgram.now = time(NULL);
#endif
diag_dgram.level = level;
diag_dgram.exitcode = diagopts.exitstatus;
vsnprintf_r(diag_dgram.text, sizeof(diag_dgram.text), format, ap);
if (diag_in_handler && !diag_immediate_msg) {
send(diag_sock_send, &diag_dgram, sizeof(diag_dgram)-TEXTLEN + strlen(diag_dgram.text)+1, MSG_DONTWAIT
#ifdef MSG_NOSIGNAL
|MSG_NOSIGNAL
#endif
);
diag_msg_avail = 1;
va_end(ap);
return;
}
msg2(&diag_dgram.now, diag_dgram.level, diagopts.exitstatus, 0, diag_dgram.text);
va_end(ap); return;
}
void msg2(
#if HAVE_CLOCK_GETTIME
struct timespec *now,
#elif HAVE_GETTIMEOFDAY
struct timeval *now,
#else
time_t *now,
#endif
int level, /* E_INFO... */
int exitcode, /* on exit use this exit code */
int handler, /* message comes from signal handler */
const char *text) {
time_t epoch;
unsigned long micros;
#if HAVE_STRFTIME
struct tm struct_tm;
#endif
#define BUFLEN 512
char buff[BUFLEN], *bufp, *syslp;
size_t bytes;
va_list ap;
DIAG_INIT;
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));
}
#if HAVE_CLOCK_GETTIME
epoch = now->tv_sec;
#elif HAVE_GETTIMEOFDAY
epoch = now->tv_sec;
#else
strcpy(buff, ctime(&nowt));
bytes = strlen(buff);
epoch = *now;
#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));
bytes = strftime(buff, 20, "%Y/%m/%d %H:%M:%S", localtime_r(&epoch, &struct_tm));
buff[bytes] = '\0';
#else
strcpy(buff, ctime(&now));
bytes = strlen(buff);
bytes = snprintf(buff, 11, F_time, epoch);
#endif
if (diagopts.micros) {
#if HAVE_CLOCK_GETTIME
micros = now->tv_nsec/1000;
#elif HAVE_GETTIMEOFDAY
micros = now->tv_usec;
#else
micros = 0;
#endif
bytes += sprintf(buff+19, ".%06lu ", micros);
} else {
buff[19] = ' '; buff[20] = '\0';
}
#endif /* !HAVE_GETTIMEOFDAY */
bytes = strlen(buff);
bufp = buff + bytes;
if (diagopts.withhostname) {
bytes = sprintf(bufp, "%s ", diagopts.hostname), bufp+=bytes;
@ -246,19 +320,20 @@ void msg(int level, const char *format, ...) {
bufp += bytes;
syslp = bufp;
*bufp++ = "DINWEF"[level];
#if 0 /* only for debugging socat */
if (handler) bufp[-1] = tolower(bufp[-1]); /* for debugging, low chars indicate messages from signal handlers */
#endif
*bufp++ = ' ';
vsnprintf(bufp, BUFLEN-(bufp-buff)-1, format, ap);
strncpy(bufp, text, BUFLEN-(bufp-buff)-1);
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");
snprintf_r(syslp, 16, "N exit(%d)\n", exitcode?exitcode:(diagopts.exitstatus?diagopts.exitstatus:1));
_msg(E_NOTICE, buff, syslp);
}
exit(diagopts.exitstatus ? diagopts.exitstatus : 1);
exit(exitcode?exitcode:(diagopts.exitstatus?diagopts.exitstatus:1));
}
va_end(ap);
}
@ -273,6 +348,44 @@ static void _msg(int level, const char *buff, const char *syslp) {
}
/* handle the messages in the queue */
void diag_flush(void) {
struct diag_dgram recv_dgram;
char exitmsg[20];
while (recv(diag_sock_recv, &recv_dgram, sizeof(recv_dgram)-1, MSG_DONTWAIT) > 0) {
recv_dgram.text[TEXTLEN-1] = '\0';
switch (recv_dgram.op) {
case DIAG_OP_EXIT:
/* we want the actual time, not when this dgram was sent */
#if HAVE_CLOCK_GETTIME
clock_gettime(CLOCK_REALTIME, &recv_dgram.now);
#elif HAVE_GETTIMEOFDAY
gettimeofday(&recv_dgram.now, NULL);
#else
recv_dgram.now = time(NULL);
#endif
if (E_NOTICE >= diagopts.msglevel) {
snprintf_r(exitmsg, sizeof(exitmsg), "exit(%d)", recv_dgram.exitcode?recv_dgram.exitcode:1);
msg2(&recv_dgram.now, E_NOTICE, recv_dgram.exitcode?recv_dgram.exitcode:1, 1, exitmsg);
}
exit(recv_dgram.exitcode?recv_dgram.exitcode:1);
case DIAG_OP_MSG:
if (recv_dgram._errno) {
/* there might be a %m control in the string (glibc compatible,
replace with strerror(...errno) ) */
char text[TEXTLEN];
errno = recv_dgram._errno;
snprinterr(text, TEXTLEN, recv_dgram.text);
msg2(&recv_dgram.now, recv_dgram.level, recv_dgram.exitcode, 1, text);
} else {
msg2(&recv_dgram.now, recv_dgram.level, recv_dgram.exitcode, 1, recv_dgram.text);
}
break;
}
}
}
/* use a new log output file descriptor that is dup'ed from the current one.
this is useful when socat logs to stderr but fd 2 should be redirected to
serve other purposes */
@ -292,3 +405,56 @@ int diag_dup(void) {
}
return newfd;
}
/* this function is kind of async-signal-safe exit(). When invoked from signal
handler it defers exit. */
void diag_exit(int status) {
struct diag_dgram diag_dgram;
if (diag_in_handler && !diag_immediate_exit) {
diag_dgram.op = DIAG_OP_EXIT;
diag_dgram.exitcode = status;
send(diag_sock_send, &diag_dgram, sizeof(diag_dgram)-TEXTLEN, MSG_DONTWAIT
#ifdef MSG_NOSIGNAL
|MSG_NOSIGNAL
#endif
);
return;
}
_diag_exit(status);
}
static void _diag_exit(int status) {
Exit(status);
}
/* a function that appears to the application like select() but that also
monitors the diag socket diag_sock_recv and processes its messages.
Do not call from within a signal handler. */
int diag_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout) {
int result;
fd_set save_readfds, save_writefds, save_exceptfds;
if (readfds) { memcpy(&save_readfds, readfds, sizeof(*readfds)); }
if (writefds) { memcpy(&save_writefds, writefds, sizeof(*writefds)); }
if (exceptfds) { memcpy(&save_exceptfds, exceptfds, sizeof(*exceptfds)); }
while (1) {
FD_SET(diag_sock_recv, readfds);
result = Select(nfds, readfds, writefds,
exceptfds, timeout);
if (!FD_ISSET(diag_sock_recv, readfds)) {
/* select terminated not due to diag_sock_recv, normalt continuation */
break;
}
diag_flush();
if (readfds) { memcpy(readfds, &save_readfds, sizeof(*readfds)); }
if (writefds) { memcpy(writefds, &save_writefds, sizeof(*writefds)); }
if (exceptfds) { memcpy(exceptfds, &save_exceptfds, sizeof(*exceptfds)); }
}
return result;
}

34
error.h
View File

@ -1,5 +1,5 @@
/* source: error.h */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __error_h_included
@ -13,6 +13,7 @@
#define E_ERROR 4 /* errors */
#define E_FATAL 5 /* emergency abort */
#define F_strerror "%m" /* a pseudo format, replaced by strerror(errno) */
/* here are the macros for diag invocation; use WITH_MSGLEVEL to specify the
lowest priority that is compiled into your program */
@ -204,6 +205,33 @@
#endif /* !(WITH_MSGLEVEL <= E_FATAL) */
enum diag_op {
DIAG_OP_MSG, /* a diagnostic message */
DIAG_OP_EXIT, /* exit the program */
} ;
/* datagram for communication between outer msg() call from signal handler to
inner msg() call in normal flow */
# define TEXTLEN 480
struct diag_dgram {
enum diag_op op;
#if HAVE_CLOCK_GETTIME
struct timespec now;
#elif HAVE_GETTIMEOFDAY
struct timeval now;
#else
time_t now;
#endif
int level; /* E_FATAL, ... E_DEBUG */
int _errno; /* for glibc %m format */
int exitcode; /* if exiting take this num */
char text[TEXTLEN];
} ;
extern sig_atomic_t diag_in_handler;
extern int diag_immediate_msg;
extern int diag_immediate_exit;
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);
@ -211,5 +239,9 @@ extern const char *diag_get_string(char what);
extern int diag_dup(void);
extern int diag_dup2(int newfd);
extern void msg(int level, const char *format, ...);
extern void diag_flush(void);
extern void diag_exit(int status);
extern int diag_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
#endif /* !defined(__error_h_included) */

View File

@ -1,5 +1,5 @@
/* source: fdname.c */
/* Copyright Gerhard Rieger 2003-2008 */
/* Copyright Gerhard Rieger 2003-2011 */
/* 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
@ -103,7 +103,6 @@ static int procgetfdname(int fd, char *filepath, size_t pathsize) {
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
@ -144,7 +143,7 @@ int statname(const char *file, int fd, int filetype, FILE *outfile) {
case (S_IFSOCK>>12): /* 12, socket */
#if _WITH_SOCKET
if (fd >= 0) {
result = sockname(fd, outfile);
sockname(fd, outfile);
} else if (file) {
fprintf(outfile, "socket %s", file);
} else {

60
filan.c
View File

@ -1,5 +1,5 @@
/* source: filan.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* the subroutine filan makes a "FILe descriptor ANalysis". It checks the
@ -215,7 +215,6 @@ int filan_stat(
#endif /* !HAVE_STAT64 */
, int statfd, int dynfd, FILE *outfile) {
char stdevstr[8];
int result;
/* print header */
if (!headprinted) {
@ -263,9 +262,9 @@ int filan_stat(
headprinted = 1;
}
if (filan_rawoutput) {
snprintf(stdevstr, 8, F_st_dev, buf->st_dev);
snprintf(stdevstr, 8, F_dev, buf->st_dev);
} else {
snprintf(stdevstr, 8, "%hu,%hu", (unsigned short)buf->st_dev>>8, (unsigned short)buf->st_dev&0xff);
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
@ -300,7 +299,7 @@ int filan_stat(
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,
(unsigned short)(buf->st_rdev>>8), (unsigned short)(buf->st_rdev&0xff),
#endif
buf->st_size
#if HAVE_ST_BLKSIZE
@ -374,7 +373,7 @@ int filan_stat(
case (S_IFIFO): /* 1, FIFO */
break;
case (S_IFCHR): /* 2, character device */
result = cdevan(statfd, outfile);
cdevan(statfd, outfile);
break;
case (S_IFDIR): /* 4, directory */
break;
@ -387,7 +386,7 @@ int filan_stat(
#ifdef S_IFSOCK
case (S_IFSOCK): /* 12, socket */
#if _WITH_SOCKET
result = sockan(statfd, outfile);
sockan(statfd, outfile);
#else
Warn("SOCKET support not compiled in");
return -1;
@ -490,7 +489,10 @@ int cdevan(int fd, FILE *outfile) {
return -1;
}
fprintf(outfile, " \tIFLAGS=%08x OFLAGS=%08x CFLAGS=%08x LFLAGS=%08x",
termarg.c_iflag, termarg.c_oflag, termarg.c_cflag, termarg.c_lflag);
(unsigned int)termarg.c_iflag,
(unsigned int)termarg.c_oflag,
(unsigned int)termarg.c_cflag,
(unsigned int)termarg.c_lflag);
/* and the control characters */
if (filan_rawoutput) {
@ -597,7 +599,10 @@ int sockan(int fd, FILE *outfile) {
{SO_DETACH_FILTER, "DETACH_FILTER"},
#endif
{0, NULL} } ;
char optval[FILAN_OPTLEN];
union {
char c[FILAN_OPTLEN];
int i[FILAN_OPTLEN/sizeof(int)];
} optval;
const struct sockopt *optname;
union sockaddr_union sockname, peername; /* the longest I know of */
socklen_t namelen;
@ -607,33 +612,33 @@ int sockan(int fd, FILE *outfile) {
#endif
optlen = FILAN_OPTLEN;
result = Getsockopt(fd, SOL_SOCKET, SO_TYPE, optval, &optlen);
result = Getsockopt(fd, SOL_SOCKET, SO_TYPE, optval.c, &optlen);
if (result < 0) {
Debug4("getsockopt(%d, SOL_SOCKET, SO_TYPE, %p, {"F_socklen"}): %s",
fd, optval, optlen, strerror(errno));
fd, optval.c, optlen, strerror(errno));
} else {
Debug3("fd %d: socket of type %d (\"%s\")", fd, *(int *)optval,
socktypes[*(int *)optval]);
Debug3("fd %d: socket of type %d (\"%s\")", fd, *optval.i,
socktypes[*optval.i]);
}
optname = sockopts; while (optname->so) {
optlen = FILAN_OPTLEN;
result =
Getsockopt(fd, SOL_SOCKET, optname->so, (void *)optval, &optlen);
Getsockopt(fd, SOL_SOCKET, optname->so, (void *)optval.c, &optlen);
if (result < 0) {
Debug5("getsockopt(%d, SOL_SOCKET, %d, %p, {"F_socklen"}): %s",
fd, optname->so, optval, optlen, strerror(errno));
fd, optname->so, optval.c, 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);
*optval.i, optlen);
/*Info2("%s: %d", optname->name, optval.i);*/
fprintf(outfile, "%s=%d\t", optname->name, *optval.i);
} else {
Debug3("getsockopt(,,, {%d,%d}, %d)",
((int *)optval)[0], ((int *)optval)[1], optlen);
optval.i[0], optval.i[1], optlen);
fprintf(outfile, "%s={%d,%d}\t", optname->name,
((int *)optval)[0], ((int *)optval)[1]);
optval.i[0], optval.i[1]);
}
++optname;
}
@ -888,16 +893,19 @@ int tcpan(int fd, FILE *outfile) {
#if _WITH_SOCKET
int sockoptan(int fd, const struct sockopt *optname, int socklay, FILE *outfile) {
#define FILAN_OPTLEN 256
char optval[FILAN_OPTLEN];
union {
char c[FILAN_OPTLEN];
int i[FILAN_OPTLEN/sizeof(int)];
} optval;
socklen_t optlen;
int result;
optlen = FILAN_OPTLEN;
result =
Getsockopt(fd, socklay, optname->so, (void *)optval, &optlen);
Getsockopt(fd, socklay, optname->so, (void *)optval.c, &optlen);
if (result < 0) {
Debug6("getsockopt(%d, %d, %d, %p, {"F_socklen"}): %s",
fd, socklay, optname->so, optval, optlen, strerror(errno));
fd, socklay, optname->so, optval.c, optlen, strerror(errno));
fputc('\t', outfile);
return -1;
} else if (optlen == 0) {
@ -905,13 +913,13 @@ int sockoptan(int fd, const struct sockopt *optname, int socklay, FILE *outfile)
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);
*optval.i, optlen);
fprintf(outfile, "%s=%d\t", optname->name, *optval.i);
} 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 += sprintf(cp, "%08x ", (unsigned int)optval.i[i]);
}
*--cp = '\0'; /* delete trailing space */
Debug2("getsockopt(,,, {%s}, %d)", outbuf, optlen);

View File

@ -1,5 +1,5 @@
/* source: filan_main.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* 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/";
@ -239,7 +239,7 @@ static void filan_usage(FILE *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(" -L follow symbolic links instead of showing their properties\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);

View File

@ -1,5 +1,5 @@
/* source: hostan.c */
/* Copyright Gerhard Rieger 2006-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* the subroutine hostan makes a "HOST ANalysis". It gathers information
@ -17,17 +17,35 @@
#include "hostan.h"
#include "error.h"
static int iffan(FILE *outfile);
int hostan(FILE *outfile) {
#if _WITH_SOCKET
fprintf(outfile, "\nC TYPE SIZES\n");
fprintf(outfile, "sizeof(char) = %u\n", (unsigned int)sizeof(char));
fprintf(outfile, "sizeof(short) = %u\n", (unsigned int)sizeof(short));
fprintf(outfile, "sizeof(int) = %u\n", (unsigned int)sizeof(int));
fprintf(outfile, "sizeof(long) = %u\n", (unsigned int)sizeof(long));
#if HAVE_TYPE_LONGLONG
fprintf(outfile, "sizeof(long long) = %u\n", (unsigned int)sizeof(long long));
#endif
fprintf(outfile, "sizeof(size_t) = %u\n", (unsigned int)sizeof(size_t));
#include <sys/time.h> /* select(); OpenBSD: struct timespec */
fprintf(outfile, "sizeof(struct timespec) = %u\n", (unsigned int)sizeof(struct timespec));
fprintf(outfile, "sizeof(struct diag_dgram) = %u\n", (unsigned int)sizeof(struct diag_dgram));
fprintf(outfile, "((struct diag_dgram *)0)->op-((struct diag_dgram *)0) = %u\n", (unsigned int)((char *)(&((struct diag_dgram *)0)->op)-(char *)((struct diag_dgram *)0)));
fprintf(outfile, "((struct diag_dgram *)0)->now-((struct diag_dgram *)0) = %u\n", (unsigned int)((char *)(&((struct diag_dgram *)0)->now)-(char *)((struct diag_dgram *)0)));
fprintf(outfile, "((struct diag_dgram *)0)->exitcode-((struct diag_dgram *)0) = %u\n", (unsigned int)((char *)(&((struct diag_dgram *)0)->exitcode)-(char *)((struct diag_dgram *)0)));
fprintf(outfile, "((struct diag_dgram *)0)->text-((struct diag_dgram *)0) = %u\n", (unsigned int)((((struct diag_dgram *)0)->text)-(char *)((struct diag_dgram *)0)));
#if _WITH_SOCKET && (_WITH_IP4 || _WITH_IP6)
fprintf(outfile, "\nIP INTERFACES\n");
iffan(outfile);
#endif
return 0;
}
#if _WITH_SOCKET
#if _WITH_SOCKET && (_WITH_IP4 || _WITH_IP6)
static int iffan(FILE *outfile) {
/* Linux: man 7 netdevice */
/* FreeBSD, NetBSD: man 4 networking */
@ -59,13 +77,15 @@ static int iffan(FILE *outfile) {
for (i = 0; i < ic.ifc_len; i += sizeof(struct ifreq)) {
struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i);
#if 0 || defined(SIOCGIFINDEX) /* not NetBSD, OpenBSD */
struct ifreq ifr;
#endif
#if 0 || defined(SIOCGIFINDEX) /* not NetBSD, OpenBSD */
strcpy(ifr.ifr_name, ifp->ifr_name);
if (Ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
Error3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}): %s",
s, &ifr.ifr_name, strerror(errno));
s, ifr.ifr_name, strerror(errno));
return 1;
}
#if HAVE_STRUCT_IFREQ_IFR_INDEX
@ -74,7 +94,7 @@ static int iffan(FILE *outfile) {
fprintf(outfile, "%2d: %s\n", ifr.ifr_ifindex, ifp->ifr_name);
#endif /* HAVE_STRUCT_IFREQ_IFR_INDEX */
#else /* !defined(SIOCGIFINDEX) */
fprintf(outfile, "%2d: %s\n", i/sizeof(struct ifreq), ifp->ifr_name);
fprintf(outfile, "%2d: %s\n", i/(int)sizeof(struct ifreq), ifp->ifr_name);
#endif /* defined(SIOCGIFINDEX) */
}
Close(s);

View File

@ -1,5 +1,5 @@
/* source: mytypes.h */
/* Copyright Gerhard Rieger 2001-2006 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __mytypes_h_included
@ -7,10 +7,18 @@
/* some types and macros I miss in C89 */
#ifndef HAVE_TYPE_BOOL
# undef bool
typedef enum { false, true } bool;
#endif
#ifndef Min
#define Min(x,y) ((x)<=(y)?(x):(y))
#endif
#ifndef Max
#define Max(x,y) ((x)>=(y)?(x):(y))
#endif
#define SOCKADDR_MAX UNIX_PATH_MAX

View File

@ -1,5 +1,5 @@
/* source: procan-cdefs.c */
/* Copyright Gerhard Rieger 2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* a function that prints compile time parameters */
@ -20,7 +20,7 @@ int procan_cdefs(FILE *outfile) {
fprintf(outfile, "#define FD_SETSIZE %u\n", FD_SETSIZE);
#endif
#ifdef NFDBITS
fprintf(outfile, "#define NFDBITS "F_Zu"\n", NFDBITS);
fprintf(outfile, "#define NFDBITS %d\n", (int)NFDBITS);
#endif
#ifdef O_RDONLY
fprintf(outfile, "#define O_RDONLY %u\n", O_RDONLY);

View File

@ -1,5 +1,5 @@
/* source: procan.c */
/* Copyright Gerhard Rieger 2001-2006 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* the subroutine procan makes a "PROCess ANalysis". It gathers information
@ -78,40 +78,40 @@ int procan(FILE *outfile) {
struct rlimit rlim;
fprintf(outfile, "\nRESOURCE LIMITS\n");
fprintf(outfile, "resource current maximum\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",
"cpu time (seconds) %24"F_rlim_max"%24"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",
"file size (blocks) %24"F_rlim_max"%24"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",
"data seg size (kbytes) %24"F_rlim_max"%24"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",
"stack size (blocks) %24"F_rlim_max"%24"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",
"core file size (blocks) %24"F_rlim_max"%24"F_rlim_max"\n",
rlim.rlim_cur, rlim.rlim_max);
}
#ifdef RLIMIT_RSS /* Linux, AIX; not Cygwin */
@ -119,7 +119,7 @@ int procan(FILE *outfile) {
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",
"max resident set size %24"F_rlim_max"%24"F_rlim_max"\n",
rlim.rlim_cur, rlim.rlim_max);
}
#endif
@ -128,7 +128,7 @@ int procan(FILE *outfile) {
Warn2("getrlimit(RLIMIT_NPROC, %p): %s", &rlim, strerror(errno));
} else {
fprintf(outfile,
"max user processes %16"F_rlim_max"%16"F_rlim_max"\n",
"max user processes %24"F_rlim_max"%24"F_rlim_max"\n",
rlim.rlim_cur, rlim.rlim_max);
}
#endif
@ -137,7 +137,7 @@ int procan(FILE *outfile) {
Warn2("getrlimit(RLIMIT_NOFILE, %p): %s", &rlim, strerror(errno));
} else {
fprintf(outfile,
"open files %16"F_rlim_max"%16"F_rlim_max"\n",
"open files %24"F_rlim_max"%24"F_rlim_max"\n",
rlim.rlim_cur, rlim.rlim_max);
}
#endif
@ -146,7 +146,7 @@ int procan(FILE *outfile) {
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",
"max locked-in-memory\n address space %24"F_rlim_max"%24"F_rlim_max"\n",
rlim.rlim_cur, rlim.rlim_max);
}
#endif
@ -155,7 +155,7 @@ int procan(FILE *outfile) {
Warn2("getrlimit(RLIMIT_AS, %p): %s", &rlim, strerror(errno));
} else {
fprintf(outfile,
"virtual memory (kbytes) %16"F_rlim_max"%16"F_rlim_max"\n",
"virtual memory (kbytes) %24"F_rlim_max"%24"F_rlim_max"\n",
rlim.rlim_cur, rlim.rlim_max);
}
#endif

View File

@ -1,12 +1,18 @@
/* source: procan_main.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* 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 <signal.h> /* sig_atomic_t for error.h */
#include <time.h> /* struct timespec for error.h */
#include <stdlib.h> /* strtoul() */
#include <string.h>
#include <stdio.h>
#include "config.h"
#if HAVE_SYS_SELECT_H
#include <sys/select.h> /* select(), fdset on FreeBSD */
#endif
#include "mytypes.h"
#include "error.h"
#include "procan.h"

85
snprinterr.c Normal file
View File

@ -0,0 +1,85 @@
/* snprinterr.c */
/* Copyright Gerhard Rieger */
/* a function similar to vsnprintf() but it just handles %m */
#include "config.h"
#include <stddef.h> /* ptrdiff_t */
#include <ctype.h> /* isdigit() */
#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 "snprinterr.h"
#define HAVE_STRERROR_R 0
/* replace %m in format with actual strerror() message, write result to *str.
keep other % formats unchanged!
writes at most size chars including the terminating \0 to *str
returns the number of bytes in the output without terminating \0
result is always \0 terminated except when size==0
*/
int snprinterr(char *str, size_t size, const char *format) {
char c;
int full = 0; /* 1 means: there is no space left in * str for more data or \0 */
int count = 0;
if (size == 0) return 0;
if (count >= size) full = 1;
while (c = *format++) {
if (c == '%') {
c = *format++;
switch (c) {
case '\0':
++count; if (!full) { (*str++ = '%'); if (count+1 >= size) full = 1; }
break;
default:
++count; if (!full) { (*str++ = '%'); if (count+1 >= size) full = 1; }
++count; if (!full) { (*str++ = c); if (count+1 >= size) full = 1; }
break;
case 'm':
{
#if HAVE_STRERROR_R
# define BUFLEN 64
char buf[BUFLEN] = "";
#endif /* HAVE_STRERROR_R */
char *bufp;
#if !HAVE_STRERROR_R
bufp = strerror(errno);
#else
/* there are two versions floating around... */
# if 1 /* GNU version */
bufp = strerror_r(errno, buf, BUFLEN);
# else /* standard version */
strerror_r(errno, buf, BUFLEN);
bufp = buf;
# endif
#endif /* HAVE_STRERROR_R */
while ((c = *bufp++) != '\0') {
++count; if (!full) { (*str++ = c); if (count+1 >= size) full = 1; }
}
}
c = ' '; /* not \0 ! */
break;
}
if (c == '\0') break;
} else {
++count; if (!full) { (*str++ = c); if (count+1 >= size) full = 1; }
}
}
*str++ = '\0'; /* always write terminating \0 */
return count;
#undef BUFLEN
}

10
snprinterr.h Normal file
View File

@ -0,0 +1,10 @@
/* source: snprinterr.h */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __snprinterr_h_included
#define __snprinterr_h_included 1
int snprinterr(char *str, size_t size, const char *format);
#endif /* !defined(__snprinterr_h_included) */

76
socat.c
View File

@ -1,5 +1,5 @@
/* source: socat.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this is the main source, including command line option parsing, general
@ -70,7 +70,7 @@ static int socat_newchild(void);
static const char socatversion[] =
#include "./VERSION"
;
static const char timestamp[] = __DATE__" "__TIME__;
static const char timestamp[] = BUILD_DATE;
const char copyright_socat[] = "socat by Gerhard Rieger - see www.dest-unreach.org";
#if WITH_OPENSSL
@ -274,7 +274,7 @@ int main(int argc, const char *argv[]) {
Info(copyright_ssleay);
#endif
Debug2("socat version %s on %s", socatversion, timestamp);
xiosetenv("VERSION", socatversion, 1); /* SOCAT_VERSION */
xiosetenv("VERSION", socatversion, 1, NULL); /* SOCAT_VERSION */
uname(&ubuf); /* ! here we circumvent internal tracing (Uname) */
Debug4("running on %s version %s, release %s, machine %s\n",
ubuf.sysname, ubuf.version, ubuf.release, ubuf.machine);
@ -285,18 +285,23 @@ int main(int argc, const char *argv[]) {
}
#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);
{
struct sigaction act;
sigfillset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = socat_signal;
/* not sure which signals should be cauhgt and print a message */
Sigaction(SIGHUP, &act, NULL);
Sigaction(SIGINT, &act, NULL);
Sigaction(SIGQUIT, &act, NULL);
Sigaction(SIGILL, &act, NULL);
Sigaction(SIGABRT, &act, NULL);
Sigaction(SIGBUS, &act, NULL);
Sigaction(SIGFPE, &act, NULL);
Sigaction(SIGSEGV, &act, NULL);
Sigaction(SIGTERM, &act, NULL);
}
Signal(SIGPIPE, SIG_IGN);
/* set xio hooks */
xiohook_newchild = &socat_newchild;
@ -546,12 +551,6 @@ int closing = 0; /* 0..no eof yet, 1..first eof just occurred,
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;
@ -680,7 +679,9 @@ int childleftdata(xiofile_t *xfd) {
in.revents = 0;
}
do {
int _errno;
retval = xiopoll(&in, 1, &timeout);
_errno = errno; diag_flush(); errno = _errno; /* just in case it's not debug level and Msg() not been called */
} while (retval < 0 && errno == EINTR);
if (retval < 0) {
@ -789,6 +790,7 @@ int _socat(void) {
if (total_timeout.tv_sec < 0 ||
total_timeout.tv_sec == 0 && total_timeout.tv_usec < 0) {
Notice("inactivity timeout triggered");
free(buff);
return 0;
}
}
@ -901,6 +903,7 @@ int _socat(void) {
fds[0].fd, fds[0].events, fds[1].fd, fds[1].events,
fds[2].fd, fds[2].events, fds[3].fd, fds[3].events,
timeout.tv_sec, timeout.tv_usec, strerror(errno));
free(buff);
return -1;
} else if (retval == 0) {
Info2("poll timed out (no data within %ld.%06ld seconds)",
@ -912,6 +915,9 @@ int _socat(void) {
if (XIO_RDSTREAM(sock1)->ignoreeof) {
mayrd1 = 0;
}
if (XIO_RDSTREAM(sock2)->ignoreeof) {
mayrd2 = 0;
}
} else if (polling && wasaction) {
wasaction = 0;
@ -919,6 +925,7 @@ int _socat(void) {
socat_opts.total_timeout.tv_usec != 0) {
/* there was a total inactivity timeout */
Notice("inactivity timeout triggered");
free(buff);
return 0;
}
@ -937,6 +944,7 @@ int _socat(void) {
named pipe. a read() might imm. return with 0 bytes, resulting
in a loop? */
Error1("poll(...[%d]: invalid request", fd1in->fd);
free(buff);
return -1;
}
mayrd1 = true;
@ -945,6 +953,7 @@ int _socat(void) {
(fd2in->revents)) {
if (fd2in->revents & POLLNVAL) {
Error1("poll(...[%d]: invalid request", fd2in->fd);
free(buff);
return -1;
}
mayrd2 = true;
@ -952,6 +961,7 @@ int _socat(void) {
if (XIO_GETWRFD(sock1) >= 0 && fd1out->fd >= 0 && fd1out->revents) {
if (fd1out->revents & POLLNVAL) {
Error1("poll(...[%d]: invalid request", fd1out->fd);
free(buff);
return -1;
}
maywr1 = true;
@ -959,6 +969,7 @@ int _socat(void) {
if (XIO_GETWRFD(sock2) >= 0 && fd2out->fd >= 0 && fd2out->revents) {
if (fd2out->revents & POLLNVAL) {
Error1("poll(...[%d]: invalid request", fd2out->fd);
free(buff);
return -1;
}
maywr2 = true;
@ -1084,6 +1095,7 @@ int _socat(void) {
xioclose(sock1);
xioclose(sock2);
free(buff);
return 0;
}
@ -1297,7 +1309,8 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
}
} else if (socat_opts.verbhex) {
int i;
/*! prefix? */
/* print prefix */
xioprintblockheader(stderr, bytes, righttoleft);
for (i = 0; i < bytes; ++i) {
fprintf(stderr, " %02x", (*buff)[i]);
}
@ -1404,6 +1417,10 @@ int cv_newline(unsigned char **buff, ssize_t *bufsiz,
}
void socat_signal(int signum) {
int _errno;
_errno = errno;
diag_in_handler = 1;
Notice1("socat_signal(): handling signal %d", signum);
switch (signum) {
case SIGQUIT:
case SIGILL:
@ -1422,7 +1439,11 @@ void socat_signal(int signum) {
case SIGINT:
Notice1("exiting on signal %d", signum); break;
}
Exit(128+signum);
//Exit(128+signum);
Notice1("socat_signal(): finishing signal %d", signum);
diag_exit(128+signum); /*!!! internal cleanup + _exit() */
diag_in_handler = 0;
errno = _errno;
}
/* this is the callback when the child of an address died */
@ -1477,8 +1498,13 @@ 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));
if (!diag_in_handler) {
Warn2("unlink(\"%s\"): %s",
socat_opts.lock.lockfile, strerror(errno));
} else {
Warn1("unlink(\"%s\"): "F_strerror,
socat_opts.lock.lockfile);
}
} else {
Info1("released lock \"%s\"", socat_opts.lock.lockfile);
}

View File

@ -1,14 +1,14 @@
%define majorver 1.7
%define minorver 1.2
%define minorver 3.0
Summary: socat - multipurpose relay
Name: socat
Version: %{majorver}.%{minorver}
Release: 1
Copyright: GPL
License: GPL
Group: Applications/Communications
Source0: http://www.dest-unreach.org/socat/download/socat-%{version}.tar.gz
Source0: http://www.dest-unreach.org/socat/download/socat-%{version}.tar.bz2
Requires: readline
Requires: openssl
BuildRoot: /var/tmp/%{name}-buildroot
@ -20,7 +20,7 @@ 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}
%setup -n %{name}-%{version}
%build
# the CPPFLAGS setting is required for RedHat Linux
@ -44,7 +44,7 @@ rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%doc README CHANGES EXAMPLES SECURITY xio.help socat.html FAQ BUGREPORTS
%doc README CHANGES EXAMPLES SECURITY doc/xio.help doc/socat.html FAQ BUGREPORTS
%doc COPYING COPYING.OpenSSL FILES PORTING DEVELOPMENT
%{_bindir}/socat
%{_bindir}/procan

137
socat_buildscript_for_android.sh Executable file
View File

@ -0,0 +1,137 @@
#!/bin/sh
# Customize these parameters according to your environment
ANDROID_NDK="${HOME}/bin/android-ndk-r6b"
# Check for parameters
if [ ! -d "${ANDROID_NDK}" ]; then
echo "Android NDK not found in ${ANDROID_NDK}, please edit $0 to fix it."
exit 1
fi
if [ ! -e "${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh" ]; then
echo "Your Android NDK is not compatible (make-standalone-toolchain.sh not found)."
echo "Android NDK r6b is known to work."
exit 1
fi
# Extract the Android toolchain from NDK
ANDROID_PLATFORM="android-3"
ROOT="`pwd`"
OUT="${ROOT}/out"
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
--ndk-dir="${ANDROID_NDK}" \
--platform="${ANDROID_PLATFORM}" \
--install-dir="${OUT}/toolchain" \
|| exit 1
# Remove resolv.h because it is quite unusable as is
rm ${OUT}/toolchain/sysroot/usr/include/resolv.h
# Create configure script
cd ${ROOT}
autoconf || exit 1
# Create config.h and Makefile
cd ${OUT}
${ROOT}/configure \
--host \
--disable-openssl \
--disable-unix \
CC="${OUT}/toolchain/bin/arm-linux-androideabi-gcc" \
|| exit 1
# Replace misconfigured values in config.h and enable PTY functions
mv config.h config.old
cat config.old \
| sed 's/CRDLY_SHIFT.*/CRDLY_SHIFT 9/' \
| sed 's/TABDLY_SHIFT.*/TABDLY_SHIFT 11/' \
| sed 's/CSIZE_SHIFT.*/CSIZE_SHIFT 4/' \
| sed 's/\/\* #undef HAVE_OPENPTY \*\//#define HAVE_OPENPTY 1/' \
| sed 's/\/\* #undef HAVE_GRANTPT \*\//#define HAVE_GRANTPT 1/' \
> config.h
# Enable openpty() in Makefile
mv Makefile Makefile.old
cat Makefile.old | sed 's/error.c/error.c openpty.c/' > Makefile
# Provide openpty.c
cat >openpty.c <<EOF
/* Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#define _PATH_DEVPTMX "/dev/ptmx"
int openpty (int *amaster, int *aslave, char *name, struct termios *termp,
struct winsize *winp)
{
char buf[PATH_MAX];
int master, slave;
master = open(_PATH_DEVPTMX, O_RDWR);
if (master == -1)
return -1;
if (grantpt(master))
goto fail;
if (unlockpt(master))
goto fail;
if (ptsname_r(master, buf, sizeof buf))
goto fail;
slave = open(buf, O_RDWR | O_NOCTTY);
if (slave == -1)
goto fail;
/* XXX Should we ignore errors here? */
if (termp)
tcsetattr(slave, TCSAFLUSH, termp);
if (winp)
ioctl(slave, TIOCSWINSZ, winp);
*amaster = master;
*aslave = slave;
if (name != NULL)
strcpy(name, buf);
return 0;
fail:
close(master);
return -1;
}
EOF
# Compile
make socat || exit 1
# Done
echo "Build finished, socat has been generated successfuly in out/socat"

138
sslcls.c
View File

@ -1,5 +1,5 @@
/* source: sslcls.c */
/* Copyright Gerhard Rieger 2001-2007 */
/* Copyright Gerhard Rieger */
/* 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
@ -35,71 +35,131 @@ int sycSSL_library_init(void) {
return result;
}
SSL_METHOD *sycSSLv2_client_method(void) {
SSL_METHOD *result;
#if HAVE_SSLv2_client_method
const SSL_METHOD *sycSSLv2_client_method(void) {
const SSL_METHOD *result;
Debug("SSLv2_client_method()");
result = SSLv2_client_method();
Debug1("SSLv2_client_method() -> %p", result);
return result;
}
#endif
SSL_METHOD *sycSSLv2_server_method(void) {
SSL_METHOD *result;
#if HAVE_SSLv2_server_method
const SSL_METHOD *sycSSLv2_server_method(void) {
const SSL_METHOD *result;
Debug("SSLv2_server_method()");
result = SSLv2_server_method();
Debug1("SSLv2_server_method() -> %p", result);
return result;
}
#endif
SSL_METHOD *sycSSLv3_client_method(void) {
SSL_METHOD *result;
const SSL_METHOD *sycSSLv3_client_method(void) {
const 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;
const SSL_METHOD *sycSSLv3_server_method(void) {
const 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;
const SSL_METHOD *sycSSLv23_client_method(void) {
const 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;
const SSL_METHOD *sycSSLv23_server_method(void) {
const 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;
const SSL_METHOD *sycTLSv1_client_method(void) {
const 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;
const SSL_METHOD *sycTLSv1_server_method(void) {
const 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) {
#if HAVE_TLSv1_1_client_method
const SSL_METHOD *sycTLSv1_1_client_method(void) {
const SSL_METHOD *result;
Debug("TLSv1_1_client_method()");
result = TLSv1_1_client_method();
Debug1("TLSv1_1_client_method() -> %p", result);
return result;
}
#endif
#if HAVE_TLSv1_1_server_method
const SSL_METHOD *sycTLSv1_1_server_method(void) {
const SSL_METHOD *result;
Debug("TLSv1_1_server_method()");
result = TLSv1_1_server_method();
Debug1("TLSv1_1_server_method() -> %p", result);
return result;
}
#endif
#if HAVE_TLSv1_2_client_method
const SSL_METHOD *sycTLSv1_2_client_method(void) {
const SSL_METHOD *result;
Debug("TLSv1_2_client_method()");
result = TLSv1_2_client_method();
Debug1("TLSv1_2_client_method() -> %p", result);
return result;
}
#endif
#if HAVE_TLSv1_2_server_method
const SSL_METHOD *sycTLSv1_2_server_method(void) {
const SSL_METHOD *result;
Debug("TLSv1_2_server_method()");
result = TLSv1_2_server_method();
Debug1("TLSv1_2_server_method() -> %p", result);
return result;
}
#endif
const SSL_METHOD *sycDTLSv1_client_method(void) {
const SSL_METHOD *result;
Debug("DTLSv1_client_method()");
result = DTLSv1_client_method();
Debug1("DTLSv1_client_method() -> %p", result);
return result;
}
const SSL_METHOD *sycDTLSv1_server_method(void) {
const SSL_METHOD *result;
Debug("DTLSv1_server_method()");
result = DTLSv1_server_method();
Debug1("DTLSv1_server_method() -> %p", result);
return result;
}
SSL_CTX *sycSSL_CTX_new(const SSL_METHOD *method) {
SSL_CTX *result;
Debug1("SSL_CTX_new(%p)", method);
result = SSL_CTX_new(method);
@ -119,8 +179,8 @@ 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?"\"":"");
CAfile?"\"":"", CAfile?CAfile:"", CAfile?"\"":"",
CApath?"\"":"", CApath?CApath:"", CApath?"\"":"");
result = SSL_CTX_load_verify_locations(ctx, CAfile, CApath);
Debug1("SSL_CTX_load_verify_locations() -> %d", result);
return result;
@ -315,4 +375,42 @@ int sycFIPS_mode_set(int onoff) {
}
#endif /* WITH_FIPS */
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
const COMP_METHOD *sycSSL_get_current_compression(SSL *ssl) {
const COMP_METHOD *result;
Debug1("SSL_get_current_compression(%p)", ssl);
result = SSL_get_current_compression(ssl);
if (result) {
Debug1("SSL_get_current_compression() -> %p", result);
} else {
Debug("SSL_get_current_compression() -> NULL");
}
return result;
}
const COMP_METHOD *sycSSL_get_current_expansion(SSL *ssl) {
const COMP_METHOD *result;
Debug1("SSL_get_current_expansion(%p)", ssl);
result = SSL_get_current_expansion(ssl);
if (result) {
Debug1("SSL_get_current_expansion() -> %p", result);
} else {
Debug("SSL_get_current_expansion() -> NULL");
}
return result;
}
const char *sycSSL_COMP_get_name(const COMP_METHOD *comp) {
const char *result;
Debug1("SSL_COMP_get_name(%p)", comp);
result = SSL_COMP_get_name(comp);
if (result) {
Debug1("SSL_COMP_get_name() -> \"%s\"", result);
} else {
Debug("SSL_COMP_get_name() -> NULL");
}
return result;
}
#endif
#endif /* WITH_SYCLS && WITH_OPENSSL */

View File

@ -1,5 +1,5 @@
/* source: sslcls.h */
/* Copyright Gerhard Rieger 2001-2007 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __sslcls_h_included
@ -10,15 +10,21 @@
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);
const SSL_METHOD *sycSSLv2_client_method(void);
const SSL_METHOD *sycSSLv2_server_method(void);
const SSL_METHOD *sycSSLv3_client_method(void);
const SSL_METHOD *sycSSLv3_server_method(void);
const SSL_METHOD *sycSSLv23_client_method(void);
const SSL_METHOD *sycSSLv23_server_method(void);
const SSL_METHOD *sycTLSv1_client_method(void);
const SSL_METHOD *sycTLSv1_server_method(void);
const SSL_METHOD *sycTLSv1_1_client_method(void);
const SSL_METHOD *sycTLSv1_1_server_method(void);
const SSL_METHOD *sycTLSv1_2_client_method(void);
const SSL_METHOD *sycTLSv1_2_server_method(void);
const SSL_METHOD *sycDTLSv1_client_method(void);
const SSL_METHOD *sycDTLSv1_server_method(void);
SSL_CTX *sycSSL_CTX_new(const SSL_METHOD *method);
SSL *sycSSL_new(SSL_CTX *ctx);
int sycSSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
const char *CApath);
@ -49,6 +55,12 @@ BIO *sycBIO_new_file(const char *filename, const char *mode);
int sycFIPS_mode_set(int onoff);
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
const COMP_METHOD *sycSSL_get_current_compression(SSL *ssl);
const COMP_METHOD *sycSSL_get_current_expansion(SSL *ssl);
const char *sycSSL_COMP_get_name(const COMP_METHOD *comp);
#endif
#endif /* WITH_OPENSSL */
#else /* !WITH_SYCLS */
@ -92,6 +104,10 @@ int sycFIPS_mode_set(int onoff);
#define sycBIO_new_file(f,m) BIO_new_file(f,m)
#define sycSSL_get_current_compression(s) SSL_get_current_compression(s)
#define sycSSL_get_current_expansion(s) SSL_get_current_expansion(s)
#define sycSSL_COMP_get_name(c) SSL_COMP_get_name(c)
#endif /* WITH_OPENSSL */
#define sycFIPS_mode_set(o) FIPS_mode_set(o)

131
sycls.c
View File

@ -1,5 +1,5 @@
/* source: sycls.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* 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
@ -36,9 +36,11 @@ mode_t Umask(mode_t mask) {
int Open(const char *pathname, int flags, mode_t mode) {
int result, _errno;
if (!diag_in_handler) diag_flush();
Debug3("open(\"%s\", 0%o, 0%03o)", pathname, flags, mode);
result = open(pathname, flags, mode);
_errno = errno;
if (!diag_in_handler) diag_flush();
Info4("open(\"%s\", 0%o, 0%03o) -> %d", pathname, flags, mode, result);
errno = _errno;
return result;
@ -276,7 +278,12 @@ int Getgroups(int size, gid_t list[]) {
#if HAVE_SETGROUPS
int Setgroups(size_t size, const gid_t *list) {
int result, _errno;
Debug2("setgroups("F_Zu", "F_gid",...)", size, list[0]);
switch (size) {
case 0: Debug1("setgroups("F_Zu", [])", size); break;;
case 1: Debug2("setgroups("F_Zu", ["F_gid"])", size, list[0]); break;;
case 2: Debug3("setgroups("F_Zu", ["F_gid","F_gid"])", size, list[0], list[1]); break;;
default: Debug3("setgroups("F_Zu", ["F_gid","F_gid",...])", size, list[0], list[1]); break;;
}
result = setgroups(size, list);
_errno = errno;
Debug1("setgroups() -> %d", result);
@ -285,6 +292,21 @@ int Setgroups(size_t size, const gid_t *list) {
}
#endif
#if HAVE_GETGROUPLIST
int Getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) {
int n = *ngroups, result;
Debug4("getgrouplist(\"%s\", "F_gid", %p, [%d])", user, group, groups, n);
result = getgrouplist(user, group, groups, ngroups);
switch (Min(n,*ngroups)) {
case 0: Debug2("getgrouplist(,, [], [%d]) -> %d", *ngroups, result); break;
case 1: Debug3("getgrouplist(,, ["F_gid"], [%d]) -> %d", groups[0], *ngroups, result); break;
case 2: Debug4("getgrouplist(,, ["F_gid","F_gid"], [%d]) -> %d", groups[0], groups[1], *ngroups, result); break;
default: Debug4("getgrouplist(,, ["F_gid","F_gid",...], [%d]) -> %d", groups[0], groups[1], *ngroups, result); break;
}
return result;
}
#endif
int Chdir(const char *path) {
int result, _errno;
Debug1("chdir(\"%s\")", path);
@ -333,7 +355,7 @@ int Gettimeofday(struct timeval *tv, struct timezone *tz) {
int Mknod(const char *pathname, mode_t mode, dev_t dev) {
int result, _errno;
Debug3("mknod(\"%s\", 0%o, %d)", pathname, mode, dev);
Debug3("mknod(\"%s\", 0%o, "F_dev")", pathname, mode, dev);
result = mknod(pathname, mode, dev);
_errno = errno;
Debug1("mknod() -> %d", result);
@ -354,11 +376,11 @@ int Mkfifo(const char *pathname, mode_t mode) {
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,
t += sprintf(t, "%s(, {"F_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);
t += sprintf(t, ","F_dev, buf->st_rdev);
#endif
t += sprintf(t, ","F_st_size, buf->st_size);
#if HAVE_ST_BLKSIZE
@ -378,11 +400,11 @@ static void prtstat64(const char *func, struct stat64 *buf, int result) {
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,
t += sprintf(t, "%s(, {"F_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);
t += sprintf(t, ","F_dev, buf->st_rdev);
#endif
t += sprintf(t, ","F_st64_size, buf->st_size);
#if HAVE_ST_BLKSIZE
@ -496,9 +518,11 @@ int Pipe(int filedes[2]) {
ssize_t Read(int fd, void *buf, size_t count) {
ssize_t result;
int _errno;
if (!diag_in_handler) diag_flush();
Debug3("read(%d, %p, "F_Zu")", fd, buf, count);
result = read(fd, buf, count);
_errno = errno;
if (!diag_in_handler) diag_flush();
Debug1("read -> "F_Zd, result);
errno = _errno;
return result;
@ -507,9 +531,11 @@ ssize_t Read(int fd, void *buf, size_t count) {
ssize_t Write(int fd, const void *buf, size_t count) {
ssize_t result;
int _errno;
if (!diag_in_handler) diag_flush();
Debug3("write(%d, %p, "F_Zu")", fd, buf, count);
result = write(fd, buf, count);
_errno = errno;
if (!diag_in_handler) diag_flush();
Debug1("write -> "F_Zd, result);
errno = _errno;
return result;
@ -517,8 +543,10 @@ ssize_t Write(int fd, const void *buf, size_t count) {
int Fcntl(int fd, int cmd) {
int result, _errno;
if (!diag_in_handler) diag_flush();
Debug2("fcntl(%d, %d)", fd, cmd);
result = fcntl(fd, cmd);
if (!diag_in_handler) diag_flush();
_errno = errno;
Debug1("fcntl() -> %d", result);
errno = _errno;
@ -527,9 +555,11 @@ int Fcntl(int fd, int cmd) {
int Fcntl_l(int fd, int cmd, long arg) {
int result, _errno;
if (!diag_in_handler) diag_flush();
Debug3("fcntl(%d, %d, %ld)", fd, cmd, arg);
result = fcntl(fd, cmd, arg);
_errno = errno;
if (!diag_in_handler) diag_flush();
Debug1("fcntl() -> %d", result);
errno = _errno;
return result;
@ -537,10 +567,12 @@ int Fcntl_l(int fd, int cmd, long arg) {
int Fcntl_lock(int fd, int cmd, struct flock *l) {
int result, _errno;
if (!diag_in_handler) diag_flush();
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;
if (!diag_in_handler) diag_flush();
Debug1("fcntl() -> %d", result);
errno = _errno;
return result;
@ -571,9 +603,11 @@ int Ftruncate64(int fd, off64_t length) {
#if HAVE_FLOCK
int Flock(int fd, int operation) {
int retval, _errno;
if (!diag_in_handler) diag_flush();
Debug2("flock(%d, %d)", fd, operation);
retval = flock(fd, operation);
_errno = errno;
if (!diag_in_handler) diag_flush();
Debug1("flock() -> %d", retval);
errno = _errno;
return retval;
@ -582,6 +616,7 @@ int Flock(int fd, int operation) {
int Ioctl(int d, int request, void *argp) {
int retval, _errno;
if (!diag_in_handler) diag_flush();
if (argp > (void *)0x10000) { /* fuzzy...*/
Debug4("ioctl(%d, 0x%x, %p{%lu})", d, request, argp, *(unsigned long *)argp);
} else {
@ -589,6 +624,7 @@ int Ioctl(int d, int request, void *argp) {
}
retval = ioctl(d, request, argp);
_errno = errno;
if (!diag_in_handler) diag_flush();
Debug1("ioctl() -> %d", retval);
errno = _errno;
return retval;
@ -687,7 +723,8 @@ int Chmod(const char *path, mode_t mode) {
#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;
int _errno, result;
if (!diag_in_handler) diag_flush();
if (nfds == 4) {
Debug10("poll({%d,0x%02hx,}{%d,0x%02hx,}{%d,0x%02hx,}{%d,0x%02hx,}, %u, %d)",
ufds[0].fd, ufds[0].events, ufds[1].fd, ufds[1].events,
@ -697,12 +734,15 @@ int Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
Debug4("poll({%d,0x%02hx,}, , %u, %d)", ufds[0].fd, ufds[0].events, nfds, timeout);
}
result = poll(ufds, nfds, timeout);
_errno = errno;
if (!diag_in_handler) diag_flush();
if (nfds == 4) {
Debug5("poll(, {,,0x%02hx}{,,0x%02hx}{,,0x%02hx}{,,0x%02hx}) -> %d",
ufds[0].revents, ufds[1].revents, ufds[2].revents, ufds[3].revents, result);
} else {
Debug2("poll(, {,,0x%02hx}) -> %d", ufds[0].revents, result);
}
errno = _errno;
return result;
}
#endif /* HAVE_POLL */
@ -712,34 +752,38 @@ 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) {
int result, _errno;
if (!diag_in_handler) diag_flush();
#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],
n, readfds?readfds->fds_bits[0]:0, writefds?writefds->fds_bits[0]:0,
exceptfds?exceptfds->fds_bits[0]: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],
n, readfds?readfds->__fds_bits[0]:0, writefds?writefds->__fds_bits[0]:0,
exceptfds?exceptfds->__fds_bits[0]:0,
timeout?"&":"NULL/", timeout?timeout->tv_sec:0,
timeout?timeout->tv_usec:0);
#endif
result = select(n, readfds, writefds, exceptfds, timeout);
_errno = errno;
if (!diag_in_handler) diag_flush();
#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],
readfds?readfds->fds_bits[0]:0, writefds?writefds->fds_bits[0]:0,
exceptfds?exceptfds->fds_bits[0]: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],
readfds?readfds->__fds_bits[0]:0, writefds?writefds->__fds_bits[0]:0,
exceptfds?exceptfds->__fds_bits[0]:0,
timeout?"&":"NULL/", timeout?timeout->tv_sec:0,
timeout?timeout->tv_usec:0, result);
#endif
errno = _errno;
return result;
}
@ -757,9 +801,11 @@ pid_t Fork(void) {
pid_t Waitpid(pid_t pid, int *status, int options) {
int _errno;
pid_t retval;
if (!diag_in_handler) diag_flush();
Debug3("waitpid("F_pid", %p, %d)", pid, status, options);
retval = waitpid(pid, status, options);
_errno = errno;
if (!diag_in_handler) diag_flush();
Debug2("waitpid(, {%d}, ) -> "F_pid, *status, retval);
errno = _errno;
return retval;
@ -848,7 +894,9 @@ int Execvp(const char *file, char *const argv[]) {
int System(const char *string) {
int result, _errno;
Debug1("system(\"%s\")", string);
diag_immediate_exit = 1;
result = system(string);
diag_immediate_exit = 0;
_errno = errno;
Debug1("system() -> %d", result);
errno = _errno;
@ -878,12 +926,12 @@ int Socket(int domain, int type, int protocol) {
#endif /* _WITH_SOCKET */
#if _WITH_SOCKET
int Bind(int sockfd, struct sockaddr *my_addr, int addrlen) {
int Bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) {
int result, _errno;
char infobuff[256];
sockaddr_info(my_addr, addrlen, infobuff, sizeof(infobuff));
Debug3("bind(%d, %s, "F_Zd")", sockfd, infobuff, addrlen);
Debug3("bind(%d, %s, "F_socklen")", sockfd, infobuff, addrlen);
result = bind(sockfd, my_addr, addrlen);
_errno = errno;
Debug1("bind() -> %d", result);
@ -893,10 +941,11 @@ int Bind(int sockfd, struct sockaddr *my_addr, int addrlen) {
#endif /* _WITH_SOCKET */
#if _WITH_SOCKET
int Connect(int sockfd, const struct sockaddr *serv_addr, int addrlen) {
int Connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) {
int result, _errno;
char infobuff[256];
if (!diag_in_handler) diag_flush();
/*sockaddr_info(serv_addr, infobuff, sizeof(infobuff));
Debug3("connect(%d, %s, "F_Zd")", sockfd, infobuff, addrlen);*/
#if 0
@ -912,13 +961,14 @@ int Connect(int sockfd, const struct sockaddr *serv_addr, int addrlen) {
((unsigned char *)serv_addr)[14], ((unsigned char *)serv_addr)[15],
addrlen);
#else
Debug4("connect(%d, {%d,%s}, "F_Zd")",
Debug4("connect(%d, {%d,%s}, "F_socklen")",
sockfd, serv_addr->sa_family,
sockaddr_info(serv_addr, addrlen, infobuff, sizeof(infobuff)),
addrlen);
#endif
result = connect(sockfd, serv_addr, addrlen);
_errno = errno;
if (!diag_in_handler) diag_flush();
Debug1("connect() -> %d", result);
errno = _errno;
return result;
@ -941,14 +991,21 @@ int Listen(int s, int backlog) {
/* don't forget to handle EINTR when using Accept() ! */
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
int result, _errno;
fd_set accept_s;
if (!diag_in_handler) diag_flush();
FD_ZERO(&accept_s);
FD_SET(s, &accept_s);
if (diag_select(s+1, &accept_s, NULL, NULL, NULL) < 0) {
return -1;
}
Debug3("accept(%d, %p, %p)", s, addr, addrlen);
result = accept(s, addr, addrlen);
_errno = errno;
if (!diag_in_handler) diag_flush();
if (result >= 0) {
char infobuff[256];
sockaddr_info(addr, *addrlen, infobuff, sizeof(infobuff));
Info5("accept(%d, {%d, %s}, "F_Zd") -> %d", s,
Info5("accept(%d, {%d, %s}, "F_socklen") -> %d", s,
addr->sa_family,
sockaddr_info(addr, *addrlen, infobuff, sizeof(infobuff)),
*addrlen, result);
@ -997,7 +1054,7 @@ int Getpeername(int s, struct sockaddr *name, socklen_t *namelen) {
#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"})",
Debug5("getsockopt(%d, %d, %d, %p, {"F_socklen"})",
s, level, optname, optval, *optlen);
result = getsockopt(s, level, optname, optval, optlen);
_errno = errno;
@ -1031,9 +1088,11 @@ int Setsockopt(int s, int level, int optname, const void *optval, int optlen) {
#if _WITH_SOCKET
int Recv(int s, void *buf, size_t len, int flags) {
int retval, _errno;
if (!diag_in_handler) diag_flush();
Debug4("recv(%d, %p, "F_Zu", %d)", s, buf, len, flags);
retval = recv(s, buf, len, flags);
_errno = errno;
if (!diag_in_handler) diag_flush();
Debug1("recv() -> %d", retval);
errno = _errno;
return retval;
@ -1045,12 +1104,14 @@ 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")",
if (!diag_in_handler) diag_flush();
Debug6("recvfrom(%d, %p, "F_Zu", %d, %p, "F_socklen")",
s, buf, len, flags, from, *fromlen);
retval = recvfrom(s, buf, len, flags, from, fromlen);
_errno = errno;
if (!diag_in_handler) diag_flush();
if (from) {
Debug4("recvfrom(,,,, {%d,%s}, "F_Zd") -> %d",
Debug4("recvfrom(,,,, {%d,%s}, "F_socklen") -> %d",
from->sa_family,
sockaddr_info(from, *fromlen, infobuff, sizeof(infobuff)),
*fromlen, retval);
@ -1065,9 +1126,10 @@ int Recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from,
#if _WITH_SOCKET
int Recvmsg(int s, struct msghdr *msgh, int flags) {
int retval, _errno;
if (!diag_in_handler) diag_flush();
char infobuff[256];
#if defined(HAVE_STRUCT_MSGHDR_MSGCONTROL) && defined(HAVE_STRUCT_MSGHDR_MSGCONTROLLEN) && defined(HAVE_STRUCT_MSGHDR_MSGFLAGS)
Debug10("recvmsg(%d, %p{%p,%u,%p,%u,%p,%u,%d}, %d)", s, msgh,
Debug10("recvmsg(%d, %p{%p,%u,%p,"F_Zu",%p,"F_Zu",%d}, %d)", s, msgh,
msgh->msg_name, msgh->msg_namelen, msgh->msg_iov, msgh->msg_iovlen,
msgh->msg_control, msgh->msg_controllen, msgh->msg_flags, flags);
#else
@ -1077,8 +1139,9 @@ int Recvmsg(int s, struct msghdr *msgh, int flags) {
#endif
retval = recvmsg(s, msgh, flags);
_errno = errno;
if (!diag_in_handler) diag_flush();
#if defined(HAVE_STRUCT_MSGHDR_MSGCONTROLLEN)
Debug5("recvmsg(, {%s,%u,,%u,,%u,}, ) -> %d",
Debug5("recvmsg(, {%s,%u,,"F_Zu",,"F_Zu",}, ) -> %d",
msgh->msg_name?sockaddr_info(msgh->msg_name, msgh->msg_namelen, infobuff, sizeof(infobuff)):"NULL",
msgh->msg_namelen, msgh->msg_iovlen, msgh->msg_controllen,
retval);
@ -1096,10 +1159,12 @@ int Recvmsg(int s, struct msghdr *msgh, int flags) {
#if _WITH_SOCKET
int Send(int s, const void *mesg, size_t len, int flags) {
int retval, _errno;
if (!diag_in_handler) diag_flush();
Debug5("send(%d, %p[%08x...], "F_Zu", %d)",
s, mesg, ntohl(*(unsigned long *)mesg), len, flags);
retval = send(s, mesg, len, flags);
_errno = errno;
if (!diag_in_handler) diag_flush();
Debug1("send() -> %d", retval);
errno = _errno;
return retval;
@ -1112,11 +1177,13 @@ int Sendto(int s, const void *mesg, size_t len, int flags,
int retval, _errno;
char infobuff[256];
if (!diag_in_handler) diag_flush();
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;
if (!diag_in_handler) diag_flush();
Debug1("sendto() -> %d", retval);
errno = _errno;
return retval;
@ -1143,6 +1210,7 @@ unsigned int Sleep(unsigned int seconds) {
return retval;
}
/* obsolete by POSIX.1-2001 */
void Usleep(unsigned long usec) {
Debug1("usleep(%lu)", usec);
usleep(usec);
@ -1199,7 +1267,7 @@ struct hostent *Gethostbyname(const char *name) {
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)",
Debug15("getaddrinfo(%s%s%s, %s%s%s, {%d,%d,%d,%d,"F_socklen",%p,%p,%p}, %p)",
node?"\"":"", node?node:"NULL", node?"\"":"",
service?"\"":"", service?service:"NULL", service?"\"":"",
hints->ai_flags, hints->ai_family, hints->ai_socktype,
@ -1219,7 +1287,7 @@ int Getaddrinfo(const char *node, const char *service,
}
#endif /* (_WITH_IP4 || _WITH_IP6) && HAVE_GETADDRINFO */
#if (WITH_IP4 || WITH_IP6) && HAVE_GETIPNODEBYNAME
#if (WITH_IP4 || WITH_IP6) && HAVE_PROTOTYPE_LIB_getipnodebyname
struct hostent *Getipnodebyname(const char *name, int af, int flags,
int *error_num) {
struct hostent *result;
@ -1234,7 +1302,7 @@ struct hostent *Getipnodebyname(const char *name, int af, int flags,
}
return result;
}
#endif /* (WITH_IP4 || WITH_IP6) && HAVE_GETIPNODEBYNAME */
#endif /* (WITH_IP4 || WITH_IP6) && HAVE_PROTOTYPE_LIB_getipnodebyname */
void *Malloc(size_t size) {
void *result;
@ -1376,7 +1444,7 @@ int Unlockpt(int fd) {
}
#endif /* HAVE_UNLOCKPT */
#if HAVE_PTSNAME /* AIX, not Linux */
#if HAVE_PROTOTYPE_LIB_ptsname /* AIX, not Linux */
char *Ptsname(int fd) {
char *result;
int _errno;
@ -1390,7 +1458,7 @@ char *Ptsname(int fd) {
errno = _errno;
return result;
}
#endif /* HAVE_PTSNAME */
#endif /* HAVE_PROTOTYPE_LIB_ptsname */
int Uname(struct utsname *buf) {
int result, _errno;
@ -1431,6 +1499,7 @@ int Atexit(void (*func)(void)) {
void Exit(int status) {
if (!diag_in_handler) diag_flush();
Debug1("exit(%d)", status);
exit(status);
}

View File

@ -1,5 +1,5 @@
/* source: sycls.h */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __sycls_h_included
@ -37,6 +37,7 @@ 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 Getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups);
int Chdir(const char *path);
int Chroot(const char *path);
int Gettimeofday(struct timeval *tv, struct timezone *tz);
@ -93,8 +94,8 @@ 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 Bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
int Connect(int sockfd, const struct sockaddr *serv_addr, socklen_t 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);
@ -175,6 +176,7 @@ void Add_history(const char *string);
#define Initgroups(u,g) initgroups(u,g)
#define Getgroups(s,l) getgroups(s,l)
#define Setgroups(s,l) setgroups(s,l)
#define Getgrouplist(u,g,gs,n) getgrouplist(u,g,gs,n)
#define Chdir(p) chdir(p)
#define Chroot(p) chroot(p)
#define Gettimeofday(tv,tz) gettimeofday(tv,tz)

View File

@ -1,10 +1,16 @@
/* source: sysincludes.h */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __sysincludes_h_included
#define __sysincludes_h_included 1
#if HAVE_STDBOOL_H
#include <stdbool.h> /* bool, true, false */
#endif
#if HAVE_INTTYPES_H
#include <inttypes.h> /* uint16_t */
#endif
#if HAVE_LIMITS_H
#include <limits.h> /* USHRT_MAX */
#endif
@ -23,7 +29,7 @@
#include <syslog.h> /* openlog(), syslog(), closelog() */
#endif
#include <signal.h> /* signal(), SIGPIPE, SIG_IGN */
#include <time.h> /* struct timeval, strftime() */
#include <time.h> /* struct timeval, strftime(), clock_gettime() */
#if 0
#include <sys/timeb.h> /* struct timeb */
#endif
@ -51,7 +57,9 @@
#if HAVE_SYS_TYPES_H
#include <sys/types.h> /* pid_t, select(), socket(), connect(), open(), u_short */
#endif
#if HAVE_SYS_POLL_H
#if HAVE_POLL_H
#include <poll.h> /* poll() */
#elif HAVE_SYS_POLL_H
#include <sys/poll.h> /* poll() */
#endif
#if HAVE_SYS_SOCKET_H
@ -84,7 +92,7 @@
#if HAVE_SYS_FILE_H
#include <sys/file.h> /* LOCK_EX, on AIX directly included */
#endif
#if _WITH_SOCKET
#if WITH_IP4 || WITH_IP6
# if HAVE_NETINET_IN_H
#include <netinet/in.h> /* struct sockaddr_in, htonl() */
# endif
@ -146,7 +154,9 @@
#if HAVE_UTIL_H
#include <util.h> /* NetBSD, OpenBSD openpty() */
#endif
#if HAVE_LIBUTIL_H
#if HAVE_BSD_LIBUTIL_H
#include <bsd/libutil.h> /* FreeBSD openpty() */
#elif HAVE_LIBUTIL_H
#include <libutil.h> /* FreeBSD openpty() */
#endif
#if HAVE_SYS_STROPTS_H

View File

@ -1,5 +1,5 @@
/* source: sysutils.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* translate socket addresses into human readable form */
@ -16,6 +16,40 @@
#include "utils.h"
#include "sysutils.h"
/* Substitute for Write():
Try to write all bytes before returning; this handles EINTR,
EAGAIN/EWOULDBLOCK, and partial write situations. The drawback is that this
function might block even with O_NONBLOCK option.
Returns <0 on unhandled error, errno valid
Will only return <0 or bytes
*/
ssize_t writefull(int fd, const void *buff, size_t bytes) {
size_t writt = 0;
ssize_t chk;
while (1) {
chk = Write(fd, (const char *)buff + writt, bytes - writt);
if (chk < 0) {
switch (errno) {
case EINTR:
case EAGAIN:
#if EAGAIN != EWOULDBLOCK
case EWOULDBLOCK:
#endif
Warn4("write(%d, %p, "F_Zu"): %s", fd, (const char *)buff+writt, bytes-writt, strerror(errno));
Sleep(1); continue;
default: return -1;
}
} else if (writt+chk < bytes) {
Warn4("write(%d, %p, "F_Zu"): only wrote "F_Zu" bytes, trying to continue ",
fd, (const char *)buff+writt, bytes-writt, chk);
writt += chk;
} else {
writt = bytes;
break;
}
}
return writt;
}
#if WITH_UNIX
void socket_un_init(struct sockaddr_un *sa) {
@ -129,6 +163,9 @@ socklen_t socket_init(int af, union sockaddr_union *sa) {
#endif
#if _WITH_SOCKET
/* writes a textual human readable representation of the sockaddr contents to buff and returns a pointer to buff
writes at most blen bytes to buff including the terminating \0 byte
*/
char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size_t blen) {
union sockaddr_union *sau = (union sockaddr_union *)sa;
char *lbuff = buff;
@ -136,14 +173,16 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
int n;
#if HAVE_STRUCT_SOCKADDR_SALEN
if ((n = snprintf(cp, blen, "LEN=%d ", sau->soa.sa_len)) < 0) {
n = xio_snprintf(cp, blen, "LEN=%d ", sau->soa.sa_len);
if (n < 0 || n >= blen) {
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
*buff = '\0';
return buff;
}
cp += n, blen -= n;
#endif
if ((n = snprintf(cp, blen, "AF=%d ", sau->soa.sa_family)) < 0) {
n = xio_snprintf(cp, blen, "AF=%d ", sau->soa.sa_family);
if (n < 0 || n >= blen) {
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
*buff = '\0';
return buff;
@ -155,7 +194,7 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
case 0:
case AF_UNIX: sockaddr_unix_info(&sau->un, salen, cp+1, blen-1);
cp[0] = '"';
*strchr(cp+1, '\0') = '"';
strncat(cp+1, "\"", 1);
break;
#endif
#if WITH_IP4
@ -167,13 +206,14 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
break;
#endif
default:
if ((n = snprintf(cp, blen, "AF=%d ", sa->sa_family)) < 0) {
n = xio_snprintf(cp, blen, "AF=%d ", sa->sa_family);
if (n < 0 || n >= blen) {
Warn1("sockaddr_info(): buffer too short ("F_Zu")", blen);
*buff = '\0';
return buff;
}
cp += n, blen -= n;
if ((snprintf(cp, blen,
n = xio_snprintf(cp, blen,
"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
((unsigned char *)sau->soa.sa_data)[0],
((unsigned char *)sau->soa.sa_data)[1],
@ -188,7 +228,8 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
((unsigned char *)sau->soa.sa_data)[10],
((unsigned char *)sau->soa.sa_data)[11],
((unsigned char *)sau->soa.sa_data)[12],
((unsigned char *)sau->soa.sa_data)[13])) < 0) {
((unsigned char *)sau->soa.sa_data)[13]);
if (n < 0 || n >= blen) {
Warn("sockaddr_info(): buffer too short");
*buff = '\0';
return buff;
@ -210,18 +251,20 @@ char *sockaddr_unix_info(const struct sockaddr_un *sa, socklen_t salen, char *bu
nextc =
sanitize_string(sa->sun_path, salen-XIOUNIXSOCKOVERHEAD,
ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3);
*nextc = '\0';
strncpy(buff, ubuff, blen);
} else
#endif /* WITH_ABSTRACT_UNIXSOCKET */
{
nextc =
sanitize_string(sa->sun_path,
MIN(UNIX_PATH_MAX, strlen(sa->sun_path)),
ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3);
*nextc = '\0';
strncpy(buff, ubuff, blen);
if (salen <= XIOUNIXSOCKOVERHEAD) {
nextc = sanitize_string ("<anon>", MIN(UNIX_PATH_MAX, strlen("<anon>")),
ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3);
} else {
nextc = sanitize_string(sa->sun_path,
MIN(UNIX_PATH_MAX, strlen(sa->sun_path)),
ubuff, XIOSAN_DEFAULT_BACKSLASH_OCT_3);
}
}
*nextc = '\0';
buff[0] = '\0'; strncat(buff, ubuff, blen-1);
return buff;
}
#endif /* WITH_UNIX */
@ -229,9 +272,9 @@ char *sockaddr_unix_info(const struct sockaddr_un *sa, socklen_t salen, char *bu
#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",
if (xio_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) {
(unsigned int)((addr >> 8) & 0xff), (unsigned int)(addr & 0xff)) >= blen) {
Warn("inet4addr_info(): buffer too short");
buff[blen-1] = '\0';
}
@ -241,12 +284,12 @@ char *inet4addr_info(uint32_t addr, char *buff, size_t blen) {
#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",
if (xio_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) {
htons(sa->sin_port)) >= blen) {
Warn("sockaddr_inet4_info(): buffer too short");
buff[blen-1] = '\0';
}
@ -262,19 +305,19 @@ const char *inet_ntop(int pf, const void *binaddr,
switch (pf) {
case PF_INET:
if ((retlen =
snprintf(addrtext, textlen, "%u.%u.%u.%u",
xio_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 */
>= textlen) {
errno = ENOSPC; return NULL;
}
break;
#if WITH_IP6
case PF_INET6:
if ((retlen =
snprintf(addrtext, textlen, "%x:%x:%x:%x:%x:%x:%x:%x",
xio_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]),
@ -284,8 +327,8 @@ const char *inet_ntop(int pf, const void *binaddr,
ntohs(((uint16_t *)binaddr)[6]),
ntohs(((uint16_t *)binaddr)[7])
))
< 0) {
return NULL; /* errno is valid */
>= textlen) {
errno = ENOSPC; return NULL;
}
break;
#endif /* WITH_IP6 */
@ -302,7 +345,7 @@ const char *inet_ntop(int pf, const void *binaddr,
/* convert the IP6 socket address to human readable form. buff should be at
least 50 chars long. output includes the port number */
char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen) {
if (snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%hu",
if (xio_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],
@ -366,22 +409,56 @@ char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen
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) {
ntohs(sa->sin6_port)) >= blen) {
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.
#if HAVE_GETGROUPLIST || (defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT))
/* fills 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) {
int getusergroups(const char *user, gid_t *list, int *ngroups) {
#if HAVE_GETGROUPLIST
/* we prefer getgrouplist because it may be much faster with many groups, but it is not standard */
gid_t grp, twogrps[2];
int two = 2;
/* getgrouplist requires to pass an extra group id, typically the users primary group, that is then added to the supplementary group list. We don't want such an additional group in the result, but there is not "unspecified" gid value available. Thus we try to find an abitrary supplementary group id that we then pass in a second call to getgrouplist. */
grp = 0;
Getgrouplist(user, grp, twogrps, &two);
if (two == 1) {
/* either user has just this supp group, or none; we try another id */
grp = 1; two = 2;
Getgrouplist(user, grp, twogrps, &two);
if (two == 1) {
/* user has no supp group */
*ngroups = 0;
return 0;
}
/* user has just the first tried group */
*ngroups = 1; list[0] = grp;
return 0;
}
/* find the first supp group that is not our grp, and use its id */
if (twogrps[0] == grp) {
grp = twogrps[1];
} else {
grp = twogrps[0];
}
if (Getgrouplist(user, grp, list, ngroups) < 0) {
return 1;
}
return 0;
#elif defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
/* this is standard (POSIX) but may be slow */
struct group *grp;
size_t i = 0;
int i = 0;
setgrent();
while (grp = getgrent()) {
@ -399,7 +476,9 @@ int getusergroups(const char *user, gid_t *list, size_t *ngroups) {
endgrent();
*ngroups = i;
return 0;
#endif /* HAVE_SETGRENT... */
}
#endif
#if !HAVE_HSTRERROR
const char *hstrerror(int err) {
@ -535,7 +614,7 @@ int ifindexbyname(const char *ifname, int anysock) {
return -1;
}
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
strncpy(ifr.ifr_name, ifname, IFNAMSIZ); /* ok */
if (Ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
Info3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}): %s",
s, ifr.ifr_name, strerror(errno));
@ -587,23 +666,19 @@ int ifindex(const char *ifname, unsigned int *ifindex, int anysock) {
#endif /* WITH_IP4 || WITH_IP6 || WITH_INTERFACE */
/* constructs an environment variable whose name is built from socats uppercase
program name, and underscore and varname; if a variable of this name already
exists a non zero value of overwrite lets the old value be overwritten.
returns 0 on success or <0 if an error occurred. */
int xiosetenv(const char *varname, const char *value, int overwrite) {
# define XIO_ENVNAMELEN 256
const char *progname;
char envname[XIO_ENVNAMELEN];
size_t i, l;
progname = diag_get_string('p');
strncpy(envname, progname, XIO_ENVNAMELEN-1);
l = strlen(progname);
strncpy(envname+l, "_", XIO_ENVNAMELEN-1-l);
for (i = 0; i < l; ++i) envname[i] = toupper(envname[i]);
strncpy(envname+l+1, varname, XIO_ENVNAMELEN-1-l);
if (Setenv(envname, value, overwrite) < 0) {
int _xiosetenv(const char *envname, const char *value, int overwrite, const char *sep) {
char *oldval;
char *newval;
if (overwrite >= 2 && (oldval = getenv(envname)) != NULL) {
size_t newlen = strlen(oldval)+strlen(sep)+strlen(value)+1;
if ((newval = Malloc(newlen+1)) == NULL) {
return -1;
}
snprintf(newval, newlen+1, "%s%s%s", oldval, sep, value);
} else {
newval = (char *)value;
}
if (Setenv(envname, newval, overwrite) < 0) {
Warn3("setenv(\"%s\", \"%s\", 1): %s",
envname, value, strerror(errno));
#if HAVE_UNSETENV
@ -612,37 +687,81 @@ int xiosetenv(const char *varname, const char *value, int overwrite) {
return -1;
}
return 0;
# undef XIO_ENVNAMELEN
}
/* constructs an environment variable whose name is built from socats uppercase
program name, and underscore and varname;
if the variable of this name already exists arg overwrite determines:
0: keep old value
1: overwrite with new value
2: append to old value, separated by *sep
a non zero value of overwrite lets the old value be overwritten.
returns 0 on success or <0 if an error occurred. */
int xiosetenv(const char *varname, const char *value, int overwrite, const char *sep) {
# define XIO_ENVNAMELEN 256
const char *progname;
char envname[XIO_ENVNAMELEN];
size_t i, l;
progname = diag_get_string('p');
envname[0] = '\0'; strncat(envname, progname, XIO_ENVNAMELEN-1);
l = strlen(envname);
for (i = 0; i < l; ++i) envname[i] = toupper(envname[i]);
strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
l += 1;
strncat(envname+l, varname, XIO_ENVNAMELEN-l-1);
return _xiosetenv(envname, value, overwrite, sep);
# undef ENVNAMELEN
}
int xiosetenv2(const char *varname, const char *varname2, const char *value,
int overwrite) {
int overwrite, const char *sep) {
# define XIO_ENVNAMELEN 256
const char *progname;
char envname[XIO_ENVNAMELEN];
size_t i, l;
progname = diag_get_string('p');
strncpy(envname, progname, XIO_ENVNAMELEN-1);
envname[0] = '\0'; strncat(envname, progname, XIO_ENVNAMELEN-1);
l = strlen(progname);
strncpy(envname+l, "_", XIO_ENVNAMELEN-1-l);
strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
l += 1;
strncpy(envname+l, varname, XIO_ENVNAMELEN-1-l);
l += strlen(varname);
strncpy(envname+l, "_", XIO_ENVNAMELEN-1-l);
strncat(envname+l, varname, XIO_ENVNAMELEN-l-1);
l += strlen(envname+l);
strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
l += 1;
strncpy(envname+l, varname2, XIO_ENVNAMELEN-1-l);
l += strlen(varname2);
strncat(envname+l, varname2, XIO_ENVNAMELEN-l-1);
l += strlen(envname+l);
for (i = 0; i < l; ++i) envname[i] = toupper(envname[i]);
if (Setenv(envname, value, overwrite) < 0) {
Warn3("setenv(\"%s\", \"%s\", 1): %s",
envname, value, strerror(errno));
#if HAVE_UNSETENV
Unsetenv(envname); /* dont want to have a wrong value */
#endif
return -1;
}
return 0;
return _xiosetenv(envname, value, overwrite, sep);
# undef XIO_ENVNAMELEN
}
int xiosetenv3(const char *varname, const char *varname2, const char *varname3,
const char *value,
int overwrite, const char *sep) {
# define XIO_ENVNAMELEN 256
const char *progname;
char envname[XIO_ENVNAMELEN];
size_t i, l;
progname = diag_get_string('p');
envname[0] = '\0'; strncat(envname, progname, XIO_ENVNAMELEN-1);
l = strlen(progname);
strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
l += 1;
strncat(envname+l, varname, XIO_ENVNAMELEN-l-1);
l += strlen(envname+l);
strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
l += 1;
strncat(envname+l, varname2, XIO_ENVNAMELEN-l-1);
l += strlen(envname+l);
strncat(envname+l, "_", XIO_ENVNAMELEN-l-1);
l += 1;
strncat(envname+l, varname3, XIO_ENVNAMELEN-l-1);
l += strlen(envname+l);
for (i = 0; i < l; ++i) envname[i] = toupper(envname[i]);
return _xiosetenv(envname, value, overwrite, sep);
# undef XIO_ENVNAMELEN
}
@ -653,7 +772,7 @@ int xiosetenvulong(const char *varname, unsigned long value, int overwrite) {
char envbuff[XIO_LONGLEN];
snprintf(envbuff, XIO_LONGLEN, "%lu", value);
return xiosetenv(varname, envbuff, overwrite);
return xiosetenv(varname, envbuff, overwrite, NULL);
# undef XIO_LONGLEN
}
@ -663,6 +782,6 @@ int xiosetenvushort(const char *varname, unsigned short value, int overwrite) {
char envbuff[XIO_SHORTLEN];
snprintf(envbuff, XIO_SHORTLEN, "%hu", value);
return xiosetenv(varname, envbuff, overwrite);
return xiosetenv(varname, envbuff, overwrite, NULL);
# undef XIO_SHORTLEN
}

View File

@ -1,5 +1,5 @@
/* source: sysutils.h */
/* Copyright Gerhard Rieger 2001-2010 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __sysutils_h_included
@ -40,6 +40,8 @@ struct xiorange {
} ;
#endif /* _WITH_SOCKET */
extern ssize_t writefull(int fd, const void *buff, size_t bytes);
#if _WITH_SOCKET
extern socklen_t socket_init(int af, union sockaddr_union *sa);
#endif
@ -71,7 +73,9 @@ 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 defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
extern int getusergroups(const char *user, gid_t *list, int *ngroups);
#endif
#if !HAVE_HSTRERROR
extern const char *hstrerror(int err);
@ -84,10 +88,13 @@ extern int parseport(const char *portname, int proto);
extern int ifindexbyname(const char *ifname, int anysock);
extern int ifindex(const char *ifname, unsigned int *ifindex, int anysock);
extern int xiosetenv(const char *varname, const char *value, int overwrite);
extern int xiosetenv(const char *varname, const char *value, int overwrite, const char *sep);
extern int
xiosetenv2(const char *varname, const char *varname2, const char *value,
int overwrite);
int overwrite, const char *sep);
extern int
xiosetenv3(const char *varname, const char *varname2, const char *varname3,
const char *value, int overwrite, const char *sep);
extern int xiosetenvulong(const char *varname, unsigned long value,
int overwrite);
extern int xiosetenvushort(const char *varname, unsigned short value,

3557
test.sh

File diff suppressed because it is too large Load Diff

View File

@ -5,5 +5,8 @@ default_bits = 768
distinguished_name=Test
[ Test ]
countryName = XY
countryName=XY
commonName=localhost
O=dest-unreach
OU=socat
L=Lunar Base

37
utils.c
View File

@ -1,5 +1,5 @@
/* source: utils.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* useful additions to C library */
@ -14,7 +14,7 @@
#include "utils.h"
#if !HAVE_MEMRCHR
#if !HAVE_PROTOTYPE_LIB_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;
@ -25,7 +25,7 @@ void *memrchr(const void *s, int c, size_t n) {
return NULL;
return (void *)t;
}
#endif /* !HAVE_MEMRCHR */
#endif /* !HAVE_PROTOTYPE_LIB_memrchr */
void *memdup(const void *src, size_t n) {
void *dest;
@ -67,7 +67,7 @@ const struct wordent *keyw(const struct wordent *keywds, const char *name, unsig
return NULL;
}
/* Linux: setenv(), AIX: putenv() */
/* Linux: setenv(), AIX (4.3?): putenv() */
#if !HAVE_SETENV
int setenv(const char *name, const char *value, int overwrite) {
int result;
@ -90,9 +90,9 @@ int setenv(const char *name, const char *value, int overwrite) {
/* sanitize an "untrusted" character. output buffer must provide at least 5
/* sanitizes an "untrusted" character. output buffer must provide at least 4
characters space.
Does not append null. returns length out output (currently: max 4) */
Does not append \0. returns length of output (currently: max 4) */
static size_t sanitize_char(char c, char *o, int style) {
int hn; /* high nibble */
int ln; /* low nibble */
@ -126,10 +126,12 @@ static size_t sanitize_char(char c, char *o, int style) {
return n;
}
/* sanitize "untrusted" text, replacing special control characters with the C
string version ("\x"), and replacing unprintable chars with ".".
/* sanitizes "untrusted" text, replacing special control characters with the C
string version (eg."\n"), and replacing unprintable chars with hex
representation ("\xAB").
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.
Output is not \0 terminated.
*/
char *sanitize_string(const char *data, /* input data */
size_t bytes, /* length of input data, >=0 */
@ -159,3 +161,22 @@ char *xiosubstr(char *scratch, const char *str, size_t from, size_t len) {
return scratch0;
}
/* since version 1.7.2.4 socat supports C-99 behaviour of snprintf but still
can handle the old glibc case with -1 return on truncation.
Do not rely on exact return value in case of truncation
*/
int xio_snprintf(char *str, size_t size, const char *format, ...) {
va_list ap;
int result;
va_start(ap, format);
result = vsnprintf(str, size, format, ap);
#if ! HAVE_C99_SNPRINTF
if (result < 0) {
result = size+63; /* indicate truncation with just some guess */
}
#endif /* !HAVE_C99_SNPRINTF */
va_end(ap);
return result;
}

View File

@ -1,5 +1,5 @@
/* source: utils.h */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __utils_h_included
@ -11,7 +11,7 @@ struct wordent {
void *desc;
} ;
#if !HAVE_MEMRCHR
#if !HAVE_PROTOTYPE_LIB_memrchr
extern void *memrchr(const void *s, int c, size_t n);
#endif
extern void *memdup(const void *src, size_t n);
@ -66,4 +66,7 @@ char *sanitize_string(const char *data, /* input data */
extern
char *xiosubstr(char *scratch, const char *str, size_t from, size_t len);
extern
int xio_snprintf(char *str, size_t size, const char *format, ...);
#endif /* !defined(__utils_h_included) */

569
vsnprintf_r.c Normal file
View File

@ -0,0 +1,569 @@
/* vsnprintf_r.c */
/* Copyright Gerhard Rieger */
/* a reduced but async-signal-safe and thread-safe version of vsnprintf */
#include "config.h"
#include <stddef.h> /* ptrdiff_t */
#include <ctype.h> /* isdigit() */
#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 "vsnprintf_r.h"
/* helper functions for vsnprintf_r():
e.g. convert an unsigned long to decimal string.
in: field (must be long enough for all digits and \0
n: length of field in bytes
ulo: the value
returns: the pointer to the result string (need not be ==field)
*/
/* this function converts an unsigned long number to decimal ASCII
it is async signal safe and thread safe
it returns NULL if n==0
it returns NULL if field is too short to hold the result
it returns a pointer to the result string (somewhere within field)
it terminates result with \0
*/
static char *_diag_ulong_to_dec(char *field, size_t n, unsigned long ulo) {
char *np = field+n; /* point to the end */
if (n == 0) return NULL;
*--np = '\0'; /* \0 in last char of string */
/* this is not optimal - uses much CPU, but simple to implement */
/* calculate the result from right to left */
do { if (np==field) return NULL; *--np = '0'+(ulo%10); } while (ulo/=10);
return np;
}
/* this function converts an unsigned long number to decimal ASCII
and pads it with space or '0' when size and leading0 are set appropriately
it is async signal safe and thread safe
it returns NULL if n==0
it returns NULL if field is too short to hold the result
it returns a pointer to the result string (somewhere within field)
it reduces size to n-1 if it is greater or equal
it terminates result with \0
*/
static char *diag_ulong_to_dec(char *field, size_t n, unsigned long ulo, int leading0, int size) {
char *np;
char c;
int i;
if (n == 0) return NULL;
np = _diag_ulong_to_dec(field, n, ulo);
if (np == NULL) return np;
if (size) {
if (size >= n) size = n-1;
if (leading0) {
c = '0';
} else {
c = ' ';
}
i = size - strlen(np);
while (--i >= 0) {
*--np = c;
}
}
return np;
}
/* this function converts a signed long number to decimal ASCII
and pads it with space or '0' when size and leading0 are set appropriately
it is async signal safe and thread safe
it returns NULL if n==0
it returns NULL if field is too short to hold the result
it returns a pointer to the result string (somewhere within field)
it reduces size to n-1 if it is greater or equal
it terminates result with \0
*/
/* like diag_ulong_to_dec but signed; fields need also space for '-' */
static char *diag_long_to_dec(char *field, size_t n, long lo, int leading0, int size) {
char *np;
int minus;
unsigned long ulo;
int i;
if ((minus = (lo < 0))) {
ulo = (~lo)+1;
} else {
ulo = lo;
}
np = _diag_ulong_to_dec(field, n, ulo);
if (np == NULL) return np;
if (size) {
if (size >= n) size = n-1;
i = size - strlen(np);
if (leading0) {
if (minus) --i;
while (--i >= 0) {
*--np = '0';
}
if (minus) *--np = '-';
} else {
if (minus) { *--np = '-'; --i; }
while (--i >= 0) {
*--np = ' ';
}
}
} else {
if (minus) *--np = '-';
}
return np;
}
/* this function converts an unsigned long number to hexadecimal ASCII
it is async signal safe and thread safe
it returns NULL if n==0
it returns NULL if field is too short to hold the result
it returns a pointer to the result string (somewhere within field)
it terminates result with \0
*/
static char *diag_ulong_to_hex(char *field, size_t n, unsigned long ulo, int leading0, size_t size) {
char *np = field+n; /* point to the end */
int i;
char c;
if (n == 0) return NULL;
*--np = '\0'; /* \0 in last char of string */
/* calculate the result from right to left */
do { if (np==field) return NULL; i = (ulo&0x0f);
*--np = (i<10?'0':('a'-10))+i; }
while (ulo>>=4);
if (size) {
if (size >= n) size = n-1;
if (leading0) {
c = '0';
} else {
c = ' ';
}
i = size - strlen(np);
while (--i >= 0) {
*--np = c;
}
}
return np;
}
/* this function converts an unsigned long number to octal ASCII
it is async signal safe and thread safe
it returns NULL if n==0
it returns NULL if field is too short to hold the result
it returns a pointer to the result string (somewhere within field)
it terminates result with \0
*/
static char *diag_ulong_to_oct(char *field, size_t n, unsigned long ulo, int leading0, size_t size) {
char *np = field+n; /* point to the end */
int i;
char c;
if (n == 0) return NULL;
*--np = '\0'; /* \0 in last char of string */
/* calculate the result from right to left */
do { if (np==field) return NULL; i = (ulo&0x07); *--np = '0'+i; }
while (ulo>>=3);
if (size) {
if (size >= n) size = n-1;
if (leading0) {
c = '0';
} else {
c = ' ';
}
i = size - strlen(np);
while (--i >= 0) {
*--np = c;
}
}
return np;
}
#if HAVE_TYPE_LONGLONG
/* this function converts an unsigned long long number to decimal ASCII
it is async signal safe and thread safe
it returns NULL if n==0
it returns NULL if field is too short to hold the result
it returns a pointer to the result string (somewhere within field)
it terminates result with \0
*/
static char *_diag_ulonglong_to_dec(char *field, size_t n, unsigned long long ull) {
char *np = field+n; /* point to the end */
if (n == 0) return NULL;
*--np = '\0'; /* \0 in last char of string */
/* this is not optimal - uses much CPU, but simple to implement */
/* calculate the result from right to left */
do { if (np==field) return NULL; *--np = '0'+(ull%10); } while (ull/=10);
return np;
}
/* this function converts an unsigned long long number to decimal ASCII
and pads it with space or '0' when size and leading0 are set appropriately
it is async signal safe and thread safe
it returns NULL if n==0
it returns NULL if field is too short to hold the result
it returns a pointer to the result string (somewhere within field)
it reduces size to n-1 if it is greater or equal
it terminates result with \0
*/
static char *diag_ulonglong_to_dec(char *field, size_t n, unsigned long long ull, int leading0, int size) {
char *np;
char c;
int i;
if (n == 0) return NULL;
np = _diag_ulonglong_to_dec(field, n, ull);
if (size) {
if (size >= n) size = n-1;
if (leading0) {
c = '0';
} else {
c = ' ';
}
i = size - strlen(np);
while (i-- > 0) {
*--np = c;
}
}
return np;
}
/* this function converts a signed long long number to decimal ASCII
and pads it with space or '0' when size and leading0 are set appropriately
it is async signal safe and thread safe
it returns NULL if n==0
it returns NULL if field is too short to hold the result
it returns a pointer to the result string (somewhere within field)
it reduces size to n-1 if it is greater or equal
it terminates result with \0
*/
/* like diag_ulonglong_to_dec but signed; fields need also space for '-' */
static char *diag_longlong_to_dec(char *field, size_t n, long long ll, int leading0, int size) {
char *np;
int minus;
unsigned long ull;
int i;
if ((minus = (ll < 0))) {
ull = (~ll)+1;
} else {
ull = ll;
}
np = _diag_ulonglong_to_dec(field, n, ull);
if (np == NULL) return np;
if (size) {
if (size >= n) size = n-1;
i = size - strlen(np);
if (leading0) {
if (minus) --i;
while (--i >= 0) {
*--np = '0';
}
if (minus) *--np = '-';
} else {
if (minus) { *--np = '-'; --i; }
while (--i >= 0) {
*--np = ' ';
}
}
}
return np;
}
/* this function converts an unsigned long long number to hexadecimal ASCII
it is async signal safe and thread safe
it returns NULL if n==0
it returns NULL if field is too short to hold the result
it returns a pointer to the result string (somewhere within field)
it terminates result with \0
*/
static char *diag_ulonglong_to_hex(char *field, size_t n, unsigned long long ull, int leading0, size_t size) {
char *np = field+n; /* point to the end */
unsigned int i;
char c;
if (n == 0) return NULL;
*--np = '\0'; /* \0 in last char of string */
/* calculate the result from right to left */
do { if (np==field) return NULL; i = (ull&0x0f);
*--np = (i<10?'0':('a'-10))+i; }
while (ull>>=4);
if (size) {
if (size >= n) size = n-1;
if (leading0) {
c = '0';
} else {
c = ' ';
}
i = size - strlen(np);
while (--i >= 0) {
*--np = c;
}
}
return np;
}
/* this function converts an unsigned long long number to octal ASCII
it is async signal safe and thread safe
it returns NULL if n==0
it returns NULL if field is too short to hold the result
it returns a pointer to the result string (somewhere within field)
it terminates result with \0
*/
static char *diag_ulonglong_to_oct(char *field, size_t n, unsigned long long ull, int leading0, size_t size) {
char *np = field+n; /* point to the end */
int i;
char c;
if (n == 0) return NULL;
*--np = '\0'; /* \0 in last char of string */
/* calculate the result from right to left */
do { if (np==field) return NULL; i = (ull&0x07); *--np = '0'+i; }
while (ull>>=3);
if (size) {
if (size >= n) size = n-1;
if (leading0) {
c = '0';
} else {
c = ' ';
}
i = size - strlen(np);
while (--i >= 0) {
*--np = c;
}
}
return np;
}
#endif /* HAVE_TYPE_LONGLONG */
/* this function is designed as a variant of vsnprintf(3) but async signal safe
and thread safe
it currently only implements a subset of the format directives
returns <0 if an error occurred (no scenario know yet)
returns >=size if output is truncated (conforming to C99 standard)
*/
int vsnprintf_r(char *str, size_t size, const char *format, va_list ap) {
size_t i = 0;
char c;
int full = 0; /* indicate if output buffer full */
--size; /* without trailing \0 */
while (c = *format++) {
if (c == '\\') {
} else if (c == '%') {
#if HAVE_TYPE_LONGLONG
# define num_buff_len ((sizeof(unsigned long long)*8+2)/3+1) /* hold up to u long long in octal w/ \0 */
#else
# define num_buff_len ((sizeof(unsigned long)*8+2)/3+1)]; /* hold up to u long in octal w/ \0 */
#endif
char lengthmod = '\0'; /* 'h' 'l' 'L' 'z' */
int leading0 = 0; /* or 1 */
size_t fsize = 0; /* size of field */
const char *st; /* string */
long lo; unsigned long ulo;
#if HAVE_TYPE_LONGLONG
long long ll; unsigned long long ull;
#endif
char field[num_buff_len]; /* result of number conversion */
char *np; /* num pointer */
c = *format++;
if (c == '\0') { break; }
/* flag characters */
switch (c) {
case '0': leading0 = 1; c = *format++; break;
/* not handled: '#' '-' ' ' '+' '\'' */
}
if (c == '\0') { break; }
/* field width */
switch (c) {
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
do {
fsize = 10*fsize+(c-'0');
c = *format++;
} while (c && isdigit(c));
break;
}
if (c == '\0') { break; }
/* precision - not handles */
/* length modifier */
switch (c) {
/* not handled: 'q' 'j' 't' */
/* handled: 'h' 'hh'->'H' 'z' 'Z'->'z' 'l' 'll'->'L' 'L' */
case 'Z': c = 'z'; /* fall through */
#if HAVE_TYPE_LONGLONG
case 'L':
#endif
case 'z': lengthmod = c; c = *format++; break;
case 'h':
lengthmod = c;
if ((c = *format++) == 'h') {
lengthmod = 'H'; c = *format++;
}
break;
case 'l':
lengthmod = c;
if ((c = *format++) == 'l') {
lengthmod = 'L'; c = *format++;
}
break;
}
if (c == '\0') { break; }
/* conversion specifier */
switch (c) {
case 'c': c = va_arg(ap, int); /* fall through */
case '%': *str++ = c; if (++i == size) { full = 1; } break;
case 's': st = va_arg(ap, const char *);
/* no modifier handled! */
while (c = *st++) {
*str++ = c;
if (++i == size) { full = 1; break; }
}
break;
case 'd':
#if HAVE_TYPE_LONGLONG
if (lengthmod == 'L') {
ll = va_arg(ap, long long);
np = diag_longlong_to_dec(field, num_buff_len, ll, leading0, fsize);
while (c = *np++) {
*str++ = c;
if (++i == size) { full = 1; break; }
}
} else
#endif
{
switch (lengthmod) {
case 'l': lo = va_arg(ap, long); break;
case 'z': lo = va_arg(ap, ptrdiff_t); break;
default: lo = va_arg(ap, int); break;
}
np = diag_long_to_dec(field, num_buff_len, lo, leading0, fsize);
while (c = *np++) { *str++ = c;
if (++i == size) { full = 1; break; }
}
}
break;
case 'u':
#if HAVE_TYPE_LONGLONG
if (lengthmod == 'L') {
ull = va_arg(ap, unsigned long long);
np = diag_ulonglong_to_dec(field, num_buff_len, ull, leading0, fsize);
while (c = *np++) { *str++ = c;
if (++i == size) { full = 1; break; }
}
} else
#endif
{
switch (lengthmod) {
case 'l': ulo = va_arg(ap, unsigned long); break;
case 'z': ulo = va_arg(ap, size_t); break;
default: ulo = va_arg(ap, unsigned int); break;
}
np = diag_ulong_to_dec(field, num_buff_len, ulo, leading0, fsize);
while (c = *np++) { *str++ = c;
if (++i == size) { full = 1; break; }
}
}
break;
case 'p':
ulo = va_arg(ap, size_t);
np = diag_ulong_to_hex(field, num_buff_len, ulo, leading0, fsize);
*str++ = '0'; if (++i == size) { full = 1; break; }
*str++ = 'x'; if (++i == size) { full = 1; break; }
while (c = *np++) { *str++ = c;
if (++i == size) { full = 1; break; }
}
break;
case 'x':
#if HAVE_TYPE_LONGLONG
if (lengthmod == 'L') {
ull = va_arg(ap, unsigned long long);
np = diag_ulonglong_to_hex(field, num_buff_len, ull, leading0, fsize);
while (c = *np++) { *str++ = c;
if (++i == size) { full = 1; break; }
}
} else
#endif
{
switch (lengthmod) {
case 'l': ulo = va_arg(ap, unsigned long); break;
case 'z': ulo = va_arg(ap, size_t); break;
default: ulo = va_arg(ap, unsigned int); break;
}
np = diag_ulong_to_hex(field, num_buff_len, ulo, leading0, fsize);
while (c = *np++) { *str++ = c;
if (++i == size) { full = 1; break; }
}
}
break;
case 'o':
#if HAVE_TYPE_LONGLONG
if (lengthmod == 'L') {
ull = va_arg(ap, unsigned long long);
np = diag_ulonglong_to_oct(field, num_buff_len, ull, leading0, fsize);
while (c = *np++) { *str++ = c;
if (++i == size) break;
}
} else
#endif
{
switch (lengthmod) {
case 'l': ulo = va_arg(ap, unsigned long); break;
case 'z': ulo = va_arg(ap, size_t); break;
default: ulo = va_arg(ap, unsigned int); break;
}
np = diag_ulong_to_oct(field, num_buff_len, ulo, leading0, fsize);
while (c = *np++) { *str++ = c;
if (++i == size) { full = 1; break; }
}
}
break;
default:
*str++ = c; if (++i == size) { full = 1; break; }
}
if (full) break;
} else {
*str++ = c;
if (++i == size) break;
}
}
*str = '\0';
return i;
}
int snprintf_r(char *str, size_t size, const char *format, ...) {
int result;
va_list ap;
va_start(ap, format);
result = vsnprintf_r(str, size, format, ap);
va_end(ap);
return result;
}

11
vsnprintf_r.h Normal file
View File

@ -0,0 +1,11 @@
/* source: vsnprintf_r.h */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __vsnprintf_r_h_included
#define __vsnprintf_r_h_included 1
int vsnprintf_r(char *str, size_t size, const char *format, va_list ap);
int snprintf_r(char *str, size_t size, const char *format, ...);
#endif /* !defined(__vsnprintf_r_h_included) */

View File

@ -1,5 +1,5 @@
/* source: xio-ascii.c */
/* Copyright Gerhard Rieger 2002-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains functions for text encoding, decoding, and conversions */
@ -111,6 +111,7 @@ char *
coding specifies how the data is to be presented. Not much to select now.
returns a pointer to the first char in codbuff that has not been overwritten;
it might also point to the first char after the buffer!
this function does not write a terminating \0
*/
static char *
_xiodump(const unsigned char *data, size_t bytes, char *codbuff, size_t codlen,
@ -118,16 +119,17 @@ _xiodump(const unsigned char *data, size_t bytes, char *codbuff, size_t codlen,
int start = 1;
int space = coding & 0xff;
if (bytes <= 0) { codbuff[0] = '\0'; return codbuff; }
if (bytes <= 0) { return codbuff; }
if (codlen < 1) { return codbuff; }
if (space == 0) space = -1;
if (0) {
; /* for canonical reasons */
} else if (1) {
/* simple hexadecimal output */
if (bytes > 2*codlen+1) {
bytes = (codlen-1)/2;
if (3*bytes+1 > codlen) {
bytes = (codlen-1)/3; /* "truncate" data so generated text fits */
}
*codbuff++ = 'x'; --codlen;
*codbuff++ = 'x';
while (bytes-- > 0) {
if (start == 0 && space == 0) {
*codbuff++ = ' ';

View File

@ -1,5 +1,5 @@
/* source: xio-exec.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger 2001-2011 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of exec type */
@ -54,7 +54,7 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
NULL
} ;
char **pargv = NULL;
int pargc, i;
int pargc;
size_t len;
const char *strp;
char *token; /*! */
@ -62,14 +62,12 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
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); /*! */
@ -125,7 +123,7 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
Dup2(duptostderr, 2);
}
Notice1("execvp'ing \"%s\"", token);
result = Execvp(token, pargv);
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;

View File

@ -1,5 +1,5 @@
/* source: xio-gopen.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger 2001-2010 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of generic open type */
@ -46,7 +46,7 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
if (exists && S_ISSOCK(st_mode)) {
#if WITH_UNIX
union sockaddr_union us;
socklen_t uslen;
socklen_t uslen = sizeof(us);
char infobuff[256];
Info1("\"%s\" is a socket, connecting to it", filename);

View File

@ -1,5 +1,5 @@
/* source: xio-ip.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for IP related functions */
@ -129,7 +129,7 @@ int xiogetaddrinfo(const char *node, const char *service,
#if HAVE_GETADDRINFO
struct addrinfo hints = {0};
struct addrinfo *res = NULL;
#else /* HAVE_GETIPNODEBYNAME || nothing */
#else /* HAVE_PROTOTYPE_LIB_getipnodebyname || nothing */
struct hostent *host;
#endif
int error_num;
@ -149,6 +149,9 @@ int xiogetaddrinfo(const char *node, const char *service,
memset(sau, 0, *socklen);
sau->soa.sa_family = family;
if (service && service[0]=='\0') {
Error("empty port/service");
}
/* 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)) {
@ -199,7 +202,7 @@ int xiogetaddrinfo(const char *node, const char *service,
#endif
return STAT_NORETRY;
}
strncpy(numnode, node+1, nodelen-2);
strncpy(numnode, node+1, nodelen-2); /* ok */
numnode[nodelen-2] = '\0';
node = numnode;
#if HAVE_GETADDRINFO
@ -314,7 +317,7 @@ int xiogetaddrinfo(const char *node, const char *service,
}
}
#elif HAVE_GETIPNODEBYNAME /* !HAVE_GETADDRINFO */
#elif HAVE_PROTOTYPE_LIB_getipnodebyname /* !HAVE_GETADDRINFO */
if (node != NULL) {
/* first fallback is getipnodebyname() */
@ -362,7 +365,7 @@ int xiogetaddrinfo(const char *node, const char *service,
freehostent(host);
}
#else /* !HAVE_GETIPNODEBYNAME */
#else /* !HAVE_PROTOTYPE_LIB_getipnodebyname */
if (node != NULL) {
/* this is not a typical IP6 resolver function - but Linux
@ -445,7 +448,17 @@ int xiogetaddrinfo(const char *node, const char *service,
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
/* these are valid for IPv4 and IPv6 */
/* converts the ancillary message in *cmsg into a form useable for further
processing. knows the specifics of common message types.
these are valid for IPv4 and IPv6
returns the number of resulting syntax elements in *num
returns a sequence of \0 terminated type strings in *typbuff
returns a sequence of \0 terminated name strings in *nambuff
returns a sequence of \0 terminated value strings in *valbuff
the respective len parameters specify the available space in the buffers
returns STAT_OK on success
returns STAT_WARNING if a buffer was too short and data truncated.
*/
int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
char *typbuff, int typlen,
char *nambuff, int namlen,
@ -454,15 +467,18 @@ int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
const char *cmsgtype, *cmsgname = NULL, *cmsgenvn = NULL, *cmsgfmt = NULL;
size_t msglen;
char scratch1[16]; /* can hold an IPv4 address in ASCII */
#if WITH_IP4 && defined(IP_PKTINFO) && HAVE_STRUCT_IN_PKTINFO
char scratch2[16];
char scratch3[16];
#endif
int rc = 0;
msglen = cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg);
envbuff[0] = '\0';
switch (cmsg->cmsg_type) {
default:
*num = 1;
strncpy(typbuff, "IP", typlen);
typbuff[0] = '\0'; strncat(typbuff, "IP", typlen-1);
snprintf(nambuff, namlen, "type_%u", cmsg->cmsg_type);
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
return STAT_OK;
@ -471,24 +487,31 @@ int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
case IP_PKTINFO: {
struct in_pktinfo *pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
*num = 3;
strncpy(typbuff, "IP_PKTINFO", typlen);
typbuff[0] = '\0'; strncat(typbuff, "IP_PKTINFO", typlen-1);
snprintf(nambuff, namlen, "%s%c%s%c%s", "if", '\0', "locaddr", '\0', "dstaddr");
snprintf(envbuff, envlen, "%s%c%s%c%s", "IP_IF", '\0',
"IP_LOCADDR", '\0', "IP_DSTADDR");
snprintf(valbuff, vallen, "%s%c%s%c%s",
xiogetifname(pktinfo->ipi_ifindex, scratch1, -1), '\0',
inet4addr_info(ntohl(pktinfo->ipi_spec_dst.s_addr), scratch2, sizeof(scratch2)), '\0',
inet4addr_info(ntohl(pktinfo->ipi_addr.s_addr), scratch3, sizeof(scratch3)));
#if HAVE_PKTINFO_IPI_SPEC_DST
inet4addr_info(ntohl(pktinfo->ipi_spec_dst.s_addr),
scratch2, sizeof(scratch2)),
#else
"",
#endif
'\0',
inet4addr_info(ntohl(pktinfo->ipi_addr.s_addr),
scratch3, sizeof(scratch3)));
}
return STAT_OK;
#endif /* defined(IP_PKTINFO) && HAVE_STRUCT_IN_PKTINFO */
#endif /* WITH_IP4 */
#ifdef IP_RECVERR
#if defined(IP_RECVERR) && HAVE_STRUCT_SOCK_EXTENDED_ERR
case IP_RECVERR: {
struct sock_extended_err *err =
(struct sock_extended_err *)CMSG_DATA(cmsg);
*num = 6;
strncpy(typbuff, "IP_RECVERR", typlen);
typbuff[0] = '\0'; strncat(typbuff, "IP_RECVERR", typlen-1);
snprintf(nambuff, namlen, "%s%c%s%c%s%c%s%c%s%c%s",
"errno", '\0', "origin", '\0', "type", '\0',
"code", '\0', "info", '\0', "data");
@ -501,17 +524,18 @@ int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
err->ee_code, '\0', err->ee_info, '\0', err->ee_data);
return STAT_OK;
}
#endif /* IP_RECVERR */
#endif /* defined(IP_RECVERR) && HAVE_STRUCT_SOCK_EXTENDED_ERR */
#ifdef IP_RECVIF
case IP_RECVIF: {
/* spec in FreeBSD: /usr/include/net/if_dl.h */
struct sockaddr_dl *sadl = (struct sockaddr_dl *)CMSG_DATA(cmsg);
*num = 1;
strncpy(typbuff, "IP_RECVIF", typlen);
strncpy(nambuff, "if", namlen);
strncpy(envbuff, "IP_IF", envlen);
strncpy(valbuff,
xiosubstr(scratch1, sadl->sdl_data, 0, sadl->sdl_nlen), vallen);
typbuff[0] = '\0'; strncat(typbuff, "IP_RECVIF", typlen-1);
nambuff[0] = '\0'; strncat(nambuff, "if", namlen-1);
envbuff[0] = '\0'; strncat(envbuff, "IP_IF", envlen-1);
valbuff[0] = '\0';
strncat(valbuff,
xiosubstr(scratch1, sadl->sdl_data, 0, sadl->sdl_nlen), vallen-1);
return STAT_OK;
}
#endif /* defined(IP_RECVIF) */
@ -519,9 +543,9 @@ int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
#ifdef IP_RECVDSTADDR
case IP_RECVDSTADDR:
*num = 1;
strncpy(typbuff, "IP_RECVDSTADDR", typlen);
strncpy(nambuff, "dstaddr", namlen);
strncpy(envbuff, "IP_DSTADDR", envlen);
typbuff[0] = '\0'; strncat(typbuff, "IP_RECVDSTADDR", typlen-1);
nambuff[0] = '\0'; strncat(nambuff, "dstaddr", namlen-1);
envbuff[0] = '\0'; strncat(envbuff, "IP_DSTADDR", envlen-1);
inet4addr_info(ntohl(*(uint32_t *)CMSG_DATA(cmsg)), valbuff, vallen);
return STAT_OK;
#endif
@ -542,13 +566,13 @@ int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
/* when we come here we provide a single parameter
with type in cmsgtype, name in cmsgname, printf format in cmsgfmt */
*num = 1;
if (strlen(cmsgtype) >= typlen) Fatal("buff too short");
strncpy(typbuff, cmsgtype, typlen);
if (strlen(cmsgname) >= namlen) Fatal("buff too short");
strncpy(nambuff, cmsgname, namlen);
if (strlen(cmsgtype) >= typlen) rc = STAT_WARNING;
typbuff[0] = '\0'; strncat(typbuff, cmsgtype, typlen-1);
if (strlen(cmsgname) >= namlen) rc = STAT_WARNING;
nambuff[0] = '\0'; strncat(nambuff, cmsgname, namlen-1);
if (cmsgenvn) {
if (strlen(cmsgenvn) >= envlen) Fatal("buff too short");
strncpy(envbuff, cmsgenvn, envlen);
if (strlen(cmsgenvn) >= envlen) rc = STAT_WARNING;
envbuff[0] = '\0'; strncat(envbuff, cmsgenvn, envlen-1);
} else {
envbuff[0] = '\0';
}
@ -557,7 +581,7 @@ int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
} else {
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
}
return STAT_OK;
return rc;
}
#endif /* defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA) */

View File

@ -1,5 +1,5 @@
/* source: xio-ip4.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for IP4 related functions */
@ -20,7 +20,7 @@ int xioparsenetwork_ip4(const char *rangename, struct xiorange *range) {
struct in_addr *netmask_in = &range->netmask.ip4.sin_addr;
char *rangename1; /* a copy of rangename with writing allowed */
char *delimpos; /* absolute address of delimiter */
int bits;
unsigned int bits; /* netmask bits */
if ((rangename1 = strdup(rangename)) == NULL) {
Error1("strdup(\"%s\"): out of memory", rangename);
@ -28,8 +28,20 @@ int xioparsenetwork_ip4(const char *rangename, struct xiorange *range) {
}
if (delimpos = strchr(rangename1, '/')) {
bits = strtoul(delimpos+1, NULL, 10);
netmask_in->s_addr = htonl((0xffffffff << (32-bits)));
char *endptr;
bits = strtoul(delimpos+1, &endptr, 10);
if (! ((*(delimpos+1) != '\0') && (*endptr == '\0'))) {
Error1("not a valid netmask in \"%s\"", rangename);
bits = 32; /* most secure selection */
} else if (bits > 32) {
Error1("netmask \"%s\" is too large", rangename);
bits = 32;
}
if (bits <= 0) {
netmask_in->s_addr = 0;
} else {
netmask_in->s_addr = htonl((0xffffffff << (32-bits)));
}
} else if (delimpos = strchr(rangename1, ':')) {
if ((maskaddr = Gethostbyname(delimpos+1)) == NULL) {
/* note: cast is req on AIX: */
@ -55,7 +67,7 @@ int xioparsenetwork_ip4(const char *rangename, struct xiorange *range) {
free(rangename1);
return STAT_NORETRY;
}
netaddr_in->s_addr = *(unsigned long *)nameaddr->h_addr_list[0];
netaddr_in->s_addr = *(uint32_t *)nameaddr->h_addr_list[0];
}
free(rangename1);
return STAT_OK;
@ -108,8 +120,7 @@ xiosetsockaddrenv_ip4(int idx, char *namebuff, size_t namelen,
switch (idx) {
case 0:
strcpy(namebuff, "ADDR");
strcpy(valuebuff,
inet4addr_info(ntohl(sa->sin_addr.s_addr), valuebuff, valuelen));
inet4addr_info(ntohl(sa->sin_addr.s_addr), valuebuff, valuelen);
switch (ipproto) {
case IPPROTO_TCP:
case IPPROTO_UDP:

103
xio-ip6.c
View File

@ -1,5 +1,5 @@
/* source: xio-ip6.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for IP6 related functions */
@ -20,34 +20,44 @@ static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen);
#ifdef IPV6_V6ONLY
const struct optdesc opt_ipv6_v6only = { "ipv6-v6only", "ipv6only", OPT_IPV6_V6ONLY, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_V6ONLY };
const struct optdesc opt_ipv6_v6only = { "ipv6-v6only", "ipv6only", OPT_IPV6_V6ONLY, GROUP_SOCK_IP6, PH_PREBIND, 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
#ifdef IPV6_PKTINFO
const struct optdesc opt_ipv6_pktinfo = { "ipv6-pktinfo", "pktinfo", OPT_IPV6_PKTINFO, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_PKTINFO };
#endif
#ifdef IPV6_RECVPKTINFO
const struct optdesc opt_ipv6_recvpktinfo = { "ipv6-recvpktinfo", "recvpktinfo", OPT_IPV6_RECVPKTINFO, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVPKTINFO };
#endif
#ifdef IPV6_RTHDR
const struct optdesc opt_ipv6_rthdr = { "ipv6-rthdr", "rthdr", OPT_IPV6_RTHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RTHDR };
#endif
#ifdef IPV6_RECVRTHDR
const struct optdesc opt_ipv6_recvrthdr = { "ipv6-recvrthdr", "recvrthdr", OPT_IPV6_RECVRTHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVRTHDR };
#endif
#ifdef IPV6_AUTHHDR
const struct optdesc opt_ipv6_authhdr = { "ipv6-authhdr", "authhdr", OPT_IPV6_AUTHHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_AUTHHDR };
#endif
#ifdef IPV6_DSTOPTS
const struct optdesc opt_ipv6_dstopts = { "ipv6-dstopts", "dstopts", OPT_IPV6_DSTOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_DSTOPTS };
#endif
#ifdef IPV6_RECVDSTOPTS
const struct optdesc opt_ipv6_recvdstopts = { "ipv6-recvdstopts", "recvdstopts", OPT_IPV6_RECVDSTOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVDSTOPTS };
#endif
#ifdef IPV6_HOPOPTS
const struct optdesc opt_ipv6_hopopts = { "ipv6-hopopts", "hopopts", OPT_IPV6_HOPOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_HOPOPTS };
#endif
#ifdef IPV6_RECVHOPOPTS
const struct optdesc opt_ipv6_recvhopopts = { "ipv6-recvhopopts", "recvhopopts", OPT_IPV6_RECVHOPOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVHOPOPTS };
#endif
#ifdef IPV6_FLOWINFO /* is in linux/in6.h */
const struct optdesc opt_ipv6_flowinfo= { "ipv6-flowinfo","flowinfo",OPT_IPV6_FLOWINFO,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_FLOWINFO };
#endif
#ifdef IPV6_HOPLIMIT
const struct optdesc opt_ipv6_hoplimit= { "ipv6-hoplimit","hoplimit",OPT_IPV6_HOPLIMIT,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_HOPLIMIT };
#endif
const struct optdesc opt_ipv6_unicast_hops= { "ipv6-unicast-hops","unicast-hops",OPT_IPV6_UNICAST_HOPS,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_UNICAST_HOPS };
#ifdef IPV6_RECVHOPLIMIT
const struct optdesc opt_ipv6_recvhoplimit= { "ipv6-recvhoplimit","recvhoplimit",OPT_IPV6_RECVHOPLIMIT,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVHOPLIMIT };
@ -68,7 +78,8 @@ const struct optdesc opt_ipv6_recvpathmtu = { "ipv6-recvpathmtu", "recvpathmtu",
int xioparsenetwork_ip6(const char *rangename, struct xiorange *range) {
char *delimpos; /* absolute address of delimiter */
size_t delimind; /* index of delimiter in string */
int bits;
unsigned int bits; /* netmask bits */
char *endptr;
char *baseaddr;
union sockaddr_union sockaddr;
socklen_t sockaddrlen = sizeof(sockaddr);
@ -102,22 +113,32 @@ int xioparsenetwork_ip6(const char *rangename, struct xiorange *range) {
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;
bits = strtoul(delimpos+1, &endptr, 10);
if (! ((*(delimpos+1) != '\0') && (*endptr == '\0'))) {
Error1("not a valid netmask in \"%s\"", rangename);
bits = 128; /* most secure selection */
} else if (bits > 128) {
Error1("netmask \"%s\" is too large", rangename);
bits = 128;
}
if (bits < 32) {
/* I am starting to dislike C...uint32_t << 32 is undefined... */
if (bits == 0) {
rangemask->u6_addr32[0] = 0;
rangemask->u6_addr32[1] = 0;
rangemask->u6_addr32[2] = 0;
rangemask->u6_addr32[3] = 0;
} else 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) {
} 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) {
} else if (bits <= 96) {
rangemask->u6_addr32[0] = 0xffffffff;
rangemask->u6_addr32[1] = 0xffffffff;
rangemask->u6_addr32[2] = htonl(0xffffffff << (96-bits));
@ -189,7 +210,16 @@ int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range) {
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
/* provides info about the ancillary message */
/* provides info about the ancillary message:
converts the ancillary message in *cmsg into a form useable for further
processing. knows the specifics of common message types.
returns the number of resulting syntax elements in *num
returns a sequence of \0 terminated type strings in *typbuff
returns a sequence of \0 terminated name strings in *nambuff
returns a sequence of \0 terminated value strings in *valbuff
the respective len parameters specify the available space in the buffers
returns STAT_OK on success
*/
int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num,
char *typbuff, int typlen,
char *nambuff, int namlen,
@ -203,10 +233,11 @@ int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num,
msglen = cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg);
envbuff[0] = '\0';
switch (cmsg->cmsg_type) {
#if defined(IPV6_PKTINFO) && HAVE_STRUCT_IN6_PKTINFO
case IPV6_PKTINFO: {
struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
*num = 2;
strncpy(typbuff, "IPV6_PKTINFO", typlen);
typbuff[0] = '\0'; strncat(typbuff, "IPV6_PKTINFO", typlen-1);
snprintf(nambuff, namlen, "%s%c%s", "dstaddr", '\0', "if");
snprintf(envbuff, envlen, "%s%c%s", "IPV6_DSTADDR", '\0', "IPV6_IF");
snprintf(valbuff, vallen, "%s%c%s",
@ -214,50 +245,62 @@ int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num,
'\0', xiogetifname(pktinfo->ipi6_ifindex, scratch2, -1));
}
return STAT_OK;
#endif /* defined(IPV6_PKTINFO) && HAVE_STRUCT_IN6_PKTINFO */
#ifdef IPV6_HOPLIMIT
case IPV6_HOPLIMIT:
strncpy(typbuff, "IPV6_HOPLIMIT", typlen);
strncpy(nambuff, "hoplimit", namlen);
snprintf(valbuff, vallen, "%d", *(int *)CMSG_DATA(cmsg));
typbuff[0] = '\0'; strncat(typbuff, "IPV6_HOPLIMIT", typlen-1);
nambuff[0] = '\0'; strncat(nambuff, "hoplimit", namlen-1);
{
int *intp = (int *)CMSG_DATA(cmsg);
snprintf(valbuff, vallen, "%d", *intp);
}
return STAT_OK;
#endif /* defined(IPV6_HOPLIMIT) */
#ifdef IPV6_RTHDR
case IPV6_RTHDR:
strncpy(typbuff, "IPV6_RTHDR", typlen);
strncpy(nambuff, "rthdr", namlen);
typbuff[0] = '\0'; strncat(typbuff, "IPV6_RTHDR", typlen-1);
nambuff[0] = '\0'; strncat(nambuff, "rthdr", namlen-1);
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
return STAT_OK;
#endif /* defined(IPV6_RTHDR) */
#ifdef IPV6_AUTHHDR
case IPV6_AUTHHDR:
strncpy(typbuff, "IPV6_AUTHHDR", typlen);
strncpy(nambuff, "authhdr", namlen);
typbuff[0] = '\0'; strncat(typbuff, "IPV6_AUTHHDR", typlen-1);
nambuff[0] = '\0'; strncat(nambuff, "authhdr", namlen-1);
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
return STAT_OK;
#endif
#ifdef IPV6_DSTOPTS
case IPV6_DSTOPTS:
strncpy(typbuff, "IPV6_DSTOPTS", typlen);
strncpy(nambuff, "dstopts", namlen);
typbuff[0] = '\0'; strncat(typbuff, "IPV6_DSTOPTS", typlen-1);
nambuff[0] = '\0'; strncat(nambuff, "dstopts", namlen-1);
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
return STAT_OK;
#endif /* defined(IPV6_DSTOPTS) */
#ifdef IPV6_HOPOPTS
case IPV6_HOPOPTS:
strncpy(typbuff, "IPV6_HOPOPTS", typlen);
strncpy(nambuff, "hopopts", namlen);
typbuff[0] = '\0'; strncat(typbuff, "IPV6_HOPOPTS", typlen-1);
nambuff[0] = '\0'; strncat(nambuff, "hopopts", namlen-1);
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
return STAT_OK;
#endif /* defined(IPV6_HOPOPTS) */
#ifdef IPV6_FLOWINFO
case IPV6_FLOWINFO:
strncpy(typbuff, "IPV6_FLOWINFO", typlen);
strncpy(nambuff, "flowinfo", namlen);
typbuff[0] = '\0'; strncat(typbuff, "IPV6_FLOWINFO", typlen-1);
nambuff[0] = '\0'; strncat(nambuff, "flowinfo", namlen-1);
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
return STAT_OK;
#endif
#ifdef IPV6_TCLASS
case IPV6_TCLASS:
strncpy(typbuff, "IPV6_TCLASS", typlen);
strncpy(nambuff, "tclass", namlen);
typbuff[0] = '\0'; strncat(typbuff, "IPV6_TCLASS", typlen-1);
nambuff[0] = '\0'; strncat(nambuff, "tclass", namlen-1);
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
return STAT_OK;
#endif
default:
snprintf(typbuff, typlen, "IPV6.%u", cmsg->cmsg_type);
strncpy(nambuff, "data", namlen);
nambuff[0] = '\0'; strncat(nambuff, "data", namlen-1);
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
return STAT_OK;
}
@ -269,7 +312,7 @@ int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num,
/* convert the IP6 socket address to human readable form. buff should be at
least 50 chars long. output includes the port number */
static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen) {
if (snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
if (xio_snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
#if HAVE_IP6_SOCKADDR==0
(sa->s6_addr[0]<<8)+sa->s6_addr[1],
(sa->s6_addr[2]<<8)+sa->s6_addr[3],
@ -325,7 +368,7 @@ static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen)
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[6]),
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[7])
#endif
) < 0) {
) >= blen) {
Warn("sockaddr_inet6_info(): buffer too short");
buff[blen-1] = '\0';
}

View File

@ -1,5 +1,5 @@
/* source: xio-ipapp.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for TCP and UDP related options */
@ -92,12 +92,13 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
if (result == STAT_RETRYLATER) {
Nanosleep(&xfd->intervall, NULL);
}
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
dropopts(opts, PH_ALL); free(opts); opts = copyopts(opts0, GROUP_ALL);
continue;
}
return STAT_NORETRY;
#endif /* WITH_RETRY */
default:
free(opts0);free(opts);
return result;
}
@ -113,6 +114,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
if (xfd->forever || --xfd->retry) {
Nanosleep(&xfd->intervall, NULL); continue;
}
free(opts0);
return STAT_RETRYLATER;
}
@ -125,7 +127,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
Close(xfd->fd);
/* with and without retry */
Nanosleep(&xfd->intervall, NULL);
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
dropopts(opts, PH_ALL); free(opts); opts = copyopts(opts0, GROUP_ALL);
continue; /* with next socket() bind() connect() */
} else
#endif /* WITH_RETRY */
@ -136,8 +138,10 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
/* only "active" process breaks (master without fork, or child) */
if ((result = _xio_openlate(xfd, opts)) < 0) {
free(opts0);free(opts);
return result;
}
free(opts0);free(opts);
return 0;
}

View File

@ -1,5 +1,5 @@
/* source: xio-listen.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for listen socket options */
@ -19,6 +19,7 @@
/***** 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 };
const struct optdesc opt_max_children = { "max-children", NULL, OPT_MAX_CHILDREN, GROUP_CHILD, PH_PASTACCEPT, TYPE_INT, OFUNC_SPEC };
/**/
#if (WITH_UDP || WITH_TCP)
const struct optdesc opt_range = { "range", NULL, OPT_RANGE, GROUP_RANGE, PH_ACCEPT, TYPE_STRING, OFUNC_SPEC };
@ -53,13 +54,7 @@ int
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 */
);
opts, pf, socktype, proto, level);
/*! not sure if we should try again on retry/forever */
switch (result) {
case STAT_OK: break;
@ -114,6 +109,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
int backlog = 5; /* why? 1 seems to cause problems under some load */
char *rangename;
bool dofork = false;
int maxchildren = 0;
char infobuff[256];
char lisname[256];
union sockaddr_union _peername;
@ -134,6 +130,13 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
xfd->flags |= XIO_DOESFORK;
}
retropt_int(opts, OPT_MAX_CHILDREN, &maxchildren);
if (! dofork && maxchildren) {
Error("option max-children not allowed without option fork");
return STAT_NORETRY;
}
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
if (dofork) {
@ -144,14 +147,12 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
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,
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd,
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
strerror(errno));
Close(xfd->fd);
@ -203,6 +204,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport);
#endif /* WITH_TCP || WITH_UDP */
applyopts(xfd->fd, opts, PH_PRELISTEN);
retropt_int(opts, OPT_BACKLOG, &backlog);
if (Listen(xfd->fd, backlog) < 0) {
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
@ -235,11 +237,11 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
continue;
}
if (errno == ECONNABORTED) {
Notice4("accept(%d, %p, {"F_Zu"}): %s",
Notice4("accept(%d, %p, {"F_socklen"}): %s",
xfd->fd, &sa, salen, strerror(errno));
continue;
}
Msg4(level, "accept(%d, %p, {"F_Zu"}): %s",
Msg4(level, "accept(%d, %p, {"F_socklen"}): %s",
xfd->fd, &sa, salen, strerror(errno));
Close(xfd->fd);
return STAT_RETRYLATER;
@ -265,6 +267,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
if (Shutdown(ps, 2) < 0) {
Info2("shutdown(%d, 2): %s", ps, strerror(errno));
}
Close(ps);
continue;
}
@ -273,19 +276,29 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
sockaddr_info((struct sockaddr *)pa, pas,
infobuff, sizeof(infobuff)));
applyopts(xfd->fd, opts, PH_FD);
applyopts(xfd->fd, opts, PH_CONNECTED);
if (dofork) {
pid_t pid; /* mostly int; only used with fork */
sigset_t mask_sigchld;
/* 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_sigchld);
sigaddset(&mask_sigchld, SIGCHLD);
Sigprocmask(SIG_BLOCK, &mask_sigchld, NULL);
if ((pid = xio_fork(false, level==E_ERROR?level:E_WARN)) < 0) {
Close(xfd->fd);
Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);
return STAT_RETRYLATER;
}
if (pid == 0) { /* child */
pid_t cpid = Getpid();
Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);
Info1("just born: client process "F_pid, cpid);
Info1("just born: child process "F_pid, cpid);
xiosetenvulong("PID", cpid, 1);
if (Close(xfd->fd) < 0) {
@ -299,12 +312,6 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
level = E_ERROR;
#endif /* WITH_RETRY */
#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;
}
@ -314,6 +321,17 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
if (Close(ps) < 0) {
Info2("close(%d): %s", ps, strerror(errno));
}
/* now we are ready to handle signals */
Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);
while (maxchildren) {
if (num_child < maxchildren) break;
Notice("maxchildren are active, waiting");
/* UINT_MAX would even be nicer, but Openindiana works only
with 31 bits */
while (!Sleep(INT_MAX)) ; /* any signal lets us continue */
}
Info("still listening");
} else {
if (Close(xfd->fd) < 0) {
@ -323,6 +341,10 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
break;
}
}
applyopts(xfd->fd, opts, PH_FD);
applyopts(xfd->fd, opts, PH_PASTSOCKET);
applyopts(xfd->fd, opts, PH_CONNECTED);
if ((result = _xio_openlate(xfd, opts)) < 0)
return result;

View File

@ -1,5 +1,5 @@
/* source: xio-listen.h */
/* Copyright Gerhard Rieger 2001-2006 */
/* Copyright Gerhard Rieger 2001-2011 */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_listen_h_included
@ -7,6 +7,7 @@
extern const struct optdesc opt_backlog;
extern const struct optdesc opt_fork;
extern const struct optdesc opt_max_children;
extern const struct optdesc opt_range;
int

View File

@ -1,5 +1,5 @@
/* source: xio-named.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for filesystem entry functions */
@ -24,7 +24,7 @@ const struct optdesc opt_unlink_close = { "unlink-close", NULL, OPT_UNLINK_CLOS
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 */
/* applies to filesystem entry all options belonging to phase */
int applyopts_named(const char *filename, struct opt *opts, unsigned int phase) {
struct opt *opt;
@ -96,7 +96,6 @@ 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
@ -120,10 +119,8 @@ int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd,
Error2("stat(\"%s\"): %s", path, strerror(errno));
return STAT_RETRYLATER;
}
iogroups = GROUP_REG;
*exists = false;
} else {
iogroups = _groupbits(statbuf.st_mode);
*exists = true;
}
@ -135,14 +132,13 @@ int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd,
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);
applyopts(-1, opts, PH_EARLY);
if (*exists) {
applyopts_named(path, opts, PH_PREOPEN);
} else {

View File

@ -1,11 +1,14 @@
/* source: xio-openssl.c */
/* Copyright Gerhard Rieger 2002-2009 */
/* Copyright Gerhard Rieger */
/* 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 <openssl/conf.h>
#include <openssl/x509v3.h>
#include "xioopen.h"
#include "xio-fd.h"
@ -45,10 +48,13 @@ 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,
static int openssl_handle_peer_certificate(struct single *xfd,
const char *peername,
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);
static int xioSSL_connect(struct single *xfd, const char *opt_commonname, bool opt_ver, int level);
static int openssl_delete_cert_info(void);
/* description record for ssl connect */
@ -104,9 +110,14 @@ const struct optdesc opt_openssl_cafile = { "openssl-cafile", "cafile",
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 OPENSSL_VERSION_NUMBER >= 0x00908000L
const struct optdesc opt_openssl_compress = { "openssl-compress", "compress", OPT_OPENSSL_COMPRESS, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
#endif
#if WITH_FIPS
const struct optdesc opt_openssl_fips = { "openssl-fips", "fips", OPT_OPENSSL_FIPS, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
#endif
const struct optdesc opt_openssl_commonname = { "openssl-commonname", "cn", OPT_OPENSSL_COMMONNAME, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
const struct optdesc opt_openssl_snihost = { "openssl-snihost", "snihost", OPT_OPENSSL_SNIHOST, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
/* If FIPS is compiled in, we need to track if the user asked for FIPS mode.
@ -134,6 +145,24 @@ int xio_reset_fips_mode(void) {
#define xio_reset_fips_mode() 0
#endif
static void openssl_conn_loginfo(SSL *ssl) {
Notice1("SSL connection using %s", SSL_get_cipher(ssl));
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
{
const COMP_METHOD *comp, *expansion;
comp = sycSSL_get_current_compression(ssl);
expansion = sycSSL_get_current_expansion(ssl);
Notice1("SSL connection compression \"%s\"",
comp?sycSSL_COMP_get_name(comp):"none");
Notice1("SSL connection expansion \"%s\"",
expansion?sycSSL_COMP_get_name(expansion):"none");
}
#endif
}
/* the open function for OpenSSL client */
static int
xioopen_openssl_connect(int argc,
@ -168,6 +197,8 @@ static int
SSL_CTX* ctx;
bool opt_ver = true; /* verify peer certificate */
char *opt_cert = NULL; /* file name of client certificate */
const char *opt_commonname = NULL; /* for checking peer certificate */
const char *opt_snihost = NULL; /* for sni host */
int result;
if (!(xioflags & XIO_MAYCONVERT)) {
@ -182,6 +213,12 @@ static int
}
hostname = argv[1];
portname = argv[2];
if (hostname[0] == '\0') {
/* we catch this explicitely because empty commonname (peername) disables
commonName check of peer certificate */
Error1("%s: empty host name", argv[0]);
return STAT_NORETRY;
}
xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
@ -190,6 +227,16 @@ static int
retropt_bool(opts, OPT_FORK, &dofork);
retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname);
retropt_string(opts, OPT_OPENSSL_SNIHOST, (char **)&opt_snihost);
if (opt_commonname == NULL) {
opt_commonname = hostname;
}
/* could do this, but might not be desired?
if (opt_snihost == NULL) {
opt_snihost = hostname;
} */
result =
_xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert, &ctx);
@ -222,7 +269,7 @@ static int
/* this cannot fork because we retrieved fork option above */
result =
_xioopen_connect(xfd,
needbind?(struct sockaddr *)us:NULL, sizeof(*us),
needbind?(struct sockaddr *)us:NULL, uslen,
(struct sockaddr *)them, themlen,
opts, pf, socktype, ipproto, lowport, level);
switch (result) {
@ -249,7 +296,7 @@ static int
return result;
}
result = _xioopen_openssl_connect(xfd, opt_ver, ctx, level);
result = _xioopen_openssl_connect(xfd, opt_ver, opt_commonname, opt_snihost, ctx, level);
switch (result) {
case STAT_OK: break;
#if WITH_RETRY
@ -304,7 +351,7 @@ static int
break;
} while (true); /* drop out on success */
Notice1("SSL connection using %s", SSL_get_cipher(xfd->para.openssl.ssl));
openssl_conn_loginfo(xfd->para.openssl.ssl);
/* fill in the fd structure */
return STAT_OK;
@ -317,6 +364,8 @@ static int
SSL connection from an FD and a CTX. */
int _xioopen_openssl_connect(struct single *xfd,
bool opt_ver,
const char *opt_commonname,
const char *opt_snihost,
SSL_CTX *ctx,
int level) {
SSL *ssl;
@ -341,14 +390,21 @@ int _xioopen_openssl_connect(struct single *xfd,
return result;
}
result = xioSSL_connect(xfd, opt_ver, level);
if (opt_snihost && !SSL_set_tlsext_host_name(ssl, opt_snihost)) {
sycSSL_free(xfd->para.openssl.ssl);
xfd->para.openssl.ssl = NULL;
return STAT_NORETRY;
}
result = xioSSL_connect(xfd, opt_commonname, 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);
result = openssl_handle_peer_certificate(xfd, opt_commonname,
opt_ver, level);
if (result != STAT_OK) {
sycSSL_free(xfd->para.openssl.ssl);
xfd->para.openssl.ssl = NULL;
@ -390,6 +446,7 @@ static int
SSL_CTX* ctx;
bool opt_ver = true; /* verify peer certificate - changed with 1.6.0 */
char *opt_cert = NULL; /* file name of server certificate */
const char *opt_commonname = NULL; /* for checking peer certificate */
int result;
if (!(xioflags & XIO_MAYCONVERT)) {
@ -422,6 +479,8 @@ static int
Warn("no certificate given; consider option \"cert\"");
}
retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname);
applyopts(-1, opts, PH_EARLY);
result =
@ -480,7 +539,7 @@ static int
return result;
}
result = _xioopen_openssl_listen(xfd, opt_ver, ctx, level);
result = _xioopen_openssl_listen(xfd, opt_ver, opt_commonname, ctx, level);
switch (result) {
case STAT_OK: break;
#if WITH_RETRY
@ -501,8 +560,7 @@ static int
return result;
}
Notice1("SSL connection using %s",
SSL_get_cipher(xfd->para.openssl.ssl));
openssl_conn_loginfo(xfd->para.openssl.ssl);
break;
} /* drop out on success */
@ -515,6 +573,7 @@ static int
int _xioopen_openssl_listen(struct single *xfd,
bool opt_ver,
const char *opt_commonname,
SSL_CTX *ctx,
int level) {
char error_string[120];
@ -582,7 +641,7 @@ int _xioopen_openssl_listen(struct single *xfd,
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));*/
/* Msg1(level, "SSL_accept(): %s", ERR_error_string(e, buf));*/
}
break;
case SSL_ERROR_SSL:
@ -596,7 +655,7 @@ int _xioopen_openssl_listen(struct single *xfd,
return STAT_RETRYLATER;
}
if (openssl_handle_peer_certificate(xfd, opt_ver, E_ERROR/*!*/) < 0) {
if (openssl_handle_peer_certificate(xfd, opt_commonname, opt_ver, E_ERROR/*!*/) < 0) {
return STAT_NORETRY;
}
@ -606,6 +665,59 @@ int _xioopen_openssl_listen(struct single *xfd,
#endif /* WITH_LISTEN */
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
/* In OpenSSL 0.9.7 compression methods could be added using
* SSL_COMP_add_compression_method(3), but the implemntation is not compatible
* with the standard (RFC3749).
*/
static int openssl_setup_compression(SSL_CTX *ctx, char *method)
{
STACK_OF(SSL_COMP)* comp_methods;
assert(method);
/* Getting the stack of compression methods has the intended side-effect of
* initializing the SSL library's compression part.
*/
comp_methods = SSL_COMP_get_compression_methods();
if (!comp_methods) {
Info("OpenSSL built without compression support");
return STAT_OK;
}
if (strcasecmp(method, "auto") == 0) {
Info("Using default OpenSSL compression");
return STAT_OK;
}
if (strcasecmp(method, "none") == 0) {
/* Disable compression */
#ifdef SSL_OP_NO_COMPRESSION
Info("Disabling OpenSSL compression");
SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
#else
/* SSL_OP_NO_COMPRESSION was only introduced in OpenSSL 0.9.9 (released
* as 1.0.0). Removing all compression methods is a work-around for
* earlier versions of OpenSSL, but it affects all SSL connections.
*/
Info("Disabling OpenSSL compression globally");
sk_SSL_COMP_zero(comp_methods);
#endif
return STAT_OK;
}
/* zlib compression in OpenSSL before version 0.9.8e-beta1 uses the libc's
* default malloc/free instead of the ones passed to OpenSSL. Should socat
* ever use custom malloc/free functions for OpenSSL, this must be taken
* into consideration. See OpenSSL bug #1468.
*/
Error1("openssl-compress=\"%s\": unknown compression method", method);
return STAT_NORETRY;
}
#endif
int
_xioopen_openssl_prepare(struct opt *opts,
struct single *xfd,/* a xio file descriptor
@ -617,14 +729,17 @@ int
SSL_CTX **ctx)
{
bool opt_fips = false;
SSL_METHOD *method;
const SSL_METHOD *method = NULL;
char *me_str = NULL; /* method string */
char *ci_str = NULL; /* cipher string */
char *ci_str = "HIGH:-NULL:-PSK:-aNULL"; /* 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 */
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
char *opt_compress = NULL; /* compression method */
#endif
bool opt_pseudo = false; /* use pseudo entropy if nothing else */
unsigned long err;
int result;
@ -642,7 +757,9 @@ int
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 OPENSSL_VERSION_NUMBER >= 0x00908000L
retropt_string(opts, OPT_OPENSSL_COMPRESS, &opt_compress);
#endif
#if WITH_FIPS
if (opt_fips) {
if (!sycFIPS_mode_set(1)) {
@ -655,6 +772,8 @@ int
}
#endif
openssl_delete_cert_info();
OpenSSL_add_all_algorithms();
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
@ -666,42 +785,109 @@ int
/*! actions_to_seed_PRNG();*/
if (!server) {
if (me_str != 0) {
if (!strcasecmp(me_str, "SSLv2") || !strcasecmp(me_str, "SSL2")) {
if (me_str != NULL) {
if (false) {
; /* for canonical reasons */
#if HAVE_SSLv2_client_method
} else if (!strcasecmp(me_str, "SSL2")) {
method = sycSSLv2_client_method();
} else if (!strcasecmp(me_str, "SSLv3") || !strcasecmp(me_str, "SSL3")) {
#endif
#if HAVE_SSLv3_client_method
} else if (!strcasecmp(me_str, "SSL3")) {
method = sycSSLv3_client_method();
} else if (!strcasecmp(me_str, "SSLv23") || !strcasecmp(me_str, "SSL23") ||
!strcasecmp(me_str, "SSL")) {
#endif
#if HAVE_SSLv23_client_method
} else if (!strcasecmp(me_str, "SSL23")) {
method = sycSSLv23_client_method();
} else if (!strcasecmp(me_str, "TLSv1") || !strcasecmp(me_str, "TLS1") ||
!strcasecmp(me_str, "TLS")) {
#endif
#if HAVE_TLSv1_client_method
} else if (!strcasecmp(me_str, "TLS1") || !strcasecmp(me_str, "TLS1.0")) {
method = sycTLSv1_client_method();
#endif
#if HAVE_TLSv1_1_client_method
} else if (!strcasecmp(me_str, "TLS1.1")) {
method = sycTLSv1_1_client_method();
#endif
#if HAVE_TLSv1_2_client_method
} else if (!strcasecmp(me_str, "TLS1.2")) {
method = sycTLSv1_2_client_method();
#endif
#if HAVE_DTLSv1_client_method
} else if (!strcasecmp(me_str, "DTLS") || !strcasecmp(me_str, "DTLS1")) {
method = sycDTLSv1_client_method();
#endif
} else {
Error1("openssl-method=\"%s\": unknown method", me_str);
method = sycSSLv23_client_method()/*!*/;
Error1("openssl-method=\"%s\": method unknown or not provided by library", me_str);
}
} else {
method = sycSSLv23_client_method()/*!*/;
#if HAVE_SSLv23_client_method
method = sycSSLv23_client_method();
#elif HAVE_TLSv1_2_client_method
method = sycTLSv1_2_client_method();
#elif HAVE_TLSv1_1_client_method
method = sycTLSv1_1_client_method();
#elif HAVE_TLSv1_client_method
method = sycTLSv1_client_method();
#elif HAVE_SSLv3_client_method
method = sycSSLv3_client_method();
#elif HAVE_SSLv2_client_method
method = sycSSLv2_client_method();
#else
# error "OpenSSL does not seem to provide client methods"
#endif
}
} else /* server */ {
if (me_str != 0) {
if (!strcasecmp(me_str, "SSLv2") || !strcasecmp(me_str, "SSL2")) {
if (false) {
; /* for canonical reasons */
#if HAVE_SSLv2_server_method
} else if (!strcasecmp(me_str, "SSL2")) {
method = sycSSLv2_server_method();
} else if (!strcasecmp(me_str, "SSLv3") || !strcasecmp(me_str, "SSL3")) {
#endif
#if HAVE_SSLv3_server_method
} else if (!strcasecmp(me_str, "SSL3")) {
method = sycSSLv3_server_method();
} else if (!strcasecmp(me_str, "SSLv23") || !strcasecmp(me_str, "SSL23") ||
!strcasecmp(me_str, "SSL")) {
#endif
#if HAVE_SSLv23_server_method
} else if (!strcasecmp(me_str, "SSL23")) {
method = sycSSLv23_server_method();
} else if (!strcasecmp(me_str, "TLSv1") || !strcasecmp(me_str, "TLS1") ||
!strcasecmp(me_str, "TLS")) {
#endif
#if HAVE_TLSv1_server_method
} else if (!strcasecmp(me_str, "TLS1") || !strcasecmp(me_str, "TLS1.0")) {
method = sycTLSv1_server_method();
#endif
#if HAVE_TLSv1_1_server_method
} else if (!strcasecmp(me_str, "TLS1.1")) {
method = sycTLSv1_1_server_method();
#endif
#if HAVE_TLSv1_2_server_method
} else if (!strcasecmp(me_str, "TLS1.2")) {
method = sycTLSv1_2_server_method();
#endif
#if HAVE_DTLSv1_server_method
} else if (!strcasecmp(me_str, "DTLS") || !strcasecmp(me_str, "DTLS1")) {
method = sycDTLSv1_server_method();
#endif
} else {
Error1("openssl-method=\"%s\": unknown method", me_str);
method = sycSSLv23_server_method()/*!*/;
Error1("openssl-method=\"%s\": method unknown or not provided by library", me_str);
}
} else {
method = sycSSLv23_server_method()/*!*/;
#if HAVE_SSLv23_server_method
method = sycSSLv23_server_method();
#elif HAVE_TLSv1_2_server_method
method = sycTLSv1_2_server_method();
#elif HAVE_TLSv1_1_server_method
method = sycTLSv1_1_server_method();
#elif HAVE_TLSv1_server_method
method = sycTLSv1_server_method();
#elif HAVE_SSLv3_server_method
method = sycSSLv3_server_method();
#elif HAVE_SSLv2_server_method
method = sycSSLv2_server_method();
#else
# error "OpenSSL does not seem to provide client methods"
#endif
}
}
@ -739,6 +925,89 @@ int
return STAT_RETRYLATER;
}
{
static unsigned char dh1024_p[] = {
0xCC,0x17,0xF2,0xDC,0x96,0xDF,0x59,0xA4,0x46,0xC5,0x3E,0x0E,
0xB8,0x26,0x55,0x0C,0xE3,0x88,0xC1,0xCE,0xA7,0xBC,0xB3,0xBF,
0x16,0x94,0xD8,0xA9,0x45,0xA2,0xCE,0xA9,0x5B,0x22,0x25,0x5F,
0x92,0x59,0x94,0x1C,0x22,0xBF,0xCB,0xC8,0xC8,0x57,0xCB,0xBF,
0xBC,0x0E,0xE8,0x40,0xF9,0x87,0x03,0xBF,0x60,0x9B,0x08,0xC6,
0x8E,0x99,0xC6,0x05,0xFC,0x00,0xD6,0x6D,0x90,0xA8,0xF5,0xF8,
0xD3,0x8D,0x43,0xC8,0x8F,0x7A,0xBD,0xBB,0x28,0xAC,0x04,0x69,
0x4A,0x0B,0x86,0x73,0x37,0xF0,0x6D,0x4F,0x04,0xF6,0xF5,0xAF,
0xBF,0xAB,0x8E,0xCE,0x75,0x53,0x4D,0x7F,0x7D,0x17,0x78,0x0E,
0x12,0x46,0x4A,0xAF,0x95,0x99,0xEF,0xBC,0xA6,0xC5,0x41,0x77,
0x43,0x7A,0xB9,0xEC,0x8E,0x07,0x3C,0x6D,
};
static unsigned char dh1024_g[] = {
0x02,
};
DH *dh;
unsigned long err;
if ((dh = DH_new()) == NULL) {
while (err = ERR_get_error()) {
Warn1("DH_new(): %s",
ERR_error_string(err, NULL));
}
Error("DH_new() failed");
} else {
dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
if ((dh->p == NULL) || (dh->g == NULL)) {
while (err = ERR_get_error()) {
Warn1("BN_bin2bn(): %s",
ERR_error_string(err, NULL));
}
Error("BN_bin2bn() failed");
} else {
if (sycSSL_CTX_set_tmp_dh(*ctx, dh) <= 0) {
while (err = ERR_get_error()) {
Warn3("SSL_CTX_set_tmp_dh(%p, %p): %s", *ctx, dh,
ERR_error_string(err, NULL));
}
Error2("SSL_CTX_set_tmp_dh(%p, %p) failed", *ctx, dh);
}
/*! OPENSSL_free(dh->p,g)? doc does not tell so */
}
DH_free(dh);
}
}
#if defined(EC_KEY) /* not on Openindiana 5.11 */
{
/* see http://openssl.6102.n7.nabble.com/Problem-with-cipher-suite-ECDHE-ECDSA-AES256-SHA384-td42229.html */
int nid;
EC_KEY *ecdh;
#if 0
nid = OBJ_sn2nid(ECDHE_CURVE);
if (nid == NID_undef) {
Error("openssl: failed to set ECDHE parameters");
return -1;
}
#endif
nid = NID_X9_62_prime256v1;
ecdh = EC_KEY_new_by_curve_name(nid);
if (NULL == ecdh) {
Error("openssl: failed to set ECDHE parameters");
return -1;
}
SSL_CTX_set_tmp_ecdh(*ctx, ecdh);
}
#endif /* !defined(EC_KEY) */
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
if (opt_compress) {
int result;
result = openssl_setup_compression(*ctx, opt_compress);
if (result != STAT_OK) {
return result;
}
}
#endif
if (opt_cafile != NULL || opt_capath != NULL) {
if (sycSSL_CTX_load_verify_locations(*ctx, opt_cafile, opt_capath) != 1) {
int result;
@ -750,6 +1019,10 @@ int
return STAT_RETRYLATER;
}
}
#ifdef HAVE_SSL_CTX_set_default_verify_paths
} else {
SSL_CTX_set_default_verify_paths(*ctx);
#endif
}
if (opt_cert) {
@ -786,8 +1059,12 @@ int
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);
if (sycSSL_CTX_set_tmp_dh(*ctx, dh) <= 0) {
while (err = ERR_get_error()) {
Warn3("SSL_CTX_set_tmp_dh(%p, %p): %s", *ctx, dh,
ERR_error_string(err, NULL));
}
Error2("SSL_CTX_set_tmp_dh(%p, %p): error", *ctx, dh);
}
}
}
@ -828,19 +1105,21 @@ int
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" */
int stat = STAT_OK;
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;
while (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\"");
stat = STAT_NORETRY;
} else {
Msg2(level, "%s(): %s", funcname, ERR_error_string(e, buf));
stat = level==E_ERROR ? STAT_NORETRY : STAT_RETRYLATER;
}
}
return STAT_OK;
return stat;
}
static const char *openssl_verify_messages[] = {
@ -897,50 +1176,172 @@ static const char *openssl_verify_messages[] = {
/* 50 */ "application verification failure",
} ;
/* delete all environment variables whose name begins with SOCAT_OPENSSL_
resp. <progname>_OPENSSL_ */
static int openssl_delete_cert_info(void) {
# define XIO_ENVNAMELEN 256
const char *progname;
char envprefix[XIO_ENVNAMELEN];
char envname[XIO_ENVNAMELEN];
size_t i, l;
const char **entry;
progname = diag_get_string('p');
envprefix[0] = '\0'; strncat(envprefix, progname, XIO_ENVNAMELEN-1);
l = strlen(envprefix);
for (i = 0; i < l; ++i) envprefix[i] = toupper(envprefix[i]);
strncat(envprefix+l, "_OPENSSL_", XIO_ENVNAMELEN-l-1);
#if HAVE_VAR_ENVIRON
entry = (const char **)environ;
while (*entry != NULL) {
if (!strncmp(*entry, envprefix, strlen(envprefix))) {
const char *eq = strchr(*entry, '=');
if (eq == NULL) eq = *entry + strlen(*entry);
envname[0] = '\0'; strncat(envname, *entry, eq-*entry);
Unsetenv(envname);
} else {
++entry;
}
}
#endif /* HAVE_VAR_ENVIRON */
return 0;
}
/* read in the "name" information (from field "issuer" or "subject") and
create environment variable with complete info, eg:
SOCAT_OPENSSL_X509_SUBJECT */
static int openssl_setenv_cert_name(const char *field, X509_NAME *name) {
BIO *bio = BIO_new(BIO_s_mem());
char *buf = NULL, *str;
size_t len;
X509_NAME_print_ex(bio, name, 0, XN_FLAG_ONELINE&~ASN1_STRFLGS_ESC_MSB); /* rc not documented */
len = BIO_get_mem_data (bio, &buf);
if ((str = Malloc(len+1)) == NULL) {
BIO_free(bio);
return -1;
}
memcpy(str, buf, len);
str[len] = '\0';
Info2("SSL peer cert %s: \"%s\"", field, buf);
xiosetenv2("OPENSSL_X509", field, str, 1, NULL);
free(str);
BIO_free(bio);
return 0;
}
/* read in the "name" information (from field "issuer" or "subject") and
create environment variables with the fields, eg:
SOCAT_OPENSSL_X509_COMMONNAME
*/
static int openssl_setenv_cert_fields(const char *field, X509_NAME *name) {
int n, i;
n = X509_NAME_entry_count(name);
/* extract fields of cert name */
for (i = 0; i < n; ++i) {
X509_NAME_ENTRY *entry;
ASN1_OBJECT *obj;
ASN1_STRING *data;
unsigned char *text;
int nid;
entry = X509_NAME_get_entry(name, i);
obj = X509_NAME_ENTRY_get_object(entry);
data = X509_NAME_ENTRY_get_data(entry);
nid = OBJ_obj2nid(obj);
text = ASN1_STRING_data(data);
Debug3("SSL peer cert %s entry: %s=\"%s\"", (field[0]?field:"subject"), OBJ_nid2ln(nid), text);
if (field != NULL && field[0] != '\0') {
xiosetenv3("OPENSSL_X509", field, OBJ_nid2ln(nid), (const char *)text, 2, " // ");
} else {
xiosetenv2("OPENSSL_X509", OBJ_nid2ln(nid), (const char *)text, 2, " // ");
}
}
return 0;
}
/* compares the peername used/provided by the client to cn as extracted from
the peer certificate.
supports wildcard cn like *.domain which matches domain and
host.domain
returns true on match */
static bool openssl_check_name(const char *cn, const char *peername) {
const char *dotp;
if (peername == NULL) {
Info1("commonName \"%s\": no peername", cn);
return false;
} else if (peername[0] == '\0') {
Info1("commonName \"%s\": matched by empty peername", cn);
return true;
}
if (! (cn[0] == '*' && cn[1] == '.')) {
/* normal server name - this is simple */
Debug1("commonName \"%s\" has no wildcard", cn);
if (strcmp(cn, peername) == 0) {
Debug2("commonName \"%s\" matches peername \"%s\"", cn, peername);
return true;
} else {
Info2("commonName \"%s\" does not match peername \"%s\"", cn, peername);
return false;
}
}
/* wildcard cert */
Debug1("commonName \"%s\" is a wildcard name", cn);
/* case: just the base domain */
if (strcmp(cn+2, peername) == 0) {
Debug2("wildcard commonName \"%s\" matches base domain \"%s\"", cn, peername);
return true;
}
/* case: subdomain; only one level! */
dotp = strchr(peername, '.');
if (dotp == NULL) {
Info2("peername \"%s\" is not a subdomain, thus is not matched by wildcard commonName \"%s\"",
peername, cn);
return false;
}
if (strcmp(cn+1, dotp) != 0) {
Info2("commonName \"%s\" does not match subdomain peername \"%s\"", cn, peername);
return false;
}
Debug2("commonName \"%s\" matches subdomain peername \"%s\"", cn, peername);
return true;
}
/* retrieves the commonName field and compares it to the peername
returns true on match, false otherwise */
static bool openssl_check_peername(X509_NAME *name, const char *peername) {
int ind = -1;
X509_NAME_ENTRY *entry;
ASN1_STRING *data;
unsigned char *text;
ind = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
if (ind < 0) {
Info("no COMMONNAME field in peer certificate");
return false;
}
entry = X509_NAME_get_entry(name, ind);
data = X509_NAME_ENTRY_get_data(entry);
text = ASN1_STRING_data(data);
return openssl_check_name((const char *)text, peername);
}
/* retrieves certificate provided by peer, sets env vars containing
certificates field values, and checks peername if provided by
calling function */
/* parts of this code were copied from Gene Spaffords C/C++ Secure Programming at Etutorials.org:
http://etutorials.org/Programming/secure+programming/Chapter+10.+Public+Key+Infrastructure/10.8+Adding+Hostname+Checking+to+Certificate+Verification/
The code examples in this tutorial do not seem to have explicit license restrictions.
*/
static int openssl_handle_peer_certificate(struct single *xfd,
const char *peername,
bool opt_ver, int level) {
X509 *peer_cert;
char *str;
char buff[2048]; /* hold peer certificate */
X509_NAME *subjectname, *issuername;
/*ASN1_TIME not_before, not_after;*/
int extcount, i, ok = 0;
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 ((peer_cert = SSL_get_peer_certificate(xfd->para.openssl.ssl)) == NULL) {
if (opt_ver) {
Msg(level, "no peer certificate");
status = STAT_RETRYLATER;
@ -948,8 +1349,113 @@ static int openssl_handle_peer_certificate(struct single *xfd,
Notice("no peer certificate and no check");
status = STAT_OK;
}
return status;
}
/* verify peer certificate (trust, signature, validity dates) */
if (opt_ver) {
long verify_result;
if ((verify_result = sycSSL_get_verify_result(xfd->para.openssl.ssl)) != X509_V_OK) {
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;
X509_free(peer_cert);
return STAT_RETRYLATER;
}
Info("peer certificate is trusted");
}
/* set env vars from cert's subject and issuer values */
if ((subjectname = X509_get_subject_name(peer_cert)) != NULL) {
openssl_setenv_cert_name("subject", subjectname);
openssl_setenv_cert_fields("", subjectname);
/*! I'd like to provide dates too; see
http://markmail.org/message/yi4vspp7aeu3xwtu#query:+page:1+mid:jhnl4wklif3pgzqf+state:results */
}
if ((issuername = X509_get_issuer_name(peer_cert)) != NULL) {
openssl_setenv_cert_name("issuer", issuername);
}
/* check peername against cert's subjectAltName DNS entries */
/* this code is based on example from Gerhard Gappmeier in
http://openssl.6102.n7.nabble.com/How-to-extract-subjectAltName-td17236.html
*/
if ((extcount = X509_get_ext_count(peer_cert)) > 0) {
for (i = 0; !ok && i < extcount; ++i) {
const char *extstr;
X509_EXTENSION *ext;
const X509V3_EXT_METHOD *meth;
ext = X509_get_ext(peer_cert, i);
extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
if (!strcasecmp(extstr, "subjectAltName")) {
void *names;
if (!(meth = X509V3_EXT_get(ext))) break;
names = X509_get_ext_d2i(peer_cert, NID_subject_alt_name, NULL, NULL);
if (names) {
int numalts;
int i;
/* get amount of alternatives, RFC2459 claims there MUST be at least one, but we don't depend on it... */
numalts = sk_GENERAL_NAME_num ( names );
/* loop through all alternatives */
for ( i=0; ( i<numalts ); i++ ) {
/* get a handle to alternative name number i */
const GENERAL_NAME *pName = sk_GENERAL_NAME_value (names, i );
unsigned char *pBuffer;
switch ( pName->type ) {
case GEN_DNS:
ASN1_STRING_to_UTF8(&pBuffer,
pName->d.ia5);
xiosetenv("OPENSSL_X509V3_SUBJECTALTNAME_DNS", (char *)pBuffer, 2, " // ");
if (peername != NULL &&
openssl_check_name((char *)pBuffer, /*const char*/peername)) {
ok = 1;
}
OPENSSL_free(pBuffer);
break;
default: continue;
}
}
}
}
}
}
if (!opt_ver) {
Notice("option openssl-verify disabled, no check of certificate");
X509_free(peer_cert);
return STAT_OK;
}
if (peername == NULL || peername[0] == '\0') {
Notice("trusting certificate, no check of commonName");
X509_free(peer_cert);
return STAT_OK;
}
if (ok) {
Notice("trusting certificate, commonName matches");
X509_free(peer_cert);
return STAT_OK;
}
/* here: all envs set; opt_ver, cert verified, no subjAltName match -> check subject CN */
if (!openssl_check_peername(/*X509_NAME*/subjectname, /*const char*/peername)) {
Error("certificate is valid but its commonName does not match hostname");
status = STAT_NORETRY;
} else {
Notice("trusting certificate, commonName matches");
status = STAT_OK;
}
X509_free(peer_cert);
return status;
}
@ -974,7 +1480,8 @@ static int xioSSL_set_fd(struct single *xfd, int level) {
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) {
static int xioSSL_connect(struct single *xfd, const char *opt_commonname,
bool opt_ver, int level) {
char error_string[120];
int errint, status, ret;
unsigned long err;
@ -1019,7 +1526,7 @@ static int xioSSL_connect(struct single *xfd, bool opt_ver, int level) {
break;
case SSL_ERROR_SSL:
status = openssl_SSL_ERROR_SSL(level, "SSL_connect");
if (openssl_handle_peer_certificate(xfd, opt_ver, level/*!*/) < 0) {
if (openssl_handle_peer_certificate(xfd, opt_commonname, opt_ver, level/*!*/) < 0) {
return STAT_RETRYLATER;
}
break;
@ -1047,6 +1554,7 @@ ssize_t xioread_openssl(struct single *pipe, void *buff, size_t bufsiz) {
case SSL_ERROR_NONE:
/* this is not an error, but I dare not continue for security reasons*/
Error("ok");
break;
case SSL_ERROR_ZERO_RETURN:
Error("connection closed by peer");
break;

View File

@ -1,5 +1,5 @@
/* source: xio-openssl.h */
/* Copyright Gerhard Rieger 2002-2007 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_openssl_included
@ -23,9 +23,14 @@ 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 OPENSSL_VERSION_NUMBER >= 0x00908000L
extern const struct optdesc opt_openssl_compress;
#endif
#if WITH_FIPS
extern const struct optdesc opt_openssl_fips;
#endif
extern const struct optdesc opt_openssl_commonname;
extern const struct optdesc opt_openssl_snihost;
extern int
_xioopen_openssl_prepare(struct opt *opts, struct single *xfd,
@ -33,9 +38,12 @@ extern int
SSL_CTX **ctx);
extern int
_xioopen_openssl_connect(struct single *xfd, bool opt_ver,
const char *opt_commonname,
const char *opt_snihost,
SSL_CTX *ctx, int level);
extern int
_xioopen_openssl_listen(struct single *xfd, bool opt_ver,
const char *opt_commonname,
SSL_CTX *ctx, int level);
extern int xioclose_openssl(xiofile_t *xfd);
extern int xioshutdown_openssl(xiofile_t *xfd, int how);

View File

@ -1,5 +1,5 @@
/* source: xio-pipe.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of pipe type */
@ -100,6 +100,7 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof
applyopts(-1, opts, PH_INIT);
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
applyopts_named(pipename, opts, PH_EARLY); /* umask! */
applyopts(-1, opts, PH_EARLY);
if (opt_unlink_early) {
@ -146,6 +147,8 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof
}
#endif
Notice2("created named pipe \"%s\" for %s", pipename, ddirection[rw]);
applyopts_named(pipename, opts, PH_ALL);
}
if (opt_unlink_close) {
if ((fd->stream.unlink_close = strdup(pipename)) == NULL) {

View File

@ -1,5 +1,5 @@
/* source: xio-process.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file handles process related addresses options */
@ -16,7 +16,9 @@ const struct optdesc opt_setuid_early= { "setuid-early",NULL, OPT_SETUID_EARLY,
const struct optdesc opt_setuid = { "setuid", NULL, OPT_SETUID, GROUP_PROCESS, PH_LATE2, TYPE_UIDT, OFUNC_SPEC };
const struct optdesc opt_substuser_early = { "substuser-early", "su-e", OPT_SUBSTUSER_EARLY, GROUP_PROCESS, PH_EARLY, TYPE_UIDT, OFUNC_SPEC };
const struct optdesc opt_substuser = { "substuser", "su", OPT_SUBSTUSER, GROUP_PROCESS, PH_LATE2, TYPE_UIDT, OFUNC_SPEC };
#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
const struct optdesc opt_substuser_delayed = { "substuser-delayed", "su-d", OPT_SUBSTUSER_DELAYED, GROUP_PROCESS, PH_INIT, TYPE_UIDT, OFUNC_SPEC };
#endif
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 };
@ -28,7 +30,7 @@ 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 */
int 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 */
@ -38,7 +40,7 @@ int _xioopen_setdelayeduser(void) {
if (delayeduser) {
#if HAVE_SETGROUPS
if ((Setgroups(delayeduser_ngids, delayeduser_gids)) != 0) {
Error3("setgroups("F_Zu", %p): %s",
Error3("setgroups(%d, %p): %s",
delayeduser_ngids, delayeduser_gids, strerror(errno));
}
#endif /* HAVE_SETGROUPS */

View File

@ -1,5 +1,5 @@
/* source: xio-process.h */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_process_h_included
@ -11,7 +11,9 @@ extern const struct optdesc opt_setuid_early;
extern const struct optdesc opt_setuid;
extern const struct optdesc opt_substuser_early;
extern const struct optdesc opt_substuser;
#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
extern const struct optdesc opt_substuser_delayed;
#endif
extern const struct optdesc opt_chroot_early;
extern const struct optdesc opt_chroot;
extern const struct optdesc opt_setsid;
@ -22,7 +24,7 @@ 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 int 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 */

View File

@ -1,5 +1,5 @@
/* source: xio-progcall.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains common code dealing with program calls (exec, system) */
@ -103,8 +103,17 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
usepipes = false;
}
#endif /* HAVE_PTY */
retropt_ushort(popts, OPT_FDIN, (unsigned short *)&fdi);
retropt_ushort(popts, OPT_FDOUT, (unsigned short *)&fdo);
if (retropt_ushort(popts, OPT_FDIN, (unsigned short *)&fdi) >= 0) {
if ((xioflags&XIO_ACCMODE) == XIO_RDONLY) {
Error("_xioopen_foxec(): option fdin is useless in read-only mode");
}
}
if (retropt_ushort(popts, OPT_FDOUT, (unsigned short *)&fdo) >= 0) {
if ((xioflags&XIO_ACCMODE) == XIO_WRONLY) {
Error("_xioopen_foxec(): option fdout is useless in write-only mode");
}
}
if (withfork) {
if (!(xioflags&XIO_MAYCHILD)) {
@ -229,17 +238,17 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
Warn2("unlockpt(%d): %s", ptyfd, strerror(errno));
}
#endif /* HAVE_UNLOCKPT */
#if HAVE_PTSNAME /* AIX, not Linux */
#if HAVE_PROTOTYPE_LIB_ptsname /* AIX, not Linux */
if ((tn = Ptsname(ptyfd)) == NULL) {
Warn2("ptsname(%d): %s", ptyfd, strerror(errno));
}
#endif /* HAVE_PTSNAME */
#endif /* HAVE_PROTOTYPE_LIB_ptsname */
if (tn == NULL) {
if ((tn = Ttyname(ptyfd)) == NULL) {
Warn2("ttyname(%d): %s", ptyfd, strerror(errno));
Error2("ttyname(%d): %s", ptyfd, strerror(errno));
}
}
strncpy(ptyname, tn, MAXPTYNAMELEN);
ptyname[0] = '\0'; strncat(ptyname, tn, MAXPTYNAMELEN-1);
if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) {
Warn2("open(\"%s\", O_RDWR|O_NOCTTY, 0620): %s", tn, strerror(errno));
} else {

View File

@ -1,5 +1,5 @@
/* source: xio-proxy.c */
/* Copyright Gerhard Rieger 2002-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of HTTP proxy CONNECT
@ -275,8 +275,9 @@ int _xioopen_proxy_connect(struct single *xfd,
struct proxyvars *proxyvars,
int level) {
size_t offset;
char request[CONNLEN];
char buff[BUFLEN+1];
char request[CONNLEN]; /* HTTP connection request line */
int rv;
char buff[BUFLEN+1]; /* for receiving HTTP reply headers */
#if CONNLEN > BUFLEN
#error not enough buffer space
#endif
@ -286,17 +287,18 @@ int _xioopen_proxy_connect(struct single *xfd,
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);
rv = snprintf(request, CONNLEN, "CONNECT %s:%u HTTP/1.0\r\n",
proxyvars->targetaddr, proxyvars->targetport);
if (rv >= CONNLEN || rv < 0) {
Error("_xioopen_proxy_connect(): PROXY CONNECT buffer too small");
return -1;
}
/* 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) {
if (writefull(xfd->fd, request, strlen(request)) < 0) {
Msg4(level, "write(%d, %p, "F_Zu"): %s",
xfd->fd, request, strlen(request), strerror(errno));
if (Close(xfd->fd) < 0) {
@ -326,10 +328,7 @@ int _xioopen_proxy_connect(struct single *xfd,
*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) {
if (writefull(xfd->fd, header, strlen(header)) < 0) {
Msg4(level, "write(%d, %p, "F_Zu"): %s",
xfd->fd, header, strlen(header), strerror(errno));
if (Close(xfd->fd) < 0) {
@ -342,10 +341,14 @@ int _xioopen_proxy_connect(struct single *xfd,
}
Info("sending \"\\r\\n\"");
do {
sresult = Write(xfd->fd, "\r\n", 2);
} while (sresult < 0 && errno == EINTR);
/*! */
if (writefull(xfd->fd, "\r\n", 2) < 0) {
Msg2(level, "write(%d, \"\\r\\n\", 2): %s",
xfd->fd, strerror(errno));
if (Close(xfd->fd) < 0) {
Info2("close(%d): %s", xfd->fd, strerror(errno));
}
return STAT_RETRYLATER;
}
/* request is kept for later error messages */
*strstr(request, " HTTP") = '\0';
@ -549,7 +552,7 @@ int _xioopen_proxy_connect(struct single *xfd,
}
if (offset >= BUFLEN) {
Msg1(level, "proxy answer exceeds "F_Zu" bytes, aborting", BUFLEN);
Msg1(level, "proxy answer exceeds %d bytes, aborting", BUFLEN);
return STAT_NORETRY;
}

View File

@ -1,5 +1,5 @@
/* source: xio-pty.c */
/* Copyright Gerhard Rieger 2002-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for creating pty addresses */
@ -47,6 +47,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
compatibility we choose "no" as default */
struct timespec pollintv = { PTY_INTERVALL };
if (argc != 1) {
Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1);
}
xfd->stream.howtoend = END_CLOSE;
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
@ -74,7 +78,9 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
useptmx = true;
# endif /* !HAVE_OPENPTY */
#else
# if HAVE_OPENPTY
useopenpty = true;
# endif /* HAVE_OPENPTY */
#endif /* ! (defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)) */
#if HAVE_POLL
@ -114,19 +120,19 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
Warn2("unlockpt(%d): %s", ptyfd, strerror(errno));
}
#endif /* HAVE_UNLOCKPT */
#if HAVE_PTSNAME /* AIX, not Linux */
#if HAVE_PROTOTYPE_LIB_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 */
#endif /* HAVE_PROTOTYPE_LIB_ptsname */
if (tn == NULL) {
if ((tn = Ttyname(ptyfd)) == NULL) {
Warn2("ttyname(%d): %s", ptyfd, strerror(errno));
}
}
strncpy(ptyname, tn, MAXPTYNAMELEN);
ptyname[0] = '\0'; strncat(ptyname, tn, MAXPTYNAMELEN-1);
}
}
#endif /* HAVE_DEV_PTMX || HAVE_DEV_PTC */

View File

@ -1,5 +1,5 @@
/* source: xio-readline.c */
/* Copyright Gerhard Rieger 2002-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening the readline address */
@ -177,9 +177,7 @@ ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz) {
/* 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);
writt = writefull(pipe->fd, "\r", 1);
if (writt < 0) {
Warn2("write(%d, \"\\r\", 1): %s",
pipe->fd, strerror(errno));
@ -204,7 +202,7 @@ ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz) {
#endif /* _WITH_TERMIOS */
Add_history(line);
bytes = strlen(line);
strncpy(buff, line, bufsiz);
((char *)buff)[0] = '\0'; strncat(buff, line, bufsiz-1);
free(line);
if ((size_t)bytes < bufsiz) {
strcat(buff, "\n"); ++bytes;
@ -216,25 +214,26 @@ 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);
const void *pcr;
const void *plf;
size_t len;
if (bytes > pipe->para.readline.dynbytes) {
ptr = (const char *)buff + bytes - pipe->para.readline.dynbytes;
len = pipe->para.readline.dynbytes;
} else {
len = bytes;
}
if (pcr) {
pcr = memrchr(ptr, '\r', len);
plf = memrchr(ptr, '\n', len);
if (pcr != NULL || plf != NULL) {
const void *peol = Max(pcr, plf);
/* forget old prompt */
pipe->para.readline.dynend = pipe->para.readline.dynprompt;
len -= (peol+1 - ptr);
/* new prompt starts here */
ptr = (const char *)pcr+1;
ptr = (const char *)peol+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,
@ -245,7 +244,6 @@ void xioscan_readline(struct single *pipe, const void *buff, size_t bytes) {
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;

View File

@ -1,5 +1,5 @@
/* source: xio-socket.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for socket related functions, and the
@ -85,7 +85,7 @@ const struct optdesc opt_so_debug = { "so-debug", "debug", OPT_SO_DEBUG,
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_reuseaddr= { "so-reuseaddr", "reuseaddr", OPT_SO_REUSEADDR,GROUP_SOCKET, PH_PREBIND, 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 };
@ -736,7 +736,6 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
union sockaddr_union sin, *sinp;
unsigned short *port, i, N;
div_t dv;
bool problem;
/* prepare sockaddr for bind probing */
if (us) {
@ -784,7 +783,6 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
}
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) {
@ -910,15 +908,15 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
Close(xfd->fd);
return STAT_RETRYLATER;
}
} else { /* result >= 0 */
Notice1("successfully connected from local address %s",
sockaddr_info(&la.soa, themlen, infobuff, sizeof(infobuff)));
}
applyopts_fchown(xfd->fd, opts); /* OPT_USER, OPT_GROUP */
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;
}
@ -1057,7 +1055,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
if (us) {
if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s",
xfd->fd, sockaddr_info((struct sockaddr *)us, uslen, infobuff, sizeof(infobuff)),
uslen, strerror(errno));
Close(xfd->fd);
@ -1090,7 +1088,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
packet in the IP stacks input queue and forks a sub process. The sub process
then reads this packet for processing its data.
There is a problem because the parent process would find the same packet
again if it calls select()/poll() before the client process reads the
again if it calls select()/poll() before the child process reads the
packet.
To solve this problem we implement the following mechanism:
The sub process sends a SIGUSR1 when it has read the packet (or a SIGCHLD if
@ -1101,7 +1099,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
handler sets xio_hashappened if the pid matched.
*/
static pid_t xio_waitingfor; /* info from recv loop to signal handler:
indicates the pid that of the child process
indicates the pid of the child process
that should send us the USR1 signal */
static bool xio_hashappened; /* info from signal handler to loop: child
process has read ("consumed") the packet */
@ -1115,6 +1113,9 @@ void xiosigaction_hasread(int signum
int _errno;
int status = 0;
bool wassig = false;
_errno = errno;
diag_in_handler = 1;
#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO)
Debug5("xiosigaction_hasread(%d, {%d,%d,%d,"F_pid"}, )",
signum, siginfo->si_signo, siginfo->si_errno, siginfo->si_code,
@ -1123,35 +1124,39 @@ void xiosigaction_hasread(int signum
Debug1("xiosigaction_hasread(%d)", signum);
#endif
if (signum == SIGCHLD) {
_errno = errno;
do {
pid = Waitpid(-1, &status, WNOHANG);
if (pid == 0) {
Msg(wassig?E_INFO:E_WARN,
"waitpid(-1, {}, WNOHANG): no child has exited");
Info("childdied() finished");
errno = _errno;
Info("xiosigaction_hasread() finished");
Debug("xiosigaction_hasread() ->");
diag_in_handler = 0;
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;
Msg(wassig?E_INFO:E_WARN,
"waitpid(-1, {}, WNOHANG): "F_strerror);
Info("xiosigaction_hasread() finished");
Debug("xiosigaction_hasread() ->");
diag_in_handler = 0;
errno = _errno;
return;
}
wassig = true;
if (pid < 0) {
Warn2("waitpid(-1, {%d}, WNOHANG): %s", status, strerror(errno));
Info("childdied() finished");
errno = _errno;
Warn1("waitpid(-1, {%d}, WNOHANG): "F_strerror, status);
Info("xiosigaction_hasread() finished");
Debug("xiosigaction_hasread() ->");
diag_in_handler = 0;
errno = _errno;
return;
}
if (pid == xio_waitingfor) {
xio_hashappened = true;
Debug("xiosigaction_hasread() ->");
diag_in_handler = 0;
errno = _errno;
return;
}
} while (1);
@ -1163,7 +1168,12 @@ void xiosigaction_hasread(int signum
#else
xio_hashappened = true;
#endif
#if !HAVE_SIGACTION
Signal(sig, xiosigaction_hasread);
#endif /* !HAVE_SIGACTION */
Debug("xiosigaction_hasread() ->");
diag_in_handler = 0;
errno = _errno;
return;
}
@ -1187,7 +1197,6 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
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];
@ -1219,7 +1228,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
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,
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd,
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
strerror(errno));
Close(xfd->fd);
@ -1268,7 +1277,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
{
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_flags = SA_NOCLDSTOP|SA_RESTART
act.sa_flags = SA_NOCLDSTOP/*|SA_RESTART*/
#ifdef SA_SIGINFO /* not on Linux 2.0(.33) */
|SA_SIGINFO
#endif
@ -1281,6 +1290,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
#else /* Linux 2.0(.33) does not have sigaction.sa_sigaction */
act.sa_handler = xiosigaction_hasread;
#endif
sigfillset(&act.sa_mask);
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));
@ -1312,7 +1322,6 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
struct msghdr msgh = {0};
socket_init(pf, pa);
salen = sizeof(struct sockaddr);
if (drop) {
char *dummy[2];
@ -1471,7 +1480,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
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,
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd,
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
strerror(errno));
Close(xfd->fd);
@ -1604,7 +1613,7 @@ int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv) {
xiodump(CMSG_DATA(cmsg),
cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg),
valbuff, sizeof(valbuff)-1, 0);
Debug4("ancillary message: len="F_socklen", level=%d, type=%d, data=%s",
Debug4("ancillary message: len="F_cmsg_len", level=%d, type=%d, data=%s",
cmsg->cmsg_len, cmsg->cmsg_level, cmsg->cmsg_type,
valbuff);
}
@ -1652,11 +1661,11 @@ int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv) {
}
if (withenv) {
if (*envp) {
xiosetenv(envp, valp, 1);
xiosetenv(envp, valp, 1, NULL);
} else if (!strcasecmp(typp+strlen(typp)-strlen(namp), namp)) {
xiosetenv(typp, valp, 1);
xiosetenv(typp, valp, 1, NULL);
} else {
xiosetenv2(typp, namp, valp, 1);
xiosetenv2(typp, namp, valp, 1, NULL);
}
}
if (++i == num) break;
@ -1739,7 +1748,7 @@ int xiocheckpeer(xiosingle_t *xfd,
#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",
Warn1("refusing connection from %s due to wrong sourceport",
sockaddr_info((struct sockaddr *)pa, 0,
infobuff, sizeof(infobuff)));
return -1;
@ -1795,12 +1804,12 @@ int xiocheckpeer(xiosingle_t *xfd,
#if HAVE_STRUCT_CMSGHDR
/* converts the ancillary message in *cmsg into a form useable for further
processing. knows the specifics of common message types.
returns the number of resulting syntax elements is *num
returns the number of resulting syntax elements in *num
returns a sequence of \0 terminated type strings in *typbuff
returns a sequence of \0 terminated name strings in *nambuff
returns a sequence of \0 terminated value strings in *valbuff
the respective len parameters specify the available space in the buffers
returns STAT_OK
returns STAT_OK or other STAT_*
*/
static int
xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
@ -1811,6 +1820,7 @@ xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
const char *cmsgtype, *cmsgname, *cmsgenvn;
size_t msglen;
struct timeval *tv;
int rc = STAT_OK;
#if defined(CMSG_DATA)
@ -1826,7 +1836,7 @@ xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
#endif
default: /* binary data */
snprintf(typbuff, typlen, "SOCKET.%u", cmsg->cmsg_type);
strncpy(nambuff, "data", namlen);
nambuff[0] = '\0'; strncat(nambuff, "data", namlen-1);
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
return STAT_OK;
#ifdef SO_TIMESTAMP
@ -1846,7 +1856,7 @@ xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
cmsgname = "timestamp";
cmsgenvn = "TIMESTAMP";
{ time_t t = tv->tv_sec; ctime_r(&t, valbuff); }
sprintf(strchr(valbuff, '\0')-1/*del \n*/, ", %06ld usecs", tv->tv_usec);
snprintf(strchr(valbuff, '\0')-1/*del \n*/, vallen-strlen(valbuff)+1, ", %06ld usecs", (long)tv->tv_usec);
break;
#endif /* defined(SO_TIMESTAMP) */
;
@ -1855,13 +1865,13 @@ xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
with type in cmsgtype, name in cmsgname,
and value already in valbuff */
*num = 1;
if (strlen(cmsgtype) >= typlen) Fatal("buff too short");
strncpy(typbuff, cmsgtype, typlen);
if (strlen(cmsgname) >= namlen) Fatal("buff too short");
strncpy(nambuff, cmsgname, namlen);
if (strlen(cmsgenvn) >= envlen) Fatal("buff too short");
strncpy(envbuff, cmsgenvn, envlen);
return STAT_OK;
if (strlen(cmsgtype) >= typlen) rc = STAT_WARNING;
typbuff[0] = '\0'; strncat(typbuff, cmsgtype, typlen-1);
if (strlen(cmsgname) >= namlen) rc = STAT_WARNING;
nambuff[0] = '\0'; strncat(nambuff, cmsgname, namlen-1);
if (strlen(cmsgenvn) >= envlen) rc = STAT_WARNING;
envbuff[0] = '\0'; strncat(envbuff, cmsgenvn, envlen-1);
return rc;
#else /* !defined(CMSG_DATA) */
@ -1878,7 +1888,7 @@ xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
provide one in parameter ins to avoid creation of a dummy socket. ins must
be <0 if it does not specify a socket fd. */
char *xiogetifname(int ind, char *val, int ins) {
#if !HAVE_IF_INDEXTONAME
#if !HAVE_PROTOTYPE_LIB_if_indextoname
int s;
struct ifreq ifr;
@ -1912,9 +1922,9 @@ char *xiogetifname(int ind, char *val, int ins) {
if (ins < 0) Close(s);
strcpy(val, ifr.ifr_name);
return val;
#else /* HAVE_IF_INDEXTONAME */
#else /* HAVE_PROTOTYPE_LIB_if_indextoname */
return if_indextoname(ind, val);
#endif /* HAVE_IF_INDEXTONAME */
#endif /* HAVE_PROTOTYPE_LIB_if_indextoname */
}
@ -1946,7 +1956,7 @@ int xioparsenetwork(const char *rangename, int pf, struct xiorange *range) {
if ((addrname = Malloc(maskname-rangename)) == NULL) {
return STAT_NORETRY;
}
strncpy(addrname, rangename, maskname-rangename-1);
strncpy(addrname, rangename, maskname-rangename-1); /* ok */
addrname[maskname-rangename-1] = '\0';
result =
dalan(addrname, (char *)&range->netaddr.soa.sa_data, &addrlen,
@ -2043,7 +2053,7 @@ int xiosetsockaddrenv(const char *lr,
xiosetsockaddrenv_unix(idx, strchr(namebuff, '\0'), XIOSOCKADDRENVLEN-strlen(lr),
valuebuff, XIOSOCKADDRENVLEN,
&sau->un, salen, proto);
xiosetenv(namebuff, valuebuff, 1);
xiosetenv(namebuff, valuebuff, 1, NULL);
break;
#endif /* WITH_UNIX */
#if WITH_IP4
@ -2053,7 +2063,7 @@ int xiosetsockaddrenv(const char *lr,
xiosetsockaddrenv_ip4(idx, strchr(namebuff, '\0'), XIOSOCKADDRENVLEN-strlen(lr),
valuebuff, XIOSOCKADDRENVLEN,
&sau->ip4, proto);
xiosetenv(namebuff, valuebuff, 1);
xiosetenv(namebuff, valuebuff, 1, NULL);
namebuff[strlen(lr)] = '\0'; ++idx;
} while (result > 0);
break;
@ -2066,7 +2076,7 @@ int xiosetsockaddrenv(const char *lr,
xiosetsockaddrenv_ip6(idx, strchr(namebuff, '\0'), XIOSOCKADDRENVLEN-strlen(lr),
valuebuff, XIOSOCKADDRENVLEN,
&sau->ip6, proto);
xiosetenv(namebuff, valuebuff, 1);
xiosetenv(namebuff, valuebuff, 1, NULL);
namebuff[strlen(lr)] = '\0'; ++idx;
} while (result > 0);
break;
@ -2087,7 +2097,7 @@ int xiosetsockaddrenv(const char *lr,
/* these do sockets internally */
/* retrieves options so-type and so-prototype from opts, calls socketpair, and
/* retrieves options so-type and so-prototype from opts, calls socket, and
ev. generates an appropriate error message.
returns 0 on success or -1 if an error occurred. */
int

View File

@ -1,5 +1,5 @@
/* source: xio-socks.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of socks4 type */
@ -236,7 +236,7 @@ int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **soc
}
}
}
strncpy(sockhead->userid, userid, *headlen-SIZEOF_STRUCT_SOCKS4);
sockhead->userid[0] = '\0'; strncat(sockhead->userid, userid, *headlen-SIZEOF_STRUCT_SOCKS4-1);
*headlen = SIZEOF_STRUCT_SOCKS4+strlen(userid)+1;
return STAT_OK;
}
@ -279,7 +279,7 @@ int
after the user name's trailing 0 byte. */
char* insert_position = (char*) sockhead + *headlen;
strncpy(insert_position, hostname, BUFF_LEN-*headlen);
insert_position[0] = '\0'; strncat(insert_position, hostname, BUFF_LEN-*headlen-1);
((char *)sockhead)[BUFF_LEN-1] = 0;
*headlen += strlen(hostname) + 1;
if (*headlen > BUFF_LEN) {
@ -328,10 +328,7 @@ int _xioopen_socks4_connect(struct single *xfd,
}
}
#endif /* WITH_MSGLEVEL <= E_DEBUG */
do {
result = Write(xfd->fd, sockhead, headlen);
} while (result < 0 && errno == EINTR);
if (result < 0) {
if (writefull(xfd->fd, sockhead, headlen) < 0) {
Msg4(level, "write(%d, %p, "F_Zu"): %s",
xfd->fd, sockhead, headlen, strerror(errno));
if (Close(xfd->fd) < 0) {
@ -367,7 +364,7 @@ int _xioopen_socks4_connect(struct single *xfd,
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);
Debug2("received socks4 reply data (offset "F_Zd"): %s", bytes, msgbuff);
}
#endif /* WITH_MSGLEVEL <= E_DEBUG */
bytes += result;
@ -375,7 +372,7 @@ int _xioopen_socks4_connect(struct single *xfd,
Debug1("received all "F_Zd" bytes", bytes);
break;
}
Debug2("received "F_Zd" bytes, waiting for "F_Zu" more bytes",
Debug2("received %d bytes, waiting for "F_Zu" more bytes",
result, SIZEOF_STRUCT_SOCKS4-bytes);
}
if (result <= 0) { /* we had a problem while reading socks answer */

View File

@ -1,5 +1,5 @@
/* source: xio-system.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of system type */
@ -40,6 +40,10 @@ static int xioopen_system(int argc, const char *argv[], struct opt *opts,
if (status == 0) { /* child */
int numleft;
/* do not shutdown connections that belong our parent */
sock[0] = NULL;
sock[1] = NULL;
if (setopt_path(opts, &path) < 0) {
/* this could be dangerous, so let us abort this child... */
Exit(1);

View File

@ -1,5 +1,5 @@
/* source: xio-termios.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for terminal I/O options */
@ -268,10 +268,16 @@ const struct optdesc opt_veol2 = { "veol2", "eol2", OPT_VEOL2, GROUP_TER
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 };
const struct optdesc opt_termios_cfmakeraw = { "termios-cfmakeraw", "cfmakeraw", OPT_TERMIOS_CFMAKERAW, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_SPEC };
const struct optdesc opt_termios_rawer = { "termios-rawer", "rawer", OPT_TERMIOS_RAWER, GROUP_TERMIOS, PH_FD, TYPE_CONST, OFUNC_TERMIOS_SPEC };
#ifdef HAVE_TERMIOS_ISPEED
#if defined(ISPEED_OFFSET) && (ISPEED_OFFSET != -1)
#if defined(OSPEED_OFFSET) && (OSPEED_OFFSET != -1)
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
#endif
#endif /* HAVE_TERMIOS_ISPEED */

View File

@ -1,5 +1,5 @@
/* source: xio-termios.h */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_termios_h_included
@ -138,6 +138,9 @@ extern const struct optdesc opt_sane;
extern const struct optdesc opt_ispeed;
extern const struct optdesc opt_ospeed;
extern const struct optdesc opt_termios_rawer;
extern const struct optdesc opt_termios_cfmakeraw;
#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);

View File

@ -1,5 +1,5 @@
/* source: xio-tun.c */
/* Copyright Gerhard Rieger 2007-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of tun/tap type */
@ -44,7 +44,7 @@ const struct optdesc opt_iff_automedia = { "iff-automedia", "automedia", O
const struct optdesc opt_route = { "route", NULL, OPT_ROUTE, GROUP_INTERFACE, PH_INIT, TYPE_STRING, OFUNC_SPEC };
#endif
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>") };
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
@ -78,8 +78,8 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
char *ifaddr;
int result;
if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)",
if (argc > 2 || argc < 0) {
Error2("%s: wrong number of parameters (%d instead of 0 or 1)",
argv[0], argc-1);
}
@ -106,7 +106,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
memset(&ifr, 0,sizeof(ifr));
if (retropt_string(opts, OPT_TUN_NAME, &tunname) == 0) {
strncpy(ifr.ifr_name, tunname, IFNAMSIZ);
strncpy(ifr.ifr_name, tunname, IFNAMSIZ); /* ok */
free(tunname);
} else {
ifr.ifr_name[0] = '\0';
@ -146,30 +146,31 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
}
/*--------------------- setting interface address and netmask ------------*/
if ((ifaddr = strdup(argv[1])) == NULL) {
Error1("strdup(\"%s\"): out of memory", argv[1]);
return STAT_RETRYLATER;
if (argc == 2) {
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.netaddr.ip4.sin_addr;
if (Ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
Error4("ioctl(%d, SIOCSIFADDR, {\"%s\", \"%s\"}: %s",
sockfd, ifr.ifr_name, ifaddr, strerror(errno));
}
((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr =
network.netmask.ip4.sin_addr;
if (Ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
Error4("ioctl(%d, SIOCSIFNETMASK, {\"0x%08u\", \"%s\"}, %s",
sockfd, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr,
ifaddr, strerror(errno));
}
free(ifaddr);
}
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.netaddr.ip4.sin_addr;
if (Ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
Error4("ioctl(%d, SIOCSIFADDR, {\"%s\", \"%s\"}: %s",
sockfd, ifr.ifr_name, ifaddr, strerror(errno));
}
((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr =
network.netmask.ip4.sin_addr;
if (Ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
Error4("ioctl(%d, SIOCSIFNETMASK, {\"0x%08u\", \"%s\"}, %s",
sockfd, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr,
ifaddr, strerror(errno));
}
free(ifaddr);
/*--------------------- setting interface flags --------------------------*/
applyopts_single(&xfd->stream, opts, PH_FD);

View File

@ -1,5 +1,5 @@
/* source: xio-udp.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for handling UDP addresses */
@ -170,7 +170,8 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
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;
int reuseaddr = dofork;
int doreuseaddr = (dofork != 0);
char infobuff[256];
union sockaddr_union _sockname;
union sockaddr_union *la = &_sockname; /* local address */
@ -178,18 +179,23 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
if ((fd->stream.fd = xiosocket(opts, pf, socktype, ipproto, E_ERROR)) < 0) {
return STAT_RETRYLATER;
}
doreuseaddr |= (retropt_int(opts, OPT_SO_REUSEADDR, &reuseaddr) >= 0);
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));
if (doreuseaddr) {
if (Setsockopt(fd->stream.fd, opt_so_reuseaddr.major,
opt_so_reuseaddr.minor, &reuseaddr, sizeof(reuseaddr))
< 0) {
Warn6("setsockopt(%d, %d, %d, {%d}, "F_Zd"): %s",
fd->stream.fd, opt_so_reuseaddr.major,
opt_so_reuseaddr.minor, reuseaddr, sizeof(reuseaddr),
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,
Error4("bind(%d, {%s}, "F_socklen"): %s", fd->stream.fd,
sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)),
uslen, strerror(errno));
return STAT_RETRYLATER;
@ -215,7 +221,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
&them->soa, &themlen);
} while (result < 0 && errno == EINTR);
if (result < 0) {
Error5("recvfrom(%d, %p, 1, MSG_PEEK, {%s}, {"F_Zu"}): %s",
Error5("recvfrom(%d, %p, 1, MSG_PEEK, {%s}, {"F_socklen"}): %s",
fd->stream.fd, buff1,
sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)),
themlen, strerror(errno));
@ -251,7 +257,6 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
if (Close(fd->stream.fd) < 0) {
Info2("close(%d): %s", fd->stream.fd, strerror(errno));
}
Sleep(1); /*! give child a chance to consume the old packet */
continue;
}
@ -260,7 +265,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
applyopts(fd->stream.fd, opts, PH_CONNECT);
if ((result = Connect(fd->stream.fd, &them->soa, themlen)) < 0) {
Error4("connect(%d, {%s}, "F_Zd"): %s",
Error4("connect(%d, {%s}, "F_socklen"): %s",
fd->stream.fd,
sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)),
themlen, strerror(errno));
@ -457,7 +462,6 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
int pf, int socktype, int ipproto) {
union sockaddr_union us;
socklen_t uslen = sizeof(us);
bool needbind = false;
int result;
if (argc != 2) {
@ -505,7 +509,6 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
case PF_INET6: us.ip6.sin6_addr = la.ip6.sin6_addr; break;
#endif
}
needbind = true;
}
}

View File

@ -1,5 +1,5 @@
/* source: xio-unix.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of UNIX socket type */
@ -57,13 +57,13 @@ const struct addrdesc xioaddr_abstract_recv = { "abstract-recv", 1, xioop
const struct addrdesc xioaddr_abstract_client = { "abstract-client", 3, xioopen_unix_client, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 1, 0, 0 HELP(":<filename>") };
#endif /* WITH_ABSTRACT_UNIXSOCKET */
const struct optdesc xioopt_unix_tightsocklen = { "unix-tightsocklen", "tightsocklen", OPT_UNIX_TIGHTSOCKLEN, GROUP_SOCK_UNIX, PH_INIT, TYPE_BOOL, OFUNC_SPEC, 0, 0 };
const struct optdesc xioopt_unix_tightsocklen = { "unix-tightsocklen", "tightsocklen", OPT_UNIX_TIGHTSOCKLEN, GROUP_SOCK_UNIX, PH_PREBIND, TYPE_BOOL, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.un.tight), XIO_SIZEOF(para.socket.un.tight) };
/* fills the socket address struct and returns its effective length.
abstract is usually 0; != 0 generates an abstract socket address on Linux.
tight!=0 calculates the resulting length from the path length, not from the
structures length; this is more common.
structures length; this is more common (see option unix-tightsocklen)
the struct need not be initialized when calling this function.
*/
socklen_t
@ -83,7 +83,7 @@ xiosetunix(int pf,
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);
strncpy(saun->sun_path+1, path, sizeof(saun->sun_path)-1); /* ok */
if (tight) {
len = sizeof(struct sockaddr_un)-sizeof(saun->sun_path)+
MIN(pathlen+1, sizeof(saun->sun_path));
@ -101,7 +101,7 @@ xiosetunix(int pf,
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));
strncpy(saun->sun_path, path, sizeof(saun->sun_path)); /* ok */
if (tight) {
len = sizeof(struct sockaddr_un)-sizeof(saun->sun_path)+
MIN(pathlen, sizeof(saun->sun_path));
@ -124,8 +124,8 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
int protocol = 0;
struct sockaddr_un us;
socklen_t uslen;
bool tight = true;
struct opt *opts0 = NULL;
pid_t pid = Getpid();
bool opt_unlink_early = false;
bool opt_unlink_close = true;
int result;
@ -135,30 +135,26 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
argv[0], argc-1);
return STAT_NORETRY;
}
name = argv[1];
retropt_socket_pf(opts, &pf);
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
uslen = xiosetunix(pf, &us, name, abstract, tight);
xfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN;
if (!(ABSTRACT && abstract)) {
/* only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
if (opt_unlink_close) {
if ((xfd->unlink_close = strdup(name)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name);
}
xfd->opt_unlink_close = true;
}
}
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(-1, opts, PH_INIT);
applyopts_named(name, opts, PH_EARLY); /* umask! */
applyopts_offset(xfd, opts);
applyopts(-1, opts, PH_EARLY);
uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight);
if (!(ABSTRACT && abstract)) {
if (opt_unlink_early) {
if (Unlink(name) < 0) {
@ -168,21 +164,43 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
Error2("unlink(\"%s\"): %s", name, strerror(errno));
}
}
} else {
struct stat buf;
if (Lstat(name, &buf) == 0) {
Error1("\"%s\" exists", name);
return STAT_RETRYLATER;
}
}
if (opt_unlink_close) {
if ((xfd->unlink_close = strdup(name)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name);
}
xfd->opt_unlink_close = true;
}
/* 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! */
}
opts0 = copyopts(opts, GROUP_ALL);
/* this may fork() */
if ((result =
xioopen_listen(xfd, xioflags,
(struct sockaddr *)&us, uslen,
opts, opts0, pf, socktype, protocol))
!= 0)
return result;
if (!(ABSTRACT && abstract)) {
if (opt_unlink_close) {
if (pid != Getpid()) {
/* in a child process - do not unlink-close here! */
xfd->opt_unlink_close = false;
}
}
}
return 0;
}
#endif /* WITH_LISTEN */
@ -196,8 +214,7 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
int socktype = SOCK_STREAM;
int protocol = 0;
struct sockaddr_un them, us;
socklen_t themlen, uslen;
bool tight = true;
socklen_t themlen, uslen = sizeof(us);
bool needbind = false;
bool opt_unlink_close = false;
int result;
@ -207,17 +224,23 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
argv[0], argc-1);
return STAT_NORETRY;
}
name = argv[1];
xfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf);
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
themlen = xiosetunix(pf, &them, name, abstract, tight);
xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(-1, opts, PH_INIT);
applyopts_offset(xfd, opts);
applyopts(-1, opts, PH_EARLY);
themlen = xiosetunix(pf, &them, name, abstract, xfd->para.socket.un.tight);
if (!(ABSTRACT && abstract)) {
/* only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
}
if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen, 0, 0, 0)
!= STAT_NOACTION) {
if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
(abstract<<1)|xfd->para.socket.un.tight, 0, 0) == STAT_OK) {
needbind = true;
}
@ -228,10 +251,6 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
xfd->opt_unlink_close = true;
}
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT);
applyopts(-1, opts, PH_EARLY);
if ((result =
xioopen_connect(xfd,
needbind?(struct sockaddr *)&us:NULL, uslen,
@ -254,8 +273,7 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
int socktype = SOCK_DGRAM;
int protocol = 0;
union sockaddr_union us;
socklen_t uslen;
bool tight = true;
socklen_t uslen = sizeof(us);
bool needbind = false;
bool opt_unlink_close = false;
@ -264,13 +282,14 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
argv[0], argc-1);
return STAT_NORETRY;
}
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
name = argv[1];
retropt_socket_pf(opts, &pf);
xfd->salen = xiosetunix(pf, &xfd->peersa.un, name, abstract, tight);
xfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN;
applyopts_offset(xfd, opts);
xfd->salen = xiosetunix(pf, &xfd->peersa.un, name, abstract, xfd->para.socket.un.tight);
if (!(ABSTRACT && abstract)) {
/* only for non abstract because abstract do not work in file system */
@ -279,8 +298,8 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
xfd->dtype = XIODATA_RECVFROM;
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 0, 0, 0)
!= STAT_NOACTION) {
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
(abstract<<1)| xfd->para.socket.un.tight, 0, 0) == STAT_OK) {
needbind = true;
}
@ -313,7 +332,6 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
int protocol = 0;
struct sockaddr_un us;
socklen_t uslen;
bool tight = true;
bool needbind = true;
bool opt_unlink_early = false;
bool opt_unlink_close = true;
@ -323,27 +341,32 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
argv[0], argc-1);
return STAT_NORETRY;
}
name = argv[1];
retropt_socket_pf(opts, &pf);
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
uslen = xiosetunix(pf, &us, name, abstract, tight);
xfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf);
xfd->howtoend = END_NONE;
retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
1, 0, 0);
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(-1, opts, PH_INIT);
applyopts_named(name, opts, PH_EARLY); /* umask! */
applyopts_offset(xfd, opts);
if (!(ABSTRACT && abstract)) {
/* only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
if (opt_unlink_close) {
if ((xfd->unlink_close = strdup(name)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name);
}
xfd->opt_unlink_close = true;
}
}
applyopts(-1, opts, PH_EARLY);
uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight);
#if 0
if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
(abstract<<1)|xfd->para.socket.un.tight, 0, 0) == STAT_OK) {
}
#endif
if (!(ABSTRACT && abstract)) {
if (opt_unlink_early) {
if (Unlink(name) < 0) {
if (errno == ENOENT) {
@ -352,12 +375,30 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
Error2("unlink(\"%s\"): %s", name, strerror(errno));
}
}
} else {
struct stat buf;
if (Lstat(name, &buf) == 0) {
Error1("\"%s\" exists", name);
return STAT_RETRYLATER;
}
}
if (opt_unlink_close) {
if ((xfd->unlink_close = strdup(name)) == NULL) {
Error1("strdup(\"%s\"): out of memory", name);
}
xfd->opt_unlink_close = true;
}
/* 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! */
xfd->para.socket.la.soa.sa_family = pf;
xfd->dtype = XIODATA_RECVFROM_ONE;
/* this may fork */
return
_xioopen_dgram_recvfrom(xfd, xioflags,
needbind?(struct sockaddr *)&us:NULL, uslen,
@ -377,7 +418,6 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
int protocol = 0;
union sockaddr_union us;
socklen_t uslen;
bool tight = true;
bool opt_unlink_early = false;
bool opt_unlink_close = true;
int result;
@ -387,19 +427,33 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
argv[0], argc-1);
return STAT_NORETRY;
}
name = argv[1];
retropt_socket_pf(opts, &pf);
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
uslen = xiosetunix(pf, &us.un, name, abstract, tight);
#if 1 /*!!! why bind option? */
retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 1, 0, 0);
#endif
xfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(-1, opts, PH_INIT);
applyopts_named(name, opts, PH_EARLY); /* umask! */
applyopts_offset(xfd, opts);
if (!(ABSTRACT && abstract)) {
/* only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
}
applyopts(-1, opts, PH_EARLY);
uslen = xiosetunix(pf, &us.un, name, abstract, xfd->para.socket.un.tight);
#if 0
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
(abstract<<1)|xfd->para.socket.un.tight, 0, 0)
== STAT_OK) {
}
#endif
if (!(ABSTRACT && abstract)) {
if (opt_unlink_early) {
if (Unlink(name) < 0) {
if (errno == ENOENT) {
@ -408,10 +462,13 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
Error2("unlink(\"%s\"): %s", name, strerror(errno));
}
}
} else {
struct stat buf;
if (Lstat(name, &buf) == 0) {
Error1("\"%s\" exists", name);
return STAT_RETRYLATER;
}
}
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);
@ -419,6 +476,7 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
xfd->opt_unlink_close = true;
}
}
applyopts_named(name, opts, PH_EARLY); /* umask! */
xfd->para.socket.la.soa.sa_family = pf;
@ -457,28 +515,27 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups,
int socktype = 0; /* to be determined by server socket type */
int protocol = 0;
union sockaddr_union them, us;
socklen_t themlen, uslen;
bool tight = true;
socklen_t themlen, uslen = sizeof(us);
bool needbind = false;
bool opt_unlink_close = false;
struct opt *opts0;
int result;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
applyopts(-1, opts, PH_INIT);
xfd->howtoend = END_SHUTDOWN;
xfd->para.socket.un.tight = true;
retropt_socket_pf(opts, &pf);
xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
applyopts(-1, opts, PH_INIT);
applyopts_offset(xfd, opts);
applyopts(-1, opts, PH_EARLY);
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
themlen = xiosetunix(pf, &them.un, name, abstract, tight);
themlen = xiosetunix(pf, &them.un, name, abstract, xfd->para.socket.un.tight);
if (!(ABSTRACT && abstract)) {
/* only for non abstract because abstract do not work in file system */
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
}
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 0, 0, 0)
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
(abstract<<1)|xfd->para.socket.un.tight, 0, 0)
!= STAT_NOACTION) {
needbind = true;
}

19
xio.h
View File

@ -1,5 +1,5 @@
/* source: xio.h */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_h_included
@ -201,6 +201,11 @@ typedef struct single {
#endif
} ip;
#endif /* _WITH_IP4 || _WITH_IP6 */
#if WITH_UNIX
struct {
bool tight;
} un;
#endif /* WITH_UNIX */
} socket;
#endif /* _WITH_SOCKET */
struct {
@ -378,6 +383,8 @@ struct opt {
extern const char *PIPESEP;
extern xiofile_t *sock[XIO_MAXSOCK];
extern int num_child;
/* return values of xioopensingle */
#define STAT_OK 0
#define STAT_WARNING 1
@ -402,10 +409,12 @@ 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;
#define NUMUNKNOWN 4
extern pid_t diedunknown[NUMUNKNOWN]; /* child died before it is registered */
#define diedunknown1 (diedunknown[0])
#define diedunknown2 (diedunknown[1])
#define diedunknown3 (diedunknown[2])
#define diedunknown4 (diedunknown[3])
extern int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *));
extern int xiosetchilddied(void);

View File

@ -1,5 +1,5 @@
/* source: xioconfig.h */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xioconfig_h_included
@ -86,12 +86,12 @@
#endif
#if HAVE_DEV_PTMX && HAVE_GRANTPT && HAVE_UNLOCKPT && HAVE_PTSNAME
#if HAVE_DEV_PTMX && HAVE_GRANTPT && HAVE_UNLOCKPT && HAVE_PROTOTYPE_LIB_ptsname
#else
# undef HAVE_DEV_PTMX
#endif
#if HAVE_DEV_PTC /* && HAVE_GRANTPT && HAVE_UNLOCKPT && HAVE_PTSNAME */
#if HAVE_DEV_PTC /* && HAVE_GRANTPT && HAVE_UNLOCKPT && HAVE_PROTOTYPE_LIB_ptsname */
#else
# undef HAVE_DEV_PTC
#endif

View File

@ -1,11 +1,13 @@
/* source: xioexit.c */
/* Copyright Gerhard Rieger 2001-2005 */
/* Copyright Gerhard Rieger */
/* 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 "compat.h"
#include "xio.h"
#include "error.h"
/* this function closes all open xio sockets on exit, if they are still open.
@ -13,9 +15,12 @@
void xioexit(void) {
int i;
diag_in_handler = 0;
Debug("starting xioexit()");
for (i = 0; i < XIO_MAXSOCK; ++i) {
if (sock[i] != NULL && sock[i]->tag != XIO_TAG_INVALID) {
xioclose(sock[i]);
}
}
Debug("finished xioexit()");
}

View File

@ -1,5 +1,5 @@
/* source: xioinitialize.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger 2001-2011 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for the initialize function */
@ -15,7 +15,7 @@ static int xioinitialized;
xiofile_t *sock[XIO_MAXSOCK];
int (*xiohook_newchild)(void); /* xio calls this function from a new child
process */
int num_child = 0;
/* returns 0 on success or != if an error occurred */
int xioinitialize(void) {
@ -62,11 +62,15 @@ int xioinitialize(void) {
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
#if HAVE_TERMIOS_ISPEED && (ISPEED_OFFSET != -1) && (OSPEED_OFFSET != -1)
#if defined(ISPEED_OFFSET) && (ISPEED_OFFSET != -1)
#if defined(OSPEED_OFFSET) && (OSPEED_OFFSET != -1)
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
#endif
}
#endif
@ -172,7 +176,12 @@ static int xio_nokill(xiofile_t *sock) {
returns 0 on success or != 0 if an error occurred */
int xio_forked_inchild(void) {
int result = 0;
int i;
for (i=0; i<NUMUNKNOWN; ++i) {
diedunknown[i] = 0;
}
num_child = 0;
xiodroplocks();
#if WITH_FIPS
if (xio_reset_fips_mode() != 0) {
@ -213,7 +222,7 @@ pid_t xio_fork(bool subchild, int level) {
if (pid == 0) { /* child process */
pid_t cpid = Getpid();
Info1("just born: client process "F_pid, cpid);
Info1("just born: child process "F_pid, cpid);
if (!subchild) {
/* set SOCAT_PID to new value */
xiosetenvulong("PID", pid, 1);
@ -229,6 +238,7 @@ pid_t xio_fork(bool subchild, int level) {
return 0;
}
num_child++;
/* parent process */
Notice1("forked off child process "F_pid, pid);
/* gdb recommends to have env controlled sleep after fork */

View File

@ -1,5 +1,5 @@
/* source: xiolockfile.c */
/* Copyright Gerhard Rieger 2005-2006 */
/* Copyright Gerhard Rieger 2005-2011 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains socats explicit locking mechanisms */
@ -52,7 +52,10 @@ int xiogetlock(const char *lockfile) {
pid = Getpid();
bytes = sprintf(pidbuf, F_pid, pid);
Write(fd, pidbuf, bytes);
if (writefull(fd, pidbuf, bytes) < 0) {
Error4("write(%d, %p, "F_Zu"): %s", fd, pidbuf, bytes, strerror(errno));
return -1;
}
Close(fd);
/* Chmod(lockfile, 0600); */

160
xioopts.c
View File

@ -1,5 +1,5 @@
/* source: xioopts.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for address options handling */
@ -277,6 +277,7 @@ const struct optname optionnames[] = {
IF_OPENSSL("capath", &opt_openssl_capath)
IF_OPENSSL("cert", &opt_openssl_certificate)
IF_OPENSSL("certificate", &opt_openssl_certificate)
IF_TERMIOS("cfmakeraw", &opt_termios_cfmakeraw)
IF_ANY ("chroot", &opt_chroot)
IF_ANY ("chroot-early", &opt_chroot_early)
/*IF_TERMIOS("cibaud", &opt_cibaud)*/
@ -290,9 +291,14 @@ const struct optname optionnames[] = {
IF_TERMIOS("clocal", &opt_clocal)
IF_ANY ("cloexec", &opt_cloexec)
IF_ANY ("close", &opt_end_close)
IF_OPENSSL("cn", &opt_openssl_commonname)
IF_OPENSSL("commonname", &opt_openssl_commonname)
#if WITH_EXT2 && defined(EXT2_COMPR_FL)
IF_ANY ("compr", &opt_ext2_compr)
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
IF_OPENSSL("compress", &opt_openssl_compress)
#endif
#ifdef TCP_CONN_ABORT_THRESHOLD /* HP_UX */
IF_TCP ("conn-abort-threshold", &opt_tcp_conn_abort_threshold)
#endif
@ -388,7 +394,9 @@ const struct optname optionnames[] = {
IF_SOCKET ("dontlinger", &opt_so_dontlinger)
#endif
IF_SOCKET ("dontroute", &opt_so_dontroute)
#ifdef IPV6_DSTOPTS
IF_IP6 ("dstopts", &opt_ipv6_dstopts)
#endif
#ifdef VDSUSP /* HP-UX */
IF_TERMIOS("dsusp", &opt_vdsusp)
#endif
@ -545,8 +553,12 @@ const struct optname optionnames[] = {
#endif
IF_READLINE("history", &opt_history_file)
IF_READLINE("history-file", &opt_history_file)
#ifdef IPV6_HOPLIMIT
IF_IP6 ("hoplimit", &opt_ipv6_hoplimit)
#endif
#ifdef IPV6_HOPOPTS
IF_IP6 ("hopopts", &opt_ipv6_hopopts)
#endif
#if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
IF_IPAPP ("hosts-allow", &opt_tcpwrap_hosts_allow_table)
#endif
@ -717,18 +729,30 @@ const struct optname optionnames[] = {
#endif
IF_IP ("iptos", &opt_ip_tos)
IF_IP ("ipttl", &opt_ip_ttl)
#ifdef IPV6_JOIN_GROUP
IF_IP6 ("ipv6-add-membership", &opt_ipv6_join_group)
#endif
#ifdef IPV6_AUTHHDR
IF_IP6 ("ipv6-authhdr", &opt_ipv6_authhdr)
#endif
#ifdef IPV6_DSTOPTS
IF_IP6 ("ipv6-dstopts", &opt_ipv6_dstopts)
#endif
#ifdef IPV4_FLOWINFO
IF_IP6 ("ipv6-flowinfo", &opt_ipv6_flowinfo)
#endif
#ifdef IPV6_HOPLIMIT
IF_IP6 ("ipv6-hoplimit", &opt_ipv6_hoplimit)
#endif
#ifdef IPV6_HOPOPTS
IF_IP6 ("ipv6-hopopts", &opt_ipv6_hopopts)
#endif
#ifdef IPV6_JOIN_GROUP
IF_IP6 ("ipv6-join-group", &opt_ipv6_join_group)
#endif
#ifdef IPV6_PKTINFO
IF_IP6 ("ipv6-pktinfo", &opt_ipv6_pktinfo)
#endif
#ifdef IPV6_RECVDSTOPTS
IF_IP6 ("ipv6-recvdstopts", &opt_ipv6_recvdstopts)
#endif
@ -753,7 +777,9 @@ const struct optname optionnames[] = {
#ifdef IPV6_RECVTCLASS
IF_IP6 ("ipv6-recvtclass", &opt_ipv6_recvtclass)
#endif
#ifdef IPV6_RTHDR
IF_IP6 ("ipv6-rthdr", &opt_ipv6_rthdr)
#endif
#ifdef IPV6_TCLASS
IF_IP6 ("ipv6-tclass", &opt_ipv6_tclass)
#endif
@ -763,7 +789,7 @@ const struct optname optionnames[] = {
IF_IP6 ("ipv6only", &opt_ipv6_v6only)
#endif
IF_TERMIOS("isig", &opt_isig)
#ifdef HAVE_TERMIOS_ISPEED
#if defined(HAVE_TERMIOS_ISPEED) && defined(ISPEED_OFFSET) && (ISPEED_OFFSET != -1)
IF_TERMIOS("ispeed", &opt_ispeed)
#endif
IF_TERMIOS("istrip", &opt_istrip)
@ -773,7 +799,9 @@ const struct optname optionnames[] = {
IF_TERMIOS("ixany", &opt_ixany)
IF_TERMIOS("ixoff", &opt_ixoff)
IF_TERMIOS("ixon", &opt_ixon)
#ifdef IPV6_JOIN_GROUP
IF_IP6 ("join-group", &opt_ipv6_join_group)
#endif
#if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
IF_ANY ("journal", &opt_ext2_journal_data)
IF_ANY ("journal-data", &opt_ext2_journal_data)
@ -838,6 +866,8 @@ const struct optname optionnames[] = {
IF_ANY ("lseek64-set", &opt_lseek64_set)
#endif
IF_TUN ("master", &opt_iff_master)
IF_LISTEN ("max-children", &opt_max_children)
IF_LISTEN ("maxchildren", &opt_max_children)
#ifdef TCP_MAXSEG
IF_TCP ("maxseg", &opt_tcp_maxseg)
IF_TCP ("maxseg-late", &opt_tcp_maxseg_late)
@ -1067,6 +1097,10 @@ const struct optname optionnames[] = {
IF_OPENSSL("openssl-capath", &opt_openssl_capath)
IF_OPENSSL("openssl-certificate", &opt_openssl_certificate)
IF_OPENSSL("openssl-cipherlist", &opt_openssl_cipherlist)
IF_OPENSSL("openssl-commonname", &opt_openssl_commonname)
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
IF_OPENSSL("openssl-compress", &opt_openssl_compress)
#endif
IF_OPENSSL("openssl-dhparam", &opt_openssl_dhparam)
IF_OPENSSL("openssl-egd", &opt_openssl_egd)
#if WITH_FIPS
@ -1075,9 +1109,10 @@ const struct optname optionnames[] = {
IF_OPENSSL("openssl-key", &opt_openssl_key)
IF_OPENSSL("openssl-method", &opt_openssl_method)
IF_OPENSSL("openssl-pseudo", &opt_openssl_pseudo)
IF_OPENSSL("openssl-snihost", &opt_openssl_snihost)
IF_OPENSSL("openssl-verify", &opt_openssl_verify)
IF_TERMIOS("opost", &opt_opost)
#ifdef HAVE_TERMIOS_ISPEED
#if defined(HAVE_TERMIOS_ISPEED) && defined(OSPEED_OFFSET) && (OSPEED_OFFSET != -1)
IF_TERMIOS("ospeed", &opt_ospeed)
#endif
IF_ANY ("owner", &opt_user)
@ -1163,6 +1198,7 @@ const struct optname optionnames[] = {
IF_TERMIOS("quit", &opt_vquit)
IF_RANGE ("range", &opt_range)
IF_TERMIOS("raw", &opt_raw)
IF_TERMIOS("rawer", &opt_termios_rawer)
IF_SOCKET ("rcvbuf", &opt_so_rcvbuf)
IF_SOCKET ("rcvbuf-late", &opt_so_rcvbuf_late)
#ifdef SO_RCVLOWAT
@ -1250,7 +1286,9 @@ const struct optname optionnames[] = {
#ifdef O_RSYNC
IF_OPEN ("rsync", &opt_o_rsync)
#endif
#ifdef IPV6_RTHDR
IF_IP6 ("rthdr", &opt_ipv6_rthdr)
#endif
IF_TUN ("running", &opt_iff_running)
#ifdef TCP_SACK_DISABLE
IF_TCP ("sack-disable", &opt_tcp_sack_disable)
@ -1340,6 +1378,7 @@ const struct optname optionnames[] = {
#ifdef SO_SNDTIMEO
IF_SOCKET ("sndtimeo", &opt_so_sndtimeo)
#endif
IF_OPENSSL("snihost", &opt_openssl_snihost)
#ifdef SO_ACCEPTCONN /* AIX433 */
IF_SOCKET ("so-acceptconn", &opt_so_acceptconn)
#endif /* SO_ACCEPTCONN */
@ -1458,10 +1497,14 @@ const struct optname optionnames[] = {
IF_ANY ("streams-i-push", &opt_streams_i_push)
#endif
IF_ANY ("su", &opt_substuser)
#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
IF_ANY ("su-d", &opt_substuser_delayed)
#endif
IF_ANY ("su-e", &opt_substuser_early)
IF_ANY ("substuser", &opt_substuser)
#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
IF_ANY ("substuser-delayed", &opt_substuser_delayed)
#endif
IF_ANY ("substuser-early", &opt_substuser_early)
IF_TERMIOS("susp", &opt_vsusp)
#ifdef VSWTC
@ -1584,6 +1627,8 @@ const struct optname optionnames[] = {
IF_IPAPP ("tcpwrapper", &opt_tcpwrappers)
IF_IPAPP ("tcpwrappers", &opt_tcpwrappers)
#endif
IF_TERMIOS("termios-cfmakeraw", &opt_termios_cfmakeraw)
IF_TERMIOS("termios-rawer", &opt_termios_rawer)
#ifdef O_TEXT
IF_ANY ("text", &opt_o_text)
#endif
@ -1790,7 +1835,11 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
parsres =
nestlex(a, &tokp, &len, endkey, hquotes, squotes, nests,
true, true, false);
if (parsres != 0) {
if (parsres < 0) {
Error1("option too long: \"%s\"", *a);
return -1;
} else if (parsres > 0) {
Error1("syntax error in \"%s\"", *a);
return -1;
}
if (tokp == token) {
@ -1825,7 +1874,11 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
parsres =
nestlex(a, &tokp, &len, endval, hquotes, squotes, nests,
true, true, false);
if (parsres != 0) {
if (parsres < 0) {
Error1("option too long: \"%s\"", *a);
return -1;
} else if (parsres > 0) {
Error1("syntax error in \"%s\"", *a);
return -1;
}
*tokp = '\0';
@ -2136,6 +2189,7 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
#endif /* HAVE_STRUCT_LINGER */
case TYPE_INT_INT:
case TYPE_INT_INTP:
if (!assign) {
Error1("option \"%s\": values required", a0);
continue;
@ -2302,9 +2356,17 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
/* parse first IP address, expect ':' */
tokp = token;
/*! result= */
nestlex((const char **)&tokp, &buffp, &bufspc,
ends, NULL, NULL, nests,
true, false, false);
parsres =
nestlex((const char **)&tokp, &buffp, &bufspc,
ends, NULL, NULL, nests,
true, false, false);
if (parsres < 0) {
Error1("option too long: \"%s\"", *a);
return -1;
} else if (parsres > 0) {
Error1("syntax error in \"%s\"", *a);
return -1;
}
if (*tokp != ':') {
Error1("syntax in option %s: missing ':'", token);
}
@ -2315,15 +2377,23 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
/* parse second IP address, expect ':' or '\0'' */
buffp = buff;
/*! result= */
nestlex((const char **)&tokp, &buffp, &bufspc,
ends, NULL, NULL, nests,
true, false, false);
parsres =
nestlex((const char **)&tokp, &buffp, &bufspc,
ends, NULL, NULL, nests,
true, false, false);
if (parsres < 0) {
Error1("option too long: \"%s\"", *a);
return -1;
} else if (parsres > 0) {
Error1("syntax error in \"%s\"", *a);
return -1;
}
*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);
strncpy((*opts)[i].value.u_ip_mreq.ifindex, tokp, IF_NAMESIZE); /* ok */
Info4("setting option \"%s\" to {\"%s\",\"%s\",\"%s\"}",
ent->desc->defname,
(*opts)[i].value.u_ip_mreq.multiaddr,
@ -2355,9 +2425,17 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1;
tokp = token;
parsres =
nestlex((const char **)&tokp, &buffp, &bufspc,
ends, NULL, NULL, nests,
true, false, false);
if (parsres < 0) {
Error1("option too long: \"%s\"", *a);
return -1;
} else if (parsres > 0) {
Error1("syntax error in \"%s\"", *a);
return -1;
}
if (*tokp != '\0') {
Error1("trailing data in option \"%s\"", token);
}
@ -2779,7 +2857,7 @@ int retropt_string(struct opt *opts, int optcode, char **result) {
#if _WITH_SOCKET
/* looks for an bind option and, if found, overwrites the complete contents of
/* looks for a 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,
@ -2792,15 +2870,19 @@ int retropt_bind(struct opt *opts,
struct sockaddr *sa,
socklen_t *salen,
int feats, /* TCP etc: 1..address allowed,
3..address and port allowed */
3..address and port allowed
UNIX (or'd): 1..tight
2..abstract
*/
unsigned long res_opts0, unsigned long res_opts1) {
const char portsep[] = ":";
const char *ends[] = { portsep, NULL };
const char *nests[] = { "[", "]", NULL };
bool addrallowed, portallowed;
bool portallowed;
char *bindname, *bindp;
char hostname[512], *hostp = hostname, *portp = NULL;
size_t hostlen = sizeof(hostname)-1;
int parsres;
int result;
if (retropt_string(opts, OPT_BIND, &bindname) < 0) {
@ -2833,10 +2915,17 @@ int retropt_bind(struct opt *opts,
#if WITH_IP6
case AF_INET6:
#endif /*WITH_IP6 */
addrallowed = true;
portallowed = (feats>=2);
nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
true, false, false);
parsres =
nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
true, false, false);
if (parsres < 0) {
Error1("option too long: \"%s\"", bindp);
return STAT_NORETRY;
} else if (parsres > 0) {
Error1("syntax error in \"%s\"", bindp);
return STAT_NORETRY;
}
*hostp++ = '\0';
if (!strncmp(bindp, portsep, strlen(portsep))) {
if (!portallowed) {
@ -2861,9 +2950,10 @@ int retropt_bind(struct opt *opts,
#if WITH_UNIX
case AF_UNIX:
{
bool tight = false;
bool abstract = (feats&2);
bool tight = (feats&1);
struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
*salen = xiosetunix(af, s_un, bindname, false, tight);
*salen = xiosetunix(af, s_un, bindname, abstract, tight);
}
break;
#endif /* WITH_UNIX */
@ -3016,7 +3106,7 @@ int applyopts(int fd, struct opt *opts, enum e_phase phase) {
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",
Error6("setsockopt(%d, %d, %d, %p, "F_Zu"): %s",
fd, opt->desc->major, opt->desc->minor,
opt->value.u_bin.b_data, opt->value.u_bin.b_len,
strerror(errno));
@ -3148,7 +3238,7 @@ int applyopts(int fd, struct opt *opts, enum e_phase phase) {
if (Getsockopt(fd, opt->desc->major, opt->desc->minor,
data, &oldlen)
< 0) {
Error6("getsockopt(%d, %d, %d, %p, {"F_Zu"}): %s",
Error6("getsockopt(%d, %d, %d, %p, {"F_socklen"}): %s",
fd, opt->desc->major, opt->desc->minor, data, oldlen,
strerror(errno));
opt->desc = ODESC_ERROR; ++opt; continue;
@ -3329,6 +3419,7 @@ int applyopts(int fd, struct opt *opts, enum e_phase phase) {
#endif
}
break;
#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
case OPT_SUBSTUSER_DELAYED:
{
struct passwd *pwd;
@ -3362,6 +3453,7 @@ int applyopts(int fd, struct opt *opts, enum e_phase phase) {
delayeduser = true;
}
break;
#endif
case OPT_CHROOT_EARLY:
case OPT_CHROOT:
if (Chroot(opt->value.u_string) < 0) {
@ -3561,6 +3653,14 @@ int applyopts(int fd, struct opt *opts, enum e_phase phase) {
termarg.c_cc[VMIN] = 1;
termarg.c_cc[VTIME] = 0;
break;
case OPT_TERMIOS_RAWER:
termarg.c_iflag = 0;
termarg.c_oflag = 0;
termarg.c_lflag = 0;
termarg.c_cflag = (CS8);
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
@ -3648,6 +3748,19 @@ int applyopts(int fd, struct opt *opts, enum e_phase phase) {
termarg.c_lflag |= (ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE);
/*! "sets characters to their default values... - which? */
break;
case OPT_TERMIOS_CFMAKERAW:
#if HAVE_CFMAKERAW
cfmakeraw(&termarg);
#else
/* these setting follow the Linux documenation of cfmakeraw */
termarg.c_iflag &=
~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
termarg.c_oflag &= ~(OPOST);
termarg.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
termarg.c_cflag &= ~(CSIZE|PARENB);
termarg.c_cflag |= (CS8);
#endif
break;
default:
Error("TERMIOS option not handled - internal error?");
}
@ -4140,9 +4253,8 @@ int _xio_openlate(struct single *fd, struct opt *opts) {
int dropopts(struct opt *opts, unsigned int phase) {
struct opt *opt;
/*!*/
if (phase == PH_ALL) {
free(opts);
opts[0].desc = ODESC_END;
return 0;
}
opt = opts; while (opt && opt->desc != ODESC_END) {

View File

@ -1,5 +1,5 @@
/* source: xioopts.h */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xioopts_h_included
@ -432,6 +432,7 @@ enum e_optcode {
OPT_IXON, /* termios.c_iflag */
OPT_LOCKFILE,
OPT_LOWPORT,
OPT_MAX_CHILDREN,
#ifdef NLDLY
# ifdef NL0
OPT_NL0, /* termios.c_oflag */
@ -472,12 +473,17 @@ enum e_optcode {
OPT_OPENSSL_CAPATH,
OPT_OPENSSL_CERTIFICATE,
OPT_OPENSSL_CIPHERLIST,
OPT_OPENSSL_COMMONNAME,
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
OPT_OPENSSL_COMPRESS,
#endif
OPT_OPENSSL_DHPARAM,
OPT_OPENSSL_EGD,
OPT_OPENSSL_FIPS,
OPT_OPENSSL_KEY,
OPT_OPENSSL_METHOD,
OPT_OPENSSL_PSEUDO,
OPT_OPENSSL_SNIHOST,
OPT_OPENSSL_VERIFY,
OPT_OPOST, /* termios.c_oflag */
OPT_OSPEED, /* termios.c_ospeed */
@ -703,7 +709,9 @@ enum e_optcode {
# undef ENABLE_OPTCODE
OPT_SUBSTUSER_EARLY,
OPT_SUBSTUSER,
#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
OPT_SUBSTUSER_DELAYED,
#endif
OPT_SYMBOLIC_LINK, /* with pty */
#ifdef TABDLY
# ifdef TAB0
@ -778,6 +786,8 @@ enum e_optcode {
#ifdef TCP_WINDOW_CLAMP
OPT_TCP_WINDOW_CLAMP, /* Linux 2.4.0 */
#endif
OPT_TERMIOS_CFMAKERAW, /* termios.cfmakeraw() */
OPT_TERMIOS_RAWER,
OPT_TIOCSCTTY,
OPT_TOSTOP, /* termios.c_lflag */
OPT_TUN_DEVICE, /* tun: /dev/net/tun ... */

View File

@ -1,5 +1,5 @@
/* source: xioparam.c */
/* Copyright Gerhard Rieger 2001-2006 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for xio options handling */
@ -54,7 +54,8 @@ int xiosetopt(char what, const char *arg) {
int xioinqopt(char what, char *arg, size_t n) {
switch (what) {
case 's': return xioopts.strictopts;
case 'p': strncpy(arg, xioopts.pipesep, n);
case 'p':
arg[0] = '\0'; strncat(arg, xioopts.pipesep, n-1);
return 0;
case 'o': return xioopts.ip4portsep;
case 'l': return xioopts.logopt;

View File

@ -1,5 +1,5 @@
/* source: xioshutdown.c */
/* Copyright Gerhard Rieger 2001-2009 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this is the source of the extended shutdown function */
@ -11,8 +11,13 @@
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");
int _errno;
_errno = errno;
diag_in_handler = 1;
Notice("SIGALRM while waiting for wo child process to die, killing it now");
Kill(socat_kill_pid, SIGTERM);
diag_in_handler = 0;
errno = _errno;
}
int xioshutdown(xiofile_t *sock, int how) {
@ -114,7 +119,13 @@ int xioshutdown(xiofile_t *sock, int how) {
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);
{
struct sigaction act;
sigfillset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = signal_kill_pid;
Sigaction(SIGALRM, &act, NULL);
}
socat_kill_pid = sock->stream.para.exec.pid;
#if HAVE_SETITIMER
/*! with next feature release, we get usec resolution and an option */
@ -127,7 +138,8 @@ int xioshutdown(xiofile_t *sock, int how) {
}
Alarm(0);
}
} else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_RECVFROM) {
} else if ((sock->stream.dtype & XIODATA_MASK) ==
(XIODATA_RECVFROM & XIODATA_MASK)) {
if (how >= 1) {
if (Close(sock->stream.fd) < 0) {
Info2("close(%d): %s",

View File

@ -1,5 +1,5 @@
/* source: xiosigchld.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this is the source of the extended child signal handler */
@ -10,10 +10,8 @@
/*!! 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;
pid_t diedunknown[NUMUNKNOWN]; /* children that died before they were registered */
size_t nextunknown;
/* register for a xio filedescriptor a callback (handler).
@ -29,6 +27,7 @@ int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *)) {
}
/* exec'd child has died, perform appropriate changes to descriptor */
/* is async-signal-safe */
static int sigchld_stream(struct single *file) {
/*!! call back to application */
file->para.exec.pid = 0;
@ -49,7 +48,7 @@ static int xio_checkchild(xiofile_t *socket, int socknum, pid_t deadchild) {
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);
sigchld_stream(&socket->stream); /* is async-signal-safe */
return 1;
}
} else {
@ -80,8 +79,8 @@ void childdied(int signum) {
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 */
diag_in_handler = 1;
Notice1("childdied(): handling signal %d", signum);
Info1("childdied(signum=%d)", signum);
do {
pid = Waitpid(-1, &status, WNOHANG);
@ -89,23 +88,27 @@ void childdied(int signum) {
Msg(wassig?E_INFO:E_WARN,
"waitpid(-1, {}, WNOHANG): no child has exited");
Info("childdied() finished");
diag_in_handler = 0;
errno = _errno;
return;
} else if (pid < 0 && errno == ECHILD) {
Msg1(wassig?E_INFO:E_WARN,
"waitpid(-1, {}, WNOHANG): %s", strerror(errno));
Msg(wassig?E_INFO:E_WARN,
"waitpid(-1, {}, WNOHANG): "F_strerror);
Info("childdied() finished");
diag_in_handler = 0;
errno = _errno;
return;
}
wassig = true;
if (pid < 0) {
Warn2("waitpid(-1, {%d}, WNOHANG): %s", status, strerror(errno));
Warn1("waitpid(-1, {%d}, WNOHANG): "F_strerror, status);
Info("childdied() finished");
diag_in_handler = 0;
errno = _errno;
return;
}
/*! indent */
if (num_child) num_child--;
/* check if it was a registered child process */
i = 0;
while (i < XIO_MAXSOCK) {
@ -114,19 +117,12 @@ void childdied(int signum) {
}
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 (nextunknown == NUMUNKNOWN) {
nextunknown = 0;
}
diedunknown[nextunknown++] = pid;
Debug1("saving pid in diedunknown"F_Zu,
nextunknown/*sic, for compatibility*/);
}
if (WIFEXITED(status)) {
@ -150,11 +146,12 @@ void childdied(int signum) {
#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));
Warn("signal(SIGCHLD, childdied): "F_strerror);
}
#endif /* !HAVE_SIGACTION */
} while (1);
Info("childdied() finished");
diag_in_handler = 0;
errno = _errno;
}
@ -163,12 +160,13 @@ int xiosetchilddied(void) {
#if HAVE_SIGACTION
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_flags = SA_NOCLDSTOP|SA_RESTART
act.sa_flags = SA_NOCLDSTOP/*|SA_RESTART*/
#ifdef SA_NOMASK
|SA_NOMASK
#endif
;
act.sa_handler = childdied;
sigfillset(&act.sa_mask);
if (Sigaction(SIGCHLD, &act, NULL) < 0) {
/*! man does not say that errno is defined */
Warn2("sigaction(SIGCHLD, %p, NULL): %s", childdied, strerror(errno));

View File

@ -1,5 +1,5 @@
/* source: xiosignal.c */
/* Copyright Gerhard Rieger 2001-2003 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains code for handling signals (except SIGCHLD) */
@ -35,6 +35,7 @@ static struct socat_sig_desc socat_sigquit;
#endif
/* is async-signal-safe */
static struct socat_sig_desc *socat_get_sig_desc(int signum) {
struct socat_sig_desc *sigdesc;
switch (signum) {
@ -46,21 +47,26 @@ static struct socat_sig_desc *socat_get_sig_desc(int signum) {
return sigdesc;
}
/* a signal handler that eventually passes the signal to sub processes */
/* a signal handler that possibly passes the signal to sub processes */
void socatsignalpass(int sig) {
int i;
struct socat_sig_desc *sigdesc;
int _errno;
Debug1("socatsignalpass(%d)", sig);
if ((sigdesc = socat_get_sig_desc(sig)) == NULL) {
_errno = errno;
diag_in_handler = 1;
Notice1("socatsignalpass(%d)", sig);
if ((sigdesc = socat_get_sig_desc(sig)) == NULL) { /* is async-signal-safe */
diag_in_handler = 0;
errno = _errno;
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));
Warn2("kill("F_pid", %d): %m",
sigdesc->sig_pids[i], sig);
}
}
}
@ -68,6 +74,8 @@ void socatsignalpass(int sig) {
Signal(sig, socatsignalpass);
#endif /* !HAVE_SIGACTION */
Debug("socatsignalpass() ->");
diag_in_handler = 0;
errno = _errno;
}
@ -91,8 +99,9 @@ int xio_opt_signal(pid_t pid, int signum) {
#if HAVE_SIGACTION
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_flags = SA_RESTART;
act.sa_flags = 0/*|SA_RESTART*/;
act.sa_handler = socatsignalpass;
sigfillset(&act.sa_mask);
if (Sigaction(signum, &act, NULL) < 0) {
/*! man does not say that errno is defined */
Warn3("sigaction(%d, %p, NULL): %s", signum, &act, strerror(errno));

View File

@ -1,5 +1,5 @@
/* source: xiowrite.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger 2001-2011 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this is the source of the extended write function */
@ -49,9 +49,7 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
switch (pipe->dtype & XIODATA_WRITEMASK) {
case XIOWRITE_STREAM:
do {
writt = Write(pipe->fd, buff, bytes);
} while (writt < 0 && errno == EINTR);
writt = writefull(pipe->fd, buff, bytes);
if (writt < 0) {
_errno = errno;
switch (_errno) {
@ -70,10 +68,6 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
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
@ -120,9 +114,7 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
#endif /* _WITH_SOCKET */
case XIOWRITE_PIPE:
do {
writt = Write(pipe->para.bipipe.fdout, buff, bytes);
} while (writt < 0 && errno == EINTR);
writt = Write(pipe->para.bipipe.fdout, buff, bytes);
_errno = errno;
if (writt < 0) {
Error4("write(%d, %p, "F_Zu"): %s",
@ -130,16 +122,10 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
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);
writt = Write(pipe->para.exec.fdout, buff, bytes);
_errno = errno;
if (writt < 0) {
Error4("write(%d, %p, "F_Zu"): %s",
@ -147,10 +133,6 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
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