Compare commits
102 Commits
tag-1.7.1.
...
master
Author | SHA1 | Date |
---|---|---|
Travis Burtrum | 268432bf42 | |
Gerhard Rieger | 8fda559e8d | |
Gerhard Rieger | b6541b4de7 | |
Gerhard Rieger | 053c4565b3 | |
Gerhard Rieger | c65a1c9791 | |
Gerhard Rieger | f0c3b1f387 | |
Gerhard Rieger | 81c4892599 | |
Gerhard Rieger | 3f63c9889f | |
Gerhard Rieger | f0abfc19fd | |
Gerhard Rieger | f749f5c3e4 | |
Gerhard Rieger | 59658d8267 | |
Gerhard Rieger | 05c0b2873e | |
Gerhard Rieger | fb0246084a | |
Gerhard Rieger | 4228399da0 | |
Gerhard Rieger | 3ee5ac5275 | |
Gerhard Rieger | 6f6d7ccb86 | |
Gerhard Rieger | 522bb45479 | |
Gerhard Rieger | 8c8f817780 | |
Gerhard Rieger | 2b99929bfc | |
Gerhard Rieger | ca872c9a9f | |
Gerhard Rieger | 281d1bd651 | |
Gerhard Rieger | d430147bc6 | |
Gerhard Rieger | 899bc6845d | |
Gerhard Rieger | d4c44ff649 | |
Gerhard Rieger | 9e863458c6 | |
Gerhard Rieger | 2f40a439cb | |
Gerhard Rieger | 05afec429d | |
Gerhard Rieger | cf3f6403bc | |
Gerhard Rieger | 59a11f2efb | |
Gerhard Rieger | ad524a56b7 | |
Gerhard Rieger | 0ab324b173 | |
Gerhard Rieger | 466cb7921c | |
Gerhard Rieger | 0219d6ac27 | |
Gerhard Rieger | 98028900e0 | |
Gerhard Rieger | 2af0495cc6 | |
Gerhard Rieger | e4c6f3d934 | |
Gerhard Rieger | 80c7fa0bca | |
Gerhard Rieger | 93cfe88290 | |
Gerhard Rieger | 8371aa3dc0 | |
Gerhard Rieger | 9585312903 | |
Gerhard Rieger | bc38f04072 | |
Gerhard Rieger | 133c180fb1 | |
Gerhard Rieger | fbb521e45e | |
Gerhard Rieger | cf39583b25 | |
Gerhard Rieger | 52e8a5ec2b | |
Gerhard Rieger | ab74be65e5 | |
Gerhard Rieger | a793c8047e | |
Gerhard Rieger | dfdeaa4836 | |
Gerhard Rieger | 04ad6d5275 | |
Gerhard Rieger | 2e17542be7 | |
Gerhard Rieger | 520e84aba7 | |
Gerhard Rieger | 82231ad799 | |
Gerhard Rieger | a214cbca6f | |
Gerhard Rieger | bf17d38dab | |
Gerhard Rieger | 0fad8877fd | |
Gerhard Rieger | 257834e501 | |
Gerhard Rieger | 1898116eca | |
Gerhard Rieger | 5e63eff878 | |
Gerhard Rieger | b732d00d30 | |
Gerhard Rieger | 91b00e8c44 | |
Gerhard Rieger | 4d013105ea | |
Gerhard Rieger | b6deb56a14 | |
Gerhard Rieger | 0978ada95e | |
Gerhard Rieger | 77a9c7ae10 | |
Gerhard Rieger | 7a348bdfd5 | |
Gerhard Rieger | 022f0a46e6 | |
Gerhard Rieger | 464d23a34f | |
Gerhard Rieger | 42ef3f4645 | |
Gerhard Rieger | 97db9bce50 | |
Gerhard Rieger | 4c9898446d | |
Gerhard Rieger | 76291f6a67 | |
Gerhard Rieger | abb25c1427 | |
Gerhard Rieger | eccce7542e | |
Gerhard Rieger | 1c302dc23c | |
Gerhard Rieger | 3ef7b3e366 | |
Gerhard Rieger | 490a01d245 | |
Gerhard Rieger | 7e3386f228 | |
Gerhard Rieger | 9e0c4e1df5 | |
Gerhard Rieger | 02f3b29ab6 | |
Gerhard Rieger | 6cefd1941e | |
Gerhard Rieger | a593b09df6 | |
Gerhard Rieger | b579f27765 | |
Gerhard Rieger | d2fab02571 | |
Gerhard Rieger | 98abed1abd | |
Gerhard Rieger | b4b7ffc732 | |
Gerhard Rieger | baa16a52a6 | |
Gerhard Rieger | 0cf1e34018 | |
Gerhard Rieger | 7a3ed71270 | |
Gerhard Rieger | 26801266f2 | |
Gerhard Rieger | 0b472d59d2 | |
Gerhard Rieger | 49c0505298 | |
Gerhard Rieger | 976d6f0b75 | |
Gerhard Rieger | 6a8f6c0734 | |
Gerhard Rieger | 3881c794a7 | |
Gerhard Rieger | b8d16ecd51 | |
Gerhard Rieger | aae035c5b9 | |
Gerhard Rieger | 06179edeb6 | |
Gerhard Rieger | 290b62c817 | |
Gerhard Rieger | e0d548df71 | |
Gerhard Rieger | 2e385902c0 | |
Gerhard Rieger | cb913fbc0c | |
Gerhard Rieger | 4c3d1ca49d |
395
CHANGES
395
CHANGES
|
@ -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
42
COPYING
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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) */
|
21
DEVELOPMENT
21
DEVELOPMENT
|
@ -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
|
||||
|
|
23
Makefile.in
23
Makefile.in
|
@ -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
13
README
|
@ -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
|
||||
|
|
161
compat.h
161
compat.h
|
@ -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) */
|
||||
|
|
113
config.h.in
113
config.h.in
|
@ -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) */
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
configure.in
|
579
configure.in
579
configure.in
|
@ -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)
|
||||
|
|
6
dalan.c
6
dalan.c
|
@ -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"
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
155
doc/socat.yo
155
doc/socat.yo
|
@ -10,7 +10,7 @@ def(Filan)(0)(bf(Filan))
|
|||
def(procan)(0)(bf(procan))
|
||||
def(Procan)(0)(bf(Procan))
|
||||
|
||||
manpage(socat)(1)(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)
|
||||
|
|
19
doc/xio.help
19
doc/xio.help
|
@ -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
294
error.c
|
@ -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
34
error.h
|
@ -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) */
|
||||
|
|
5
fdname.c
5
fdname.c
|
@ -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
60
filan.c
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
30
hostan.c
30
hostan.c
|
@ -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);
|
||||
|
|
10
mytypes.h
10
mytypes.h
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
24
procan.c
24
procan.c
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
76
socat.c
|
@ -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);
|
||||
}
|
||||
|
|
10
socat.spec
10
socat.spec
|
@ -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
|
||||
|
|
|
@ -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
138
sslcls.c
|
@ -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 */
|
||||
|
|
36
sslcls.h
36
sslcls.h
|
@ -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
131
sycls.c
|
@ -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);
|
||||
}
|
||||
|
|
8
sycls.h
8
sycls.h
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
257
sysutils.c
257
sysutils.c
|
@ -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
|
||||
}
|
||||
|
|
15
sysutils.h
15
sysutils.h
|
@ -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,
|
||||
|
|
|
@ -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
37
utils.c
|
@ -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;
|
||||
}
|
||||
|
|
7
utils.h
7
utils.h
|
@ -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) */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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) */
|
12
xio-ascii.c
12
xio-ascii.c
|
@ -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++ = ' ';
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
80
xio-ip.c
80
xio-ip.c
|
@ -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) */
|
||||
|
||||
|
|
25
xio-ip4.c
25
xio-ip4.c
|
@ -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
103
xio-ip6.c
|
@ -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';
|
||||
}
|
||||
|
|
10
xio-ipapp.c
10
xio-ipapp.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
68
xio-listen.c
68
xio-listen.c
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
10
xio-named.c
10
xio-named.c
|
@ -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 {
|
||||
|
|
686
xio-openssl.c
686
xio-openssl.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 {
|
||||
|
|
39
xio-proxy.c
39
xio-proxy.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
14
xio-pty.c
14
xio-pty.c
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
108
xio-socket.c
108
xio-socket.c
|
@ -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
|
||||
|
|
15
xio-socks.c
15
xio-socks.c
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
57
xio-tun.c
57
xio-tun.c
|
@ -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);
|
||||
|
||||
|
|
29
xio-udp.c
29
xio-udp.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
199
xio-unix.c
199
xio-unix.c
|
@ -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
19
xio.h
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()");
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
160
xioopts.c
|
@ -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) {
|
||||
|
|
12
xioopts.h
12
xioopts.h
|
@ -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 ... */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
48
xiosigchld.c
48
xiosigchld.c
|
@ -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));
|
||||
|
|
23
xiosignal.c
23
xiosignal.c
|
@ -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));
|
||||
|
|
26
xiowrite.c
26
xiowrite.c
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue