mirror of
https://repo.or.cz/socat.git
synced 2025-05-29 15:30:48 +00:00
Compare commits
51 commits
4ee1f31cf8
...
78cc5ae1a5
Author | SHA1 | Date | |
---|---|---|---|
|
78cc5ae1a5 | ||
|
245f5e657f | ||
|
34b09a44ee | ||
|
6a53c955d3 | ||
|
b57d8668ec | ||
|
436d764029 | ||
|
9269897bab | ||
|
f0b30f3859 | ||
|
48f3341d82 | ||
|
186a323c2d | ||
|
52e2e5a277 | ||
|
d9d06eb587 | ||
|
c8aec28b82 | ||
|
e6aa3d1787 | ||
|
3339885f5b | ||
|
699da5f522 | ||
|
200ccb24cd | ||
|
568c26861b | ||
|
08d01c19ff | ||
|
264b21c1a9 | ||
|
7b26406d96 | ||
|
63f67101f4 | ||
|
676888e8cc | ||
|
ed11b3d2c5 | ||
|
416fe38e33 | ||
|
3f4b171523 | ||
|
2439276651 | ||
|
19d488a14f | ||
|
0f1c5dd85a | ||
|
c4844692f3 | ||
|
1ea37d48c2 | ||
|
25d2f746d9 | ||
|
663a6bb012 | ||
|
9bf5fc625c | ||
|
68f0143f7b | ||
|
920ed1f0a3 | ||
|
bcca5a3b9a | ||
|
9beffd3193 | ||
|
1154e69d3e | ||
|
1878ae93fd | ||
|
2dd1452f25 | ||
|
29f9e4db92 | ||
|
e7df880af5 | ||
|
5e56f25285 | ||
|
fa67d7d380 | ||
|
9968ca4c5b | ||
|
7a90caade5 | ||
|
af7d44d751 | ||
|
f38b76f5c8 | ||
|
2e21396282 | ||
|
69c9eb550c |
87 changed files with 5265 additions and 5989 deletions
CHANGESCHANGES.ISO-8859-1EXAMPLESFAQMakefile.inPORTINGREADMEREADME.FIPSSECURITYVERSIONcompat.hconfig.h.inconfigure.ac
doc
error.hfdname.cfilan.cfilan_main.chostan.cprocan-cdefs.cprocan.cprocan_main.creadline-test.shreadline.shsocat-broker.shsocat-chain.shsocat-mux.shsocat.csocat.specsocks4a-echo.shsocks4echo.shsocks5server-echo.shsslcls.csycls.csycls.hsysincludes.hsysutils.csysutils.htest.shxio-ascii.cxio-exec.cxio-fd.cxio-file.cxio-file.hxio-fs.cxio-interface.cxio-ip.cxio-ip.hxio-ip6.cxio-ipapp.cxio-ipapp.hxio-openssl.cxio-openssl.hxio-posixmq.cxio-posixmq.hxio-progcall.cxio-proxy.cxio-proxy.hxio-readline.cxio-shell.cxio-socket.cxio-socket.hxio-socketpair.cxio-socketpair.hxio-socks.cxio-socks.hxio-socks5.cxio-stdio.cxio-streams.cxio-tcpwrap.cxio-termios.cxio-tun.cxio-udp.cxio-unix.cxio-vsock.cxio.hxioconfig.hxiohelp.cxioinitialize.cxiolayer.cxiolockfile.cxioopen.cxioopts.cxioopts.hxioshutdown.cxiowrite.c
243
CHANGES
243
CHANGES
|
@ -1,4 +1,191 @@
|
|||
|
||||
####################### V 1.8.0.3:
|
||||
|
||||
Security:
|
||||
readline.sh has new option -lf <logfile> for stderr. If this option is
|
||||
not given it logs to a file in . (cwd) only when . is not writable by
|
||||
other users.
|
||||
|
||||
Corrections:
|
||||
Fixed display of option phases in help output.
|
||||
|
||||
filan -s displayed "(stream)" instead of "tcp" with addresses
|
||||
(regression).
|
||||
|
||||
Fixed a bug that made ignoreeof fail in 1.8.0.0 and 1.8.0.1;
|
||||
corrected test IGNOREEOF.
|
||||
Thanks to Rusty Bird for the precise problem report.
|
||||
|
||||
Fixed the regression introduced with version 1.8.0.1 that in socks5
|
||||
addresses the explicit socksport (2nd address parameter) was ignored.
|
||||
Thanks to Jakub Fišer for reporting this bug.
|
||||
|
||||
Do not log simple successful write with NOTICE level.
|
||||
|
||||
On partial write to not poll with sleep() but use select()/poll().
|
||||
|
||||
Partial write situations respect total inactivity timeout when
|
||||
nonblocking.
|
||||
|
||||
Fixed a bug that could lead to error "xiopoll(...): Bad file descriptor"
|
||||
or to undefined behaviour before terminating Socat with addresses EXEC,
|
||||
SYSTEM, or SHELL.
|
||||
|
||||
Option ip-add-source-membership did not work.
|
||||
Thanks to Duncan Sands and others for reporting this issue and sending
|
||||
the fix.
|
||||
|
||||
Option ip-add-membership with only two parameters crashed or failed
|
||||
when malloc() does not initialize memory with zeros.
|
||||
Thanks to Nicolas Cavallari for reporting and fixing this bug.
|
||||
|
||||
The readline() library function does not output the newline of empty
|
||||
input lines. Changed Socat to explicitly print the newline in this
|
||||
case.
|
||||
|
||||
Fixed implementation of options o-creat, o-excl, and o-cloexec with
|
||||
POSIXMQ-* addresses.
|
||||
POSIXMQ addresses are no longer experimental.
|
||||
|
||||
With version 1.8.0.0, and with 1.8.0.1 and option -0, the following
|
||||
command failed:
|
||||
socat UDP-LISTEN:1234,fork,reuseaddr,bind=127.0.0.1 -
|
||||
Message: "E xioopen_ipdgram_listen(): unknown address family 0":
|
||||
Thanks to Brian Woo for reporting this issue.
|
||||
Test: UDP_LISTEN_BIND4
|
||||
|
||||
Protected SSL_connect() from SIGCHLD,SIGUSR1.
|
||||
|
||||
Nanosleep() trace output now in decimal form.
|
||||
|
||||
UNIX-LISTEN with bind option terminated with INTERNAL error, this is
|
||||
now handled properly.
|
||||
Test: UNIX_L_BIND
|
||||
|
||||
Removed unused bytes variable from gettimestamp(), corrected #elsif,
|
||||
and socks4 record length.
|
||||
Thanks to clang-18 and gcc-13.
|
||||
|
||||
Address TCP-CONNECT, when target address resolves to both IPv4 and
|
||||
IPv6, now tries to take into account bind address for protocol
|
||||
selection.
|
||||
|
||||
Reworked and harmonized ipapp client addresses.
|
||||
Tests: TCP_CONNECT_RETRY SCTP_CONNECT_RETRY DCCP_CONNECT_RETRY
|
||||
OPENSSL_CONNECT_RETRY SOCKS4_RETRY SOCKS5_CONNECT_RETRY
|
||||
PROXY_CONNECT_RETRY
|
||||
|
||||
Socks and proxy clients now also support option max-children.
|
||||
Tests: TCP_CONNECT_MAXCHILDREN SCTP_CONNECT_MAXCHILDREN
|
||||
DCCP_CONNECT_MAXCHILDREN OPENSSL_CONNECT_MAXCHILDREN
|
||||
SOCKS4_MAXCHILDREN SOCKS5_CONNECT_MAXCHILDREN PROXY_CONNECT_MAXCHILDREN
|
||||
|
||||
On failure of getpwuid() (used in options su and su-d) now consider
|
||||
errno.
|
||||
|
||||
When IP4 was completed deconfigured, UDP6-RECVFROM with range option
|
||||
failed.
|
||||
|
||||
Fixed preprocessor directives in macro invocation.
|
||||
Thanks to Mario de Weerd for reporting this issue.
|
||||
|
||||
CONNECT addresses could use a wrong IPPROTO when getaddrinfo() does not
|
||||
support the selected one (at least on Debian-4 with SCTP).
|
||||
|
||||
socat -h (help) did not show option groups POSIXMQ, SCTP, DCCP, and
|
||||
UDPLITE of addresses.
|
||||
|
||||
Features:
|
||||
POSIXMQ-RECV now takes option o-nonblock; this, in combination with -T,
|
||||
makes it possible to terminate Socat in case the queue is empty.
|
||||
|
||||
New option posixmq-flush (mq-flush) for POSIXMQ addresses empties the
|
||||
queue before starting to transfer data.
|
||||
Test: LINUX_POSIXMQ_FLUSH
|
||||
|
||||
New options posixmq-maxmsg, posixmq-msgsize.
|
||||
Tests: POSIXMQ_MAXMSG POSIXMQ_MSGSIZE
|
||||
|
||||
POSIXMQ is now an alias for POSIXMQ-BIDIRECTIONAL. It can also be used
|
||||
in unidirectional context.
|
||||
|
||||
Procan uses getresuid() and getresgid() when available, to determine
|
||||
the saved set-user-ID.
|
||||
|
||||
Procan prints more C-defines, esp.O_*, AI_*, EAI_*; __GLIBC__;
|
||||
prints some C-defines in oct and hex;
|
||||
added option -V
|
||||
|
||||
Procan tells if char is signed or unsigned
|
||||
|
||||
Socat now prints an info message when implicitly setting SO_REUSEADDR.
|
||||
Thanks to Michael Renner for this suggestion.
|
||||
|
||||
Added generic options setsockopt-socket and setsockopt-connected that
|
||||
are applied after socket() or when connected.
|
||||
|
||||
POSIXMQ addresses now print a warning when options posixmq-maxmsg or
|
||||
posixmq-msgsize were not applied.
|
||||
|
||||
New address POSIXMQ-WRITE does the same as POSIXMQ-SEND, as counterpart
|
||||
of POSIXMQ-READ.
|
||||
|
||||
Building:
|
||||
Disabling certain features during configure could break build process.
|
||||
|
||||
Again fixes a few disable problems.
|
||||
|
||||
Porting:
|
||||
Fix for old FreeBSD.
|
||||
|
||||
Fixes for old Debian
|
||||
|
||||
Fixes for old Scientific/RHEL
|
||||
|
||||
Socat failed to build on platforms without flock() function (AIX,
|
||||
Solaris) due to a missing guard.
|
||||
|
||||
Newer Linux distributions do not provide libwrap: do not leave unused
|
||||
variable.
|
||||
|
||||
Newer Linux distributions deprecate usleep, replace it.
|
||||
|
||||
OpenSSL-3 loudly deprecates some functions or macros, replace a first
|
||||
bunch of them.
|
||||
|
||||
Fixes for FreeBSD-15 (DCCP)
|
||||
|
||||
Fix for compiling on Solaris-11
|
||||
|
||||
Testing:
|
||||
test.sh produces file results.txt with columns of test numbers, names,
|
||||
and results.
|
||||
|
||||
Fixed a few testing issues.
|
||||
|
||||
Added test script sock5server-echo.sh for SOCKS5-CONNECT and
|
||||
SOCKS5-LISTEN, and appropriate tests.
|
||||
SOCKS5 addresses are no longer experimental.
|
||||
Tests: SOCKS5CONNECT_TCP4 SOCKS5LISTEN_TCP4
|
||||
|
||||
Added a developer test that overwrites malloc'ed memory with non-zeros.
|
||||
|
||||
Newer Linux distributions now deprecate usleep; replaced it in test.sh
|
||||
|
||||
UDPLITE4STREAM was trice, changed one of them to UDPLITE6STREAM.
|
||||
|
||||
Catch problems caused by ISPs that filter *.dest-unreach.net records.
|
||||
|
||||
Documentation:
|
||||
Removed obsolete CHANGES.ISO-8859-1 file.
|
||||
|
||||
Corrected lots of misspelling and typos.
|
||||
Thanks to Mario de Weerd for reporting these issues.
|
||||
|
||||
Improved README file.
|
||||
|
||||
Better explained benefit of UDP-DATAGRAM address type.
|
||||
|
||||
####################### V 1.8.0.2:
|
||||
|
||||
Security:
|
||||
|
@ -70,6 +257,9 @@ Corrections:
|
|||
Print warning about not checking CRLs in OpenSSL only in the first
|
||||
child process.
|
||||
|
||||
Fixed preprocessor directives in macro invocation.
|
||||
Thanks to Mario de Weerd for reporting this issue.
|
||||
|
||||
Features:
|
||||
Total inactivity timeout option -T 0 now means 0.0 seconds; up to
|
||||
version 1.8.0.0 it meant no total inactivity timeout.
|
||||
|
@ -237,11 +427,11 @@ Features:
|
|||
no IP version is preferred by build, environment, option, or address
|
||||
type, Socat chooses IPv6 because this might activate both versions (but
|
||||
check option ipv6-v6only).
|
||||
Added option ai-passive to control this flag explicitely.
|
||||
Added option ai-passive to control this flag explicitly.
|
||||
|
||||
New option ai-v4mapped (v4mapped) sets or unsets the AI_V4MAPPED flag
|
||||
of the resolver. For Socat addresses requiring IPv6 addresses, this
|
||||
resolves IPv4 addresses to the approriate IPv6 address [::ffff:*:*].
|
||||
resolves IPv4 addresses to the appropriate IPv6 address [::ffff:*:*].
|
||||
|
||||
DNS resolver Options (res-*) are now set for the complete open phase of
|
||||
the address, not per getaddrinfo() invocation.
|
||||
|
@ -434,14 +624,14 @@ Porting:
|
|||
Some corrections for better 32bit systems support.
|
||||
|
||||
Testing:
|
||||
Removed obselete parts from test.sh
|
||||
Removed obsolete parts from test.sh
|
||||
|
||||
test.sh: Introduced function checkcond
|
||||
|
||||
Renamed test.sh option -foreign to -internet
|
||||
|
||||
Documentation:
|
||||
Removed obselete file doc/xio.help
|
||||
Removed obsolete file doc/xio.help
|
||||
|
||||
Added doc for option ipv6-join-group (ipv6-add-membership)
|
||||
Thanks to Martin Buck for sending the patch.
|
||||
|
@ -454,7 +644,7 @@ Documentation:
|
|||
|
||||
Corrections:
|
||||
On connect() failure and in some other situations Socat tries to get
|
||||
detailled information about the error with recvmsg(). Error return of
|
||||
detailed information about the error with recvmsg(). Error return of
|
||||
this function is now logged as Info instead of Warn.
|
||||
|
||||
Tests of the correction of the "IP_ADD_SOURCE_MEMBERSHIP but not struct
|
||||
|
@ -498,7 +688,7 @@ Corrections:
|
|||
Thanks to Gordon W.Ross for reporting and fixing this issue.
|
||||
Test: RESTORE_TTY
|
||||
|
||||
The OpenSSL client SNI parameter, when not explicitely specified, is
|
||||
The OpenSSL client SNI parameter, when not explicitly specified, is
|
||||
derived from option commonname or rom target server name. This is not
|
||||
useful with IP addresses, which Socat now checks and avoids.
|
||||
|
||||
|
@ -529,7 +719,7 @@ Coding:
|
|||
|
||||
fcntl() trace prints flags now in hexadecimal.
|
||||
|
||||
Stream dump options -r and -R now open their pathes with CLOEXEC to
|
||||
Stream dump options -r and -R now open their paths with CLOEXEC to
|
||||
prevent leaking into sub processes.
|
||||
Test: EXEC_SNIFF
|
||||
|
||||
|
@ -828,7 +1018,7 @@ Corrections:
|
|||
Print a message when readbytes option causes EOF
|
||||
|
||||
The ip-recverr option had no effect. Corrected and improved its
|
||||
handling of ancilliary messages, so it is able to analyze ICMP error
|
||||
handling of ancillary messages, so it is able to analyze ICMP error
|
||||
packets (Linux only?)
|
||||
|
||||
Setgui(), Setuid() calls in xio-progcall.c were useless.
|
||||
|
@ -862,11 +1052,11 @@ Corrections:
|
|||
|
||||
Under certain conditions OpenSSL stream connections, in particular bulk
|
||||
data transfer in unidirectional mode, failed during transfer or near
|
||||
its with Connection reset by peer on receiver side.
|
||||
its end with Connection reset by peer on receiver side.
|
||||
This happened with Socat versions 1.7.3.3 to 1.7.4.0. Reasons were
|
||||
lazy SSL shutdown handling on the sender side in combination with
|
||||
SSL_MODE_AUTO_RETRY turned off.
|
||||
Fix: After SSH_shutdown but before socket shutdown call SSL_read()
|
||||
Fix: After SSL_shutdown() but before socket shutdown call SSL_read()
|
||||
Test: OPENSSL_STREAM_TO_SERVER
|
||||
Fixes Red Hat issue 1870279.
|
||||
|
||||
|
@ -966,7 +1156,7 @@ Porting:
|
|||
ai_protocol=0 and try again
|
||||
Test: SCTP_SERVICENAME
|
||||
|
||||
Per file filesystem options were still named ext2-* and depended on
|
||||
Per file filesystem options were still named ext2-* and dependent on
|
||||
<linux/ext2_fs.h>. Now they are called fs-* and depend on <linux/fs.h>.
|
||||
These fs-* options are also available on old systems with ext2_fs.h
|
||||
|
||||
|
@ -979,14 +1169,14 @@ Porting:
|
|||
SSL_library_init.
|
||||
|
||||
With OPENSSL_API_COMPAT=0x10000000L the files openssl/dh.h, openssl/bn.h
|
||||
must explicitely be included.
|
||||
must explicitly be included.
|
||||
Thanks to Rosen Penev for reporting and sending a patch.
|
||||
|
||||
Testing:
|
||||
test.sh now produces a list of tests that could not be performed for
|
||||
any reason. This helps to analyse these cases.
|
||||
|
||||
OpenSSL s_server appearently started to neglect TCPs half close feature.
|
||||
OpenSSL s_server apparently started to neglect TCPs half close feature.
|
||||
Test OPENSSL_TCP4 has been changed to tolerate this.
|
||||
|
||||
OpenSSL changed its behaviour when connection is rejected. Tests
|
||||
|
@ -1180,7 +1370,7 @@ Corrections:
|
|||
Porting:
|
||||
OpenSSL functions TLS1_client_method() and similar are
|
||||
deprecated. Socat now uses recommended TLS_client_method(). The old
|
||||
functions and dependend option openssl-method can still be
|
||||
functions and dependent option openssl-method can still be
|
||||
used when configuring socat with --enable-openssl-method
|
||||
|
||||
Shell scripts in socat distribution are now headed with:
|
||||
|
@ -1222,7 +1412,7 @@ Testing:
|
|||
More corrections to test.sh:
|
||||
Language settings could still influence test results
|
||||
netstat was still required
|
||||
Suppress usleep deprecated messag
|
||||
Suppress usleep deprecated message
|
||||
Force use of IPv4 with some certificates
|
||||
Set timeout for UDPxMAXCHILDREN tests
|
||||
|
||||
|
@ -1375,7 +1565,7 @@ testing:
|
|||
|
||||
docu:
|
||||
Corrected source of socat man page to correctly show man references
|
||||
like socket(2); removed obseolete entries from See Also
|
||||
like socket(2); removed obsolete entries from See Also
|
||||
|
||||
Docu and some comments mentioned addresses SSL-LISTEN and SSL-CONNECT
|
||||
that do not exist (OPENSSL-LISTEN, SSL-L; and OPENNSSL-CONNECT, SSL
|
||||
|
@ -1410,6 +1600,7 @@ security:
|
|||
|
||||
Socat security advisory 7
|
||||
MSVR-1499
|
||||
CVE-2016-2217
|
||||
In the OpenSSL address implementation the hard coded 1024 bit DH p
|
||||
parameter was not prime. The effective cryptographic strength of a key
|
||||
exchange using these parameters was weaker than the one one could get by
|
||||
|
@ -1417,7 +1608,7 @@ security:
|
|||
parameters were chosen, the existence of a trapdoor that makes possible
|
||||
for an eavesdropper to recover the shared secret from a key exchange
|
||||
that uses them cannot be ruled out.
|
||||
Futhermore, 1024bit is not considered sufficiently secure.
|
||||
Furthermore, 1024bit is not considered sufficiently secure.
|
||||
Fix: generated a new 2048bit prime.
|
||||
Thanks to Santiago Zanella-Beguelin and Microsoft Vulnerability
|
||||
Research (MSVR) for finding and reporting this issue.
|
||||
|
@ -1431,7 +1622,7 @@ security:
|
|||
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
|
||||
applied to make the code async signal safe but still provide detailed
|
||||
logging from signal handlers:
|
||||
Coded function vsnprintf_r() as async signal safe incomplete substitute
|
||||
of libc vsnprintf()
|
||||
|
@ -1519,7 +1710,7 @@ corrections:
|
|||
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
|
||||
over option raw which is now obsolete. On SysV systems this call is
|
||||
simulated by appropriate setting.
|
||||
Thanks to Youfu Zhang for reporting issue with option raw.
|
||||
|
||||
|
@ -1532,7 +1723,7 @@ porting:
|
|||
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
|
||||
support external BUILD_DATE env var to allow to build reproducible
|
||||
binaries
|
||||
|
||||
Joachim Fenkes provided an new adapted spec file.
|
||||
|
@ -1653,7 +1844,7 @@ porting:
|
|||
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
|
||||
type of struct cmsghdr.cmsg is system dependent, determine it with
|
||||
configure; some more print format corrections
|
||||
|
||||
docu:
|
||||
|
@ -1707,7 +1898,7 @@ corrections:
|
|||
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
|
||||
UDP-LISTEN would always 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
|
||||
|
@ -1940,7 +2131,7 @@ new features:
|
|||
|
||||
added generic socket addresses: SOCKET-CONNECT, SOCKET-LISTEN,
|
||||
SOCKET-SENDTO, SOCKET-RECVFROM, SOCKET-RECV, SOCKET-DATAGRAM allow
|
||||
protocol independent socket handling; all parameters are explicitely
|
||||
protocol independent socket handling; all parameters are explicitly
|
||||
specified as numbers or hex data
|
||||
|
||||
added address options ioctl-void, ioctl-int, ioctl-intp, ioctl-string,
|
||||
|
@ -2013,7 +2204,7 @@ corrections:
|
|||
this bug). test: EXECSPACES
|
||||
|
||||
in ignoreeof polling mode socat also blocked data transfer in the other
|
||||
direction during the 1s wait intervalls (thanks to Jorgen Cederlof for
|
||||
direction during the 1s wait intervals (thanks to Jorgen Cederlof for
|
||||
reporting this bug)
|
||||
|
||||
corrected alphabetical order of options (proxy-auth)
|
||||
|
@ -2439,7 +2630,7 @@ corrections:
|
|||
|
||||
check for /proc at runtime, even if configure found it
|
||||
|
||||
src.rpm accidently supported SuSE instead of RedHat
|
||||
src.rpm accidentally supported SuSE instead of RedHat
|
||||
|
||||
####################### V 1.3.2.0:
|
||||
|
||||
|
@ -2715,7 +2906,7 @@ solved problems and bugs:
|
|||
SOLVED: now uses common TCP service resolver
|
||||
|
||||
PROBLEM: with PIPE, wrong FDs were shown for data transfer loop
|
||||
SOLVED: retrieval of FDs now pays respect to PIPE pecularities
|
||||
SOLVED: retrieval of FDs now pays respect to PIPE peculiarities
|
||||
|
||||
PROBLEM: using address EXEC against an address with IGNOREEOF, socat
|
||||
never terminated
|
||||
|
|
1800
CHANGES.ISO-8859-1
1800
CHANGES.ISO-8859-1
File diff suppressed because it is too large
Load diff
8
EXAMPLES
8
EXAMPLES
|
@ -67,7 +67,7 @@ $ socat \
|
|||
TCP-LISTEN:8000,crlf \
|
||||
SYSTEM:"echo HTTP/1.0 200; echo Content-Type\: text/plain; echo; cat"
|
||||
|
||||
// A less primitive HTTP echo server that sends back not only the reqest but
|
||||
// A less primitive HTTP echo server that sends back not only the request but
|
||||
// also server and client address and port. Might have portability issues with
|
||||
// echo
|
||||
$ socat -T 1 -d -d \
|
||||
|
@ -131,7 +131,7 @@ $ socat \
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Intrusion testing
|
||||
|
||||
// Found an XWindow Server behind IP filters with FTP data hole? (you are
|
||||
// Found an X-Window Server behind IP filters with FTP data hole? (you are
|
||||
// lucky!)
|
||||
// prepare your host:
|
||||
# rm -f /tmp/.X11-unix/X1
|
||||
|
@ -241,7 +241,7 @@ $ socat - /tmp/postoffice
|
|||
// Uses of filan
|
||||
// See what your operating system opens for you
|
||||
$ filan
|
||||
// or if that was too detailled
|
||||
// or if that was too detailed
|
||||
$ filan -s
|
||||
// See what file descriptors are passed via exec function
|
||||
$ socat - EXEC:"filan -s",nofork
|
||||
|
@ -342,7 +342,7 @@ socat \
|
|||
// three main versions for entering password:
|
||||
// 1) from your TTY; have 10 seconds to enter password:
|
||||
(sleep 10; echo "ls"; sleep 1) |socat - EXEC:'ssh server',pty
|
||||
// 2) from XWindows (DISPLAY !); again 10 seconds
|
||||
// 2) from X-Windows (DISPLAY !); again 10 seconds
|
||||
(sleep 10; echo "ls"; sleep 1) |socat - EXEC:'ssh server',pty,setsid
|
||||
// 3) from script
|
||||
(sleep 5; echo PASSWORD; echo ls; sleep 1) |./socat - EXEC:'ssh server',pty,setsid,ctty
|
||||
|
|
2
FAQ
2
FAQ
|
@ -60,7 +60,7 @@ Q: When I specify a dual address (two partial addresses linked with "!!") on
|
|||
the command line, I get some message "event not found", and my shell history
|
||||
has the line truncated. Not even protecting the '!'s with '\' helps.
|
||||
|
||||
A: '!' is appearently used by your shell as history expansion character. Say
|
||||
A: '!' is apparently used by your shell as history expansion character. Say
|
||||
"set +H" and add this line to your (bash) profile.
|
||||
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ SHFILES = socat-chain.sh socat-mux.sh socat-broker.sh \
|
|||
daemon.sh mail.sh ftp.sh readline.sh \
|
||||
socat_buildscript_for_android.sh
|
||||
TESTFILES = test.sh socks4echo.sh proxyecho.sh readline-test.sh \
|
||||
proxy.sh socks4a-echo.sh
|
||||
proxy.sh socks4a-echo.sh socks5server-echo.sh
|
||||
|
||||
all: progs doc
|
||||
|
||||
|
|
2
PORTING
2
PORTING
|
@ -51,7 +51,7 @@ ACTIVE PHASE:
|
|||
. xioopts.h: enum e_optcode (sorted numerically/alphabetically by name)
|
||||
. xio-*.c: select the appropriate address file (e.g., xio-tcp.c for
|
||||
TCP-options) and make a record of type struct optdesc: opt_newoption
|
||||
. xio-*.h: the declation of struct optdesc
|
||||
. xio-*.h: the declaration of struct optdesc
|
||||
. xioopts.c: add records to struct optname optionnames for all appropriate
|
||||
names (sorted strictly ASCII for binary search)
|
||||
. filan.c: add the option to the appropriate array (sockopts, ipopts,
|
||||
|
|
15
README
15
README
|
@ -58,18 +58,25 @@ Rocky 9
|
|||
Cygwin 10.0
|
||||
|
||||
|
||||
install
|
||||
-------
|
||||
build
|
||||
-----
|
||||
|
||||
You need at least gcc and make.
|
||||
A few libraries are required for full features:
|
||||
Debian: libssl-dev libreadline-dev libwrap0-dev
|
||||
Red Hat: openssl-devel readline-devel tcp_wrappers-libs
|
||||
Arch Linux: openssl readline
|
||||
|
||||
|
||||
Get the tarball and extract it:
|
||||
tar xzf socat.tar.gz
|
||||
cd socat-1.8.0.2
|
||||
cd socat-1.8.0.3
|
||||
./configure
|
||||
make
|
||||
su
|
||||
make install # installs socat, filan, and procan in /usr/local/bin
|
||||
|
||||
For compiling socat, gcc (or clang) is recommended.
|
||||
For compiling socat, gcc or a compatible compiler (e.g. clang) is recommended.
|
||||
If gcc (or a compiler with similar front end) is not available, the configure
|
||||
script might fail to determine some features
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ initializes things so after a fork, the child must reinitialize. When the
|
|||
ssl code detects a forks occur and if FIPS mode was enabled, it reinitializes
|
||||
FIPS by disabling and then enabling it again.
|
||||
|
||||
To produce Davids enviroment, do the following:
|
||||
To produce Davids environment, do the following:
|
||||
To build openssl
|
||||
download OpenSSL 0.9.7j-fips-dev from
|
||||
http://www.openssl.org/source/OpenSSL-fips-1.0.tar.gz
|
||||
|
|
2
SECURITY
2
SECURITY
|
@ -24,7 +24,7 @@ avoid accessing files in world-writable directories like /tmp
|
|||
|
||||
* When using socat with system, exec, or in a shell script, know what you do
|
||||
|
||||
* With system and exec, use absolute pathes or set the path option
|
||||
* With system and exec, use absolute paths or set the path option
|
||||
|
||||
* When starting programs with socat, consider using the chroot option (this
|
||||
requires root, so use the substuser option too).
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
"1.8.0.2"
|
||||
"1.8.0.3"
|
||||
|
|
4
compat.h
4
compat.h
|
@ -98,6 +98,10 @@ typedef int sig_atomic_t;
|
|||
# define SOL_IPV6 IPPROTO_IPV6
|
||||
#endif
|
||||
|
||||
#ifndef EAI_NODATA
|
||||
# define EAI_NODATA 7 /* for old FreeBSD */
|
||||
#endif
|
||||
|
||||
#define F_uint8_t "%hu"
|
||||
#define F_uint8_x "%02hx"
|
||||
#define F_int8_t "%hd"
|
||||
|
|
12
config.h.in
12
config.h.in
|
@ -162,6 +162,12 @@
|
|||
/* Define if you have the clock_gettime function */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* Define if you have the getresuid function */
|
||||
#undef HAVE_GETRESUID
|
||||
|
||||
/* Define if you have the getresgid function */
|
||||
#undef HAVE_GETRESGID
|
||||
|
||||
/* Define if you have the strtoll function */
|
||||
#undef HAVE_STRTOLL
|
||||
|
||||
|
@ -282,6 +288,9 @@
|
|||
/* Define if you have the <linux/if_tun.h> header file. */
|
||||
#undef HAVE_LINUX_IF_TUN_H
|
||||
|
||||
/* Define if you have the <netinet/dccp.h> header file. */
|
||||
#undef HAVE_NETINET_DCCP_H
|
||||
|
||||
/* Define if you have the <linux/dccp.h> header file. */
|
||||
#undef HAVE_LINUX_DCCP_H
|
||||
|
||||
|
@ -333,6 +342,9 @@
|
|||
/* Define if you have the <readline/history.h> header file. */
|
||||
#undef HAVE_READLINE_HISTORY_H
|
||||
|
||||
/* Define if you have the <mqueue.h> header file. */
|
||||
#undef HAVE_MQUEUE_H
|
||||
|
||||
/* Define if you have the readline library. */
|
||||
#undef HAVE_LIBREADLINE
|
||||
|
||||
|
|
78
configure.ac
78
configure.ac
|
@ -39,7 +39,7 @@ AC_PROG_RANLIB
|
|||
AC_SUBST(AR)
|
||||
AC_CHECK_PROG(AR, ar, ar, gar)
|
||||
#
|
||||
# we need to explicitely call this here; otherwise, with --disable-libwrap we
|
||||
# we need to explicitly call this here; otherwise, with --disable-libwrap we
|
||||
# fail
|
||||
AC_LANG_COMPILER_REQUIRE()
|
||||
|
||||
|
@ -409,21 +409,33 @@ AC_ARG_ENABLE(dccp, [ --disable-dccp disable DCCP support],
|
|||
[AC_MSG_RESULT(yes); WITH_DCCP=1 ])
|
||||
|
||||
if test -n "$WITH_DCCP"; then
|
||||
AC_MSG_CHECKING(for IPPROTO_DCCP)
|
||||
AC_CACHE_VAL(sc_cv_define_ipproto_dccp,
|
||||
[AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <netinet/in.h>],
|
||||
[IPPROTO_DCCP;],
|
||||
[sc_cv_define_ipproto_dccp=yes],
|
||||
[sc_cv_define_ipproto_dccp=no])])
|
||||
AC_MSG_RESULT($sc_cv_define_ipproto_dccp)
|
||||
if test $sc_cv_define_ipproto_dccp = yes; then
|
||||
AC_DEFINE(WITH_DCCP)
|
||||
AC_CHECK_HEADER(netinet/dccp.h,
|
||||
AC_DEFINE(HAVE_NETINET_DCCP_H))
|
||||
AC_CHECK_HEADER(linux/dccp.h,
|
||||
AC_DEFINE(HAVE_LINUX_DCCP_H))
|
||||
else
|
||||
AC_MSG_WARN([IPPROTO_DCCP undefined, disabling DCCP support])
|
||||
fi
|
||||
if test -n "$WITH_DCCP"; then
|
||||
AC_MSG_CHECKING(for IPPROTO_DCCP)
|
||||
AC_CACHE_VAL(sc_cv_define_ipproto_dccp,
|
||||
[AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <netinet/in.h>],
|
||||
[IPPROTO_DCCP;],
|
||||
[sc_cv_define_ipproto_dccp=yes],
|
||||
[sc_cv_define_ipproto_dccp=no; WITH_DCCP=])])
|
||||
AC_MSG_RESULT($sc_cv_define_ipproto_dccp)
|
||||
fi
|
||||
if test -n "$WITH_DCCP"; then
|
||||
AC_MSG_CHECKING(for SOCK_DCCP)
|
||||
AC_CACHE_VAL(sc_cv_define_sock_dccp,
|
||||
[AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <netinet/in.h>],
|
||||
[SOCK_DCCP;],
|
||||
[sc_cv_define_sock_dccp=yes],
|
||||
[sc_cv_define_sock_dccp=no; WITH_DCCP=])])
|
||||
AC_MSG_RESULT($sc_cv_define_sock_dccp)
|
||||
fi
|
||||
if test -n "$WITH_DCCP"; then
|
||||
AC_DEFINE(WITH_DCCP)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(whether to include vsock support)
|
||||
|
@ -489,6 +501,13 @@ AC_ARG_ENABLE(posixmq, [ --disable-posixmq disable POSIX MQ support],
|
|||
*) WITH_POSIXMQ=1; AC_MSG_RESULT(yes);;
|
||||
esac],
|
||||
[WITH_POSIXMQ=1; AC_MSG_RESULT(yes)])
|
||||
if test "$WITH_POSIXMQ"; then
|
||||
AC_CHECK_HEADERS(mqueue.h)
|
||||
if test "x$ac_cv_header_mqueue_h" != xyes; then
|
||||
AC_MSG_WARN([Header mqueue.h not found, disabling POSIX MQ])
|
||||
WITH_POSIXMQ=
|
||||
fi
|
||||
fi
|
||||
if test "$WITH_POSIXMQ"; then
|
||||
case "`uname`" in
|
||||
Linux) AC_DEFINE(WITH_POSIXMQ)
|
||||
|
@ -652,23 +671,16 @@ if test -n "$WITH_OPENSSL"; then
|
|||
AC_CACHE_VAL(sc_cv_have_openssl_ssl_h,
|
||||
[AC_TRY_COMPILE([#include <openssl/ssl.h>],[;],
|
||||
[sc_cv_have_openssl_ssl_h=yes; OPENSSL_BASE=""; ],
|
||||
[sc_cv_have_openssl_ssl_h=no
|
||||
if test "$OPENSSL_BASE"; then
|
||||
Ds="$OPENSSL_BASE"
|
||||
else
|
||||
Ds="/sw /usr/local /opt/freeware /usr/sfw /usr/local/ssl"
|
||||
fi
|
||||
for D in $Ds; do
|
||||
I="$D/include"
|
||||
i="$I/openssl/ssl.h"
|
||||
if test -r "$i"; then
|
||||
#V_INCL="$V_INCL -I$I"
|
||||
CPPFLAGS="$CPPFLAGS -I$I"
|
||||
AC_MSG_NOTICE(found $i)
|
||||
sc_cv_have_openssl_ssl_h=yes; OPENSSL_BASE="$D"
|
||||
break;
|
||||
fi
|
||||
done])
|
||||
[
|
||||
# Another attempt to compile with OPENSSL_NO_KRB5
|
||||
AC_MSG_NOTICE(trying with -DOPENSSL_NO_KRB5)
|
||||
CFLAGS_ORIG="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -DOPENSSL_NO_KRB5"
|
||||
AC_TRY_COMPILE([#include <openssl/ssl.h>],[;],
|
||||
[sc_cv_have_openssl_ssl_h=yes],
|
||||
[sc_cv_have_openssl_ssl_h=no
|
||||
CFLAGS="$CFLAGS_ORIG"])
|
||||
])
|
||||
])
|
||||
if test "$sc_cv_have_openssl_ssl_h" = "yes"; then
|
||||
AC_DEFINE(HAVE_OPENSSL_SSL_H)
|
||||
|
@ -1722,6 +1734,8 @@ AC_CHECK_PROTOTYPE_LIB(gettimeofday)
|
|||
|
||||
AC_CHECK_FUNC(clock_gettime, AC_DEFINE(HAVE_CLOCK_GETTIME), AC_CHECK_LIB(rt, clock_gettime, [LIBS="-lrt $LIBS"; AC_DEFINE(HAVE_CLOCK_GETTIME)]))
|
||||
|
||||
AC_CHECK_FUNCS(getresuid getresgid)
|
||||
|
||||
dnl Search for flock()
|
||||
# with Linux it's in libc, with AIX in libbsd
|
||||
AC_CHECK_FUNC(flock, AC_DEFINE(HAVE_FLOCK),
|
||||
|
@ -2248,7 +2262,7 @@ AC_TRY_COMPILE([#include <resolv.h>],
|
|||
|
||||
dnl "tcpd" "tcpwrappers"
|
||||
# on some platforms, raw linking with libwrap fails because allow_severity and
|
||||
# deny_severity are not explicitely defined. Thus we put the libwrap part to
|
||||
# deny_severity are not explicitly defined. Thus we put the libwrap part to
|
||||
# the end
|
||||
AC_MSG_CHECKING(whether to include libwrap support)
|
||||
AC_ARG_ENABLE(libwrap, [ --disable-libwrap disable libwrap support],
|
||||
|
@ -2303,7 +2317,7 @@ int allow_severity,deny_severity;],[hosts_access(0)],
|
|||
AC_TRY_LINK([#include <sys/types.h>
|
||||
#include <tcpd.h>
|
||||
int allow_severity,deny_severity;],[hosts_access(0)],
|
||||
[sc_cv_have_libwrap='yes'],
|
||||
[sc_cv_have_libwrap='yes'],
|
||||
[sc_cv_have_libwrap='no'])
|
||||
]
|
||||
)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<h2>Introduction</h2>
|
||||
<p>Beginning with version 1.7.0 socat provides means to freely control
|
||||
important aspects of socket handling. This allows to experiment with socket
|
||||
types and protocols that are not explicitely implemented in socat.
|
||||
types and protocols that are not explicitly implemented in socat.
|
||||
</p>
|
||||
|
||||
<p>The related socat features fall into three major categories:<p>
|
||||
|
@ -216,7 +216,7 @@ struct sockaddr_at {
|
|||
</p>
|
||||
|
||||
<p>The address family component must be omitted from the socket address because
|
||||
it is added by socat implicitely. The resulting hexadecimal representation of
|
||||
it is added by socat implicitly. The resulting hexadecimal representation of
|
||||
the target socket address is therefore:
|
||||
</p>
|
||||
<tt>x40x00xff00xf3x00x0000000000000000</tt>
|
||||
|
@ -287,7 +287,7 @@ struct sockaddr_at {
|
|||
and for bind and range options. The basis is the <tt>struct sockaddr_*</tt> for
|
||||
the respective address family that should be declared in the C include files.
|
||||
Please keep in mind that their first two bytes (<tt>sa_family</tt> and - on BSD
|
||||
- <tt>sa_len</tt>) are implicitely prepended by socat.</p>
|
||||
- <tt>sa_len</tt>) are implicitly prepended by socat.</p>
|
||||
|
||||
<h4>Linux on 32bit Intel:</h4>
|
||||
|
||||
|
|
139
doc/socat.yo
139
doc/socat.yo
|
@ -313,6 +313,7 @@ label(ADDRESS_CREAT)dit(bf(tt(CREATE:<filename>)))
|
|||
if <filename> refers to a socket, this is an error.nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(REG)(GROUP_REG),link(NAMED)(GROUP_NAMED) nl()
|
||||
Useful options:
|
||||
link(mode)(OPTION_UMASK),
|
||||
link(mode)(OPTION_MODE),
|
||||
link(user)(OPTION_USER),
|
||||
link(group)(OPTION_GROUP),
|
||||
|
@ -332,7 +333,7 @@ label(ADDRESS_DCCP_CONNECT)dit(bf(tt(DCCP-CONNECT:<host>:<port>)) (bf(tt(DCCP:<h
|
|||
link(connect-timeout)(OPTION_CONNECT_TIMEOUT),
|
||||
link(tos)(OPTION_TOS),
|
||||
link(dccp-set-ccid)(OPTION_DCCP_SET_CCID),
|
||||
link(nonblock)(OPTION_NONBLOCK),
|
||||
link(nonblock)(OPTION_O_NONBLOCK),
|
||||
link(sourceport)(OPTION_SOURCEPORT),
|
||||
link(retry)(OPTION_RETRY),
|
||||
link(readbytes)(OPTION_READBYTES)nl()
|
||||
|
@ -583,7 +584,7 @@ label(ADDRESS_OPEN)dit(bf(tt(OPEN:<filename>)))
|
|||
Option groups: link(FD)(GROUP_FD),link(REG)(GROUP_REG),link(NAMED)(GROUP_NAMED),link(OPEN)(GROUP_OPEN) nl()
|
||||
Useful options:
|
||||
link(creat)(OPTION_O_CREAT),
|
||||
link(excl)(OPTION_EXCL),
|
||||
link(excl)(OPTION_O_EXCL),
|
||||
link(noatime)(OPTION_O_NOATIME),
|
||||
link(nofollow)(OPTION_NOFOLLOW),
|
||||
link(append)(OPTION_APPEND),
|
||||
|
@ -747,7 +748,7 @@ label(ADDRESS_NAMED_PIPE)dit(bf(tt(PIPE:<filename>)))
|
|||
Option groups: link(FD)(GROUP_FD),link(NAMED)(GROUP_NAMED),link(OPEN)(GROUP_OPEN) nl()
|
||||
Useful options:
|
||||
link(rdonly)(OPTION_RDONLY),
|
||||
link(nonblock)(OPTION_NONBLOCK),
|
||||
link(nonblock)(OPTION_O_NONBLOCK),
|
||||
link(group)(OPTION_GROUP),
|
||||
link(user)(OPTION_USER),
|
||||
link(mode)(OPTION_MODE),
|
||||
|
@ -773,50 +774,65 @@ label(ADDRESS_SOCKETPAIR)dit(bf(tt(SOCKETPAIR)))
|
|||
See also: link(unnamed pipe)(ADDRESS_UNNAMED_PIPE)
|
||||
|
||||
label(ADDRESS_POSIXMQ_READ)dit(bf(tt(POSIXMQ-READ:/<mqueue>)))
|
||||
Opens the specified POSIX message queue and reads messages (packets). It
|
||||
keeps the boundaries.nl()
|
||||
Opens or creates the specified POSIX message queue and reads messages
|
||||
(packets). It keeps the packet boundaries.nl()
|
||||
This is a read-only address, see options link(-u)(option_u) and
|
||||
link(-U)(option_U) and link(dual addresses)(ADDRESS_DUAL).nl()
|
||||
Socat() provides this address type only on Linux because POSIX MQ is based
|
||||
on UNIX filedescriptors there.nl()
|
||||
This feature is new in version 1.8.0.0 and might change in the future,
|
||||
therefore it is link(experimental)(option_experimental).nl()
|
||||
Useful options:
|
||||
link(posixmq-priority)(OPTION_POSIXMQ_PRIORITY),
|
||||
link(unlink-early)(OPTION_UNLINK_EARLY),
|
||||
link(unlink-close)(OPTION_UNLINK_CLOSE)
|
||||
link(unlink-close)(OPTION_UNLINK_CLOSE),
|
||||
link(o-nonblock)(OPTION_O_NONBLOCK),
|
||||
link(o-creat)(OPTION_O_CREAT),
|
||||
link(o-excl)(OPTION_O_EXCL),
|
||||
link(umask)(OPTION_UMASK)
|
||||
|
||||
label(ADDRESS_POSIXMQ_RECEIVE)dit(bf(tt(POSIXMQ-RECEIVE:/<mqueue>)))
|
||||
dit(bf(tt(POSIXMQ-RECV:/<mqueue>)))
|
||||
Opens the specified POSIX message queue and reads one message (packet).nl()
|
||||
Opens or creates the specified POSIX message queue and reads one message
|
||||
(packet).nl()
|
||||
This is a read-only address. See link(POSIXMQ-READ)(ADDRESS_POSIXMQ_READ)
|
||||
for more info.nl()
|
||||
Example: link(POSIX MQ recv with fork)(EXAMPLE_POSIXMQ_RECV_FORK)nl()
|
||||
This feature is link(experimental)(option_experimental).nl()
|
||||
Useful options:
|
||||
link(posixmq-priority)(OPTION_POSIXMQ_PRIORITY),
|
||||
link(fork)(OPTION_FORK),
|
||||
link(max-children)(OPTION_MAX_CHILDREN),
|
||||
link(unlink-early)(OPTION_UNLINK_EARLY),
|
||||
link(unlink-close)(OPTION_UNLINK_CLOSE)
|
||||
link(unlink-close)(OPTION_UNLINK_CLOSE),
|
||||
link(o-creat)(OPTION_O_CREAT),
|
||||
link(o-excl)(OPTION_O_EXCL),
|
||||
link(umask)(OPTION_UMASK)
|
||||
|
||||
label(ADDRESS_POSIXMQ_SEND)dit(bf(tt(POSIXMQ-SEND:/<mqueue>)))
|
||||
Opens the specified POSIX message queue and writes messages (packets).nl()
|
||||
Opens or creates the specified POSIX message queue and writes messages
|
||||
(packets).nl()
|
||||
This is a write-only address. See link(POSIXMQ-READ)(ADDRESS_POSIXMQ_READ)
|
||||
for more info.nl()
|
||||
(link(Example)(EXAMPLE_POSIXMQ_SEND))nl()
|
||||
This feature is link(experimental)(option_experimental).nl()
|
||||
Useful options:
|
||||
link(posixmq-priority)(OPTION_POSIXMQ_PRIORITY),
|
||||
link(posixmq-flush)(OPTION_POSIXMQ_FLUSH),
|
||||
link(fork)(OPTION_FORK),
|
||||
link(max-children)(OPTION_MAX_CHILDREN),
|
||||
link(unlink-early)(OPTION_UNLINK_EARLY),
|
||||
link(unlink-close)(OPTION_UNLINK_CLOSE)
|
||||
link(unlink-close)(OPTION_UNLINK_CLOSE),
|
||||
link(o-creat)(OPTION_O_CREAT),
|
||||
link(o-excl)(OPTION_O_EXCL),
|
||||
link(umask)(OPTION_UMASK)
|
||||
|
||||
label(ADDRESS_POSIXMQ_WRITE)dit(bf(tt(POSIXMQ-WRITE:/<mqueue>)))
|
||||
Does the same as link(POSIXMQ-SEND)(ADDRESS_POSIXMQ_SEND).
|
||||
|
||||
label(ADDRESS_POSIXMQ_BIDIRECTIONAL)dit(bf(tt(POSIXMQ-BIDIRECTIONAL:/mqueue)))
|
||||
Opens the specified POSIX message queue and writes and reads messages
|
||||
(packet). This is probably rarely useful but has been implemented for
|
||||
functional completeness.
|
||||
dit(bf(tt(POSIXMQ:/mqueue)))
|
||||
Opens or creates the specified POSIX message queue in read and/or write mode
|
||||
depending on context, then reads and/or writes messages (packets).
|
||||
In bidirectional mode this is just another echo service.nl()
|
||||
See link(POSIXMQ-READ)(ADDRESS_POSIXMQ_READ) and
|
||||
link(POSIXMQ-SEND)(ADDRESS_POSIXMQ_SEND) for more info.
|
||||
|
||||
label(ADDRESS_PROXY_CONNECT)dit(bf(tt(PROXY:<proxy>:<hostname>:<port>)))
|
||||
Connects to an HTTP proxy server on port 8080 using TCP/IP version 4 or 6
|
||||
|
@ -882,7 +898,7 @@ label(ADDRESS_SCTP_CONNECT)dit(bf(tt(SCTP-CONNECT:<host>:<port>)))
|
|||
link(mtudiscover)(OPTION_MTUDISCOVER),
|
||||
link(sctp-maxseg)(OPTION_SCTP_MAXSEG),
|
||||
link(sctp-nodelay)(OPTION_SCTP_NODELAY),
|
||||
link(nonblock)(OPTION_NONBLOCK),
|
||||
link(nonblock)(OPTION_O_NONBLOCK),
|
||||
link(sourceport)(OPTION_SOURCEPORT),
|
||||
link(retry)(OPTION_RETRY),
|
||||
link(readbytes)(OPTION_READBYTES)nl()
|
||||
|
@ -1103,11 +1119,11 @@ label(ADDRESS_SOCKS4A)dit(bf(tt(SOCKS4A:<socks-server>:<host>:<port>)))
|
|||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(SOCKS4)(GROUP_SOCKS),link(RETRY)(GROUP_RETRY) nl()
|
||||
|
||||
label(ADDRESS_SOCKS5_CONNECT)dit(bf(tt(SOCKS5-CONNECT:<socks-server>:<socks-port>:<target-host>:<target-port>)))
|
||||
dit(bf(tt(SOCKS5-CONNECT:<socks-server>:<target-host>:<target-port>)))
|
||||
Connects via <socks-server> [link(IP address)(TYPE_IP_ADDRESS)]
|
||||
to <target-host> [link(IPv4 address)(TYPE_IPV4_ADDRESS)]
|
||||
on <target-port> [link(TCP service)(TYPE_TCP_SERVICE)],
|
||||
using socks version 5 protocol over TCP. Currently no authentication mechanism is provided.nl()
|
||||
This address type is experimental.nl()
|
||||
Option groups: link(FD)(GROUP_FD), link(SOCKET)(GROUP_SOCKET), link(IP4)(GROUP_IP4), link(IP6)(GROUP_IP6), link(TCP)(GROUP_TCP), link(CHILD)(GROUP_CHILD), link(RETRY)(GROUP_RETRY)nl()
|
||||
Useful options:
|
||||
link(socksport)(OPTION_SOCKSPORT),
|
||||
|
@ -1122,10 +1138,11 @@ label(ADDRESS_SOCKS5_CONNECT)dit(bf(tt(SOCKS5-CONNECT:<socks-server>:<socks-port
|
|||
link(TCP)(ADDRESS_TCP_CONNECT)
|
||||
|
||||
label(ADDRESS_SOCKS5_LISTEN)dit(bf(tt(SOCKS5-LISTEN:<socks-server>:<socks-port>:<listen-host>:<listen-port>)))
|
||||
dit(bf(tt(SOCKS5-LISTEN:<socks-server>:<listen-host>:<listen-port>)))
|
||||
Connects to <socks-server> [link(IP address)(TYPE_IP_ADDRESS)]
|
||||
using socks version 5 protocol over TCP
|
||||
and makes it listen for incoming connections on <listen-port> [link(TCP service)(TYPE_TCP_SERVICE)], binding to <-listen-host> [link(IPv4 address)(TYPE_IPV4_ADDRESS)]
|
||||
Currently not authentication mechanism is provided. This address type is experimental.
|
||||
Currently not authentication mechanism is provided.nl()
|
||||
Option groups: link(FD)(GROUP_FD), link(SOCKET)(GROUP_SOCKET), link(IP4)(GROUP_IP4), link(IP6)(GROUP_IP6), link(TCP)(GROUP_TCP), link(CHILD)(GROUP_CHILD), link(RETRY)(GROUP_RETRY)nl()
|
||||
Useful options:
|
||||
link(sourceport)(OPTION_SOURCEPORT),
|
||||
|
@ -1233,7 +1250,7 @@ label(ADDRESS_TCP_CONNECT)dit(bf(tt(TCP:<host>:<port>)))
|
|||
link(mtudiscover)(OPTION_MTUDISCOVER),
|
||||
link(mss)(OPTION_MSS),
|
||||
link(nodelay)(OPTION_TCP_NODELAY),
|
||||
link(nonblock)(OPTION_NONBLOCK),
|
||||
link(nonblock)(OPTION_O_NONBLOCK),
|
||||
link(readbytes)(OPTION_READBYTES)nl()
|
||||
See also:
|
||||
link(TCP4)(ADDRESS_TCP4_CONNECT),
|
||||
|
@ -1290,7 +1307,7 @@ label(ADDRESS_TCP6_LISTEN)dit(bf(tt(TCP6-LISTEN:<port>)))
|
|||
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 optionally assignes it the address and
|
||||
Creates a Linux TUN/TAP device and optionally assigns 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
|
||||
|
@ -1418,7 +1435,8 @@ label(ADDRESS_UDP_SENDTO)dit(bf(tt(UDP-SENDTO:<host>:<port>)))
|
|||
link(pf)(OPTION_PROTOCOL_FAMILY). It sends packets to and receives packets
|
||||
from that peer socket only.
|
||||
This address effectively implements a datagram client.
|
||||
It works well with socat UDP-RECVFROM and UDP-RECV address peers.nl()
|
||||
It works well with socat UDP-RECVFROM and UDP-RECV address peers.
|
||||
When the peer might send data first, link(UDP-DATAGRAM)(ADDRESS_UDP_DATAGRAM) is preferable.nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6) nl()
|
||||
Useful options:
|
||||
link(ttl)(OPTION_TTL),
|
||||
|
@ -1456,7 +1474,8 @@ label(ADDRESS_UDP_RECVFROM)dit(bf(tt(UDP-RECVFROM:<port>)))
|
|||
label(NOTE_RECVFROM)Note: When the second address fails before entering the transfer loop the
|
||||
packet is dropped. Use option link(retry)(OPTION_RETRY) or
|
||||
link(forever)(OPTION_FOREVER) on the second address to avoid data loss.
|
||||
nl()
|
||||
When you know the peer address, link(UDP-DATAGRAM)(ADDRESS_UDP_DATAGRAM) is
|
||||
preferable.nl()
|
||||
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE) nl()
|
||||
Useful options:
|
||||
link(fork)(OPTION_FORK),
|
||||
|
@ -1839,8 +1858,10 @@ label(OPTION_MODE)dit(bf(tt(mode=<mode>)))
|
|||
system calls, socat() uses the code(chmod()) system call after opening the
|
||||
filesystem entry or binding to the unixdomain() socket (race condition!).
|
||||
Otherwise, socat() sets the mode of the stream
|
||||
using code(fchmod()).
|
||||
These calls might require ownership or root privilege.
|
||||
using code(fchmod()) which, btw, might not have any effect.nl()
|
||||
These calls might require ownership or root privilege.nl()
|
||||
Note: this option can only tighten the permissions implied by processes
|
||||
umask. See option link(umask)(OPTION_UMASK) to loosen permissions.
|
||||
label(OPTION_PERM_LATE)dit(bf(tt(perm-late=<mode>)))
|
||||
Sets the permissions of the fd to value <mode>
|
||||
[link(mode_t)(TYPE_MODE_T)] using the code(fchmod()) system call after
|
||||
|
@ -1852,7 +1873,7 @@ label(OPTION_APPEND)dit(bf(tt(append[=<bool>])))
|
|||
socat() uses the code(O_APPEND) flag with the code(open()) system call
|
||||
(link(example)(EXAMPLE_OPTION_APPEND)).
|
||||
Otherwise, socat() applies the code(fcntl(fd, F_SETFL, O_APPEND)) call.
|
||||
label(OPTION_NONBLOCK)dit(bf(tt(nonblock[=<bool>])))
|
||||
label(OPTION_O_NONBLOCK)dit(bf(tt(nonblock[=<bool>])))
|
||||
Tries to open or use file in nonblocking mode. Its only effects are that the
|
||||
code(connect()) call of TCP addresses does not block, and that opening a
|
||||
named pipe for reading does not block.
|
||||
|
@ -1987,13 +2008,13 @@ E.g., option `creat' sets the code(O_CREAT) flag. When the used address does
|
|||
not use code(open()) (e.g.STDIO), the code(fcntl(..., F_SETFL, ...)) call is
|
||||
used instead.nl()
|
||||
See also options link(append)(OPTION_APPEND) and
|
||||
link(nonblock)(OPTION_NONBLOCK).
|
||||
link(nonblock)(OPTION_O_NONBLOCK).
|
||||
startdit()
|
||||
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.
|
||||
label(OPTION_EXCL)dit(bf(tt(excl[=<bool>])))
|
||||
label(OPTION_O_EXCL)dit(bf(tt(excl[=<bool>])))
|
||||
With option creat, if file exists this is an error.
|
||||
label(OPTION_LARGEFILE)dit(bf(tt(largefile[=<bool>])))
|
||||
On 32 bit systems, allows a file larger than 2^31 bytes.
|
||||
|
@ -2108,8 +2129,9 @@ label(OPTION_CHDIR)dit(bf(tt(chdir=<filename>))) dit(bf(tt(cd=<filename>)))
|
|||
label(OPTION_UMASK)dit(bf(tt(umask=<mode>)))
|
||||
Sets the umask of the process to <mode> [link(mode_t)(TYPE_MODE_T)] before
|
||||
opening the address. Useful when file system entries are created or a shell
|
||||
or program is invoked. Usually the value is specified as octal number.nl()
|
||||
The processes tt(umask) value is inherited by child processes.
|
||||
or program is invoked. Usually the value is specified as octal number with
|
||||
leading '0'.nl()
|
||||
The processes tt(umask) value is inherited by child processes.nl()
|
||||
Note: umask is an inverted value: creating a file with umask=0026 results in
|
||||
permissions 0640.
|
||||
enddit()
|
||||
|
@ -2136,7 +2158,7 @@ label(OPTION_SETGID)dit(bf(tt(setgid=<group>)))
|
|||
processing the address. This call might require root privilege. Please note
|
||||
that this option does not drop other group related privileges.
|
||||
label(OPTION_SETGID_EARLY)dit(bf(tt(setgid-early=<group>)))
|
||||
Like link(setgit)(OPTION_SETGID) but is performed before opening the address.
|
||||
Like link(setgid)(OPTION_SETGID) but is performed before opening the address.
|
||||
label(OPTION_SETUID)dit(bf(tt(setuid=<user>)))
|
||||
Changes the link(<user>)(TYPE_USER) (owner) of the process after processing
|
||||
the address. This call might require root privilege. Please note that this
|
||||
|
@ -2164,9 +2186,9 @@ label(OPTION_SETSID)dit(bf(tt(setsid)))
|
|||
Makes the process the leader of a new session (link(example)(EXAMPLE_OPTION_SETSID)).
|
||||
label(OPTION_NETNS)dit(bf(tt(netns=<net-namespace-name>)))
|
||||
Before opening the address it tries to switch to the named network namespace.
|
||||
After opening the address it switches back to the previous namespace.
|
||||
(link(Example with TCP forwarder)(EXAMPLE_OPTION_NETNS),
|
||||
link(example with virtual network connection)(EXAMPLE_TUN_NETNS).nl()
|
||||
After opening the address it switches back to the previous namespace
|
||||
(link(example with TCP forwarder)(EXAMPLE_OPTION_NETNS),
|
||||
link(example with virtual network connection)(EXAMPLE_TUN_NETNS)).nl()
|
||||
Only on Linux; requires root; use option tt(--experimental).nl()
|
||||
enddit()
|
||||
|
||||
|
@ -2189,7 +2211,7 @@ label(OPTION_NOECHO)dit(bf(tt(noecho=<pattern>)))
|
|||
Specifies a regular pattern for a prompt that prevents the following input
|
||||
line from being displayed on the screen and from being added to the history.
|
||||
The prompt is defined as the text that was output to the readline address
|
||||
after the lastest newline character and before an input character was
|
||||
after the last newline character and before an input character was
|
||||
typed. The pattern is a regular expression, e.g.
|
||||
"^[Pp]assword:.*$" or "([Uu]ser:|[Pp]assword:)". See NOEXPAND(regex(7)) for details.
|
||||
(link(example)(EXAMPLE_OPTION_NOECHO))
|
||||
|
@ -2368,7 +2390,7 @@ COMMENT(label(OPTION_SECURITYENCRYPTIONNETWORK)dit(bf(tt(securityencryptionnetwo
|
|||
COMMENT(label(OPTION_SECURITYENCRYPTIONTRANSPORT)dit(bf(tt(securityencryptiontransport)))
|
||||
Set the code(SO_SECURITY_ENCRYPTION_TRANSPORT) socket option.)
|
||||
COMMENT(label(OPTION_SIOCSPGRP)dit(bf(tt(siocspgrp=<pid_t>)))
|
||||
Set the SIOCSPGRP with code(ioclt()) to enable SIGIO.)
|
||||
Set the SIOCSPGRP with code(ioctl()) to enable SIGIO.)
|
||||
COMMENT(label(OPTION_USEIFBUFS)dit(bf(tt(useifbufs)))
|
||||
Set the code(SO_USE_IFBUFS) socket option.)
|
||||
label(OPTION_SO_TIMESTAMP)dit(bf(tt(so-timestamp)))
|
||||
|
@ -2394,6 +2416,12 @@ label(OPTION_SETSOCKOPT_STRING)dit(bf(tt(setsockopt-string=<level>:<optname>:<op
|
|||
Like tt(setsockopt), but <optval> is a link(string)(TYPE_STRING).
|
||||
This string is passed to the function with trailing null character, and the
|
||||
length parameter is automatically derived from the data.
|
||||
label(OPTION_SETSOCKOPT_SOCKET)dit(bf(tt(setsockopt-socket=<level>:<optname>:<optval>)))
|
||||
Like tt(setsockopt), but is applied to the socket before other operations
|
||||
(code(bind()), code(connect()), code(accept()), ...)
|
||||
label(OPTION_SETSOCKOPT_CONNECTED)dit(bf(tt(setsockopt-connected=<level>:<optname>:<optval>)))
|
||||
Like tt(setsockopt), but is applied only when the socket has been connected
|
||||
by a code(connect()) or code(listen()) call.
|
||||
enddit()
|
||||
|
||||
startdit()enddit()nl()
|
||||
|
@ -2525,7 +2553,8 @@ dit(bf(tt(ipv6-join-source-group=<multicast-address:interface-index:source-addre
|
|||
IPv4 variant. The option takes the IP address of the multicast group,
|
||||
info about the desired network interface and the source IP address of the
|
||||
multicast traffic. The indices of active network interfaces can be shown
|
||||
using the utility procan().
|
||||
using the utility procan().nl()
|
||||
This feature is experimental.
|
||||
label(OPTION_IP_MULTICAST_IF)
|
||||
dit(bf(tt(ip-multicast-if=<hostname>)))
|
||||
Specifies hostname or address of the network interface to be used for
|
||||
|
@ -2976,6 +3005,8 @@ label(OPTION_NOFORK)dit(bf(tt(nofork)))
|
|||
it() the first socat address cannot be OPENSSL or READLINE
|
||||
it() socat options -b, -t, -D, -l, -v, -x become useless
|
||||
it() for both addresses, options ignoreeof, cr, and crnl become useless
|
||||
it() for both addresses, address specific end/shutdown handling (e.g.,
|
||||
graceful socket shutdown) and related options become useless
|
||||
it() for the second address (the one with option nofork), options
|
||||
append, metaCOMMENT(async,) cloexec, flock, user, group, mode, nonblock,
|
||||
perm-late, setlk, and setpgid cannot be applied. Some of these could be
|
||||
|
@ -3345,7 +3376,7 @@ label(OPTION_OPENSSL_PSEUDO)dit(bf(tt(pseudo)))
|
|||
gathering daemon can be utilized, this option activates a mechanism for
|
||||
providing pseudo entropy. This is achieved by taking the current time in
|
||||
microseconds for feeding the libc pseudo random number generator with an
|
||||
initial value. openssl is then feeded with output from NOEXPAND(random()) calls.nl()
|
||||
initial value. openssl is then fed with output from NOEXPAND(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
|
||||
|
@ -3490,6 +3521,15 @@ startdit()
|
|||
label(OPTION_POSIXMQ_PRIORITY)dit(bf(tt(posixmq-priority (mq-prio))))
|
||||
Sets the priority of messages (packets) written to the queue, or the minimal
|
||||
priority of packet read from the queue.
|
||||
label(OPTION_POSIXMQ_FLUSH)dit(bf(tt(posixmq-flush (mq-flush))))
|
||||
"Consumes" (drops) all messages currently in the queue before starting
|
||||
transfers.
|
||||
label(OPTION_POSIXMQ_MAXMSG)dit(bf(tt(posixmq-maxmsg (mq-maxmsg))))
|
||||
Sets the maxmsg parameter of the POSIX message queue when creating it.nl()
|
||||
Note: This option applies only when the queue does not already exist.
|
||||
label(OPTION_POSIXMQ_MSGSIZE)dit(bf(tt(posixmq-msgsize (mq-msgsize))))
|
||||
Sets the msgsize parameter of the POSIX message queue when creating it.nl()
|
||||
Note: This option applies only when the queue does not already exist.
|
||||
enddit()
|
||||
|
||||
|
||||
|
@ -3512,7 +3552,8 @@ label(TYPE_COMMAND_LINE)dit(command-line)
|
|||
A string specifying a program name and its arguments, separated by single
|
||||
spaces.
|
||||
label(TYPE_DATA)dit(data)
|
||||
This is a more general data specification. The given text string contains
|
||||
This is a more general data specification, "dalan" (low level data
|
||||
description language). The given text string contains
|
||||
information about the target data type and value. Generally a leading
|
||||
character specifies the type of the following data item. In its specific
|
||||
context a default data type may exist.nl()
|
||||
|
@ -3528,12 +3569,12 @@ label(TYPE_DATA)dit(data)
|
|||
dit(b) A signed byte (signed char).nl()
|
||||
dit(B) An unsigned byte (unsigned char).nl()
|
||||
dit(x) Following is an even number of hex digits, stored as sequence of
|
||||
bytes.nl()
|
||||
bytes, the data length is the resulting number of bytes.nl()
|
||||
Example: bf(x7f000001) (IP address 127.0.0.1)
|
||||
dit(") Following is a string that is used with the common conversions
|
||||
\n \r \t \f \b \a \e \0; the string must be closed with '"'. Please note
|
||||
that the quotes and backslashes need to be escaped from shell and socat()
|
||||
conversion.nl()
|
||||
conversion. No implicit \0 is appended.nl()
|
||||
Example: bf("Hello world!\n")
|
||||
dit(') A single char, with the usual conversions. Please note that the
|
||||
quotes and backslashes need to be escaped from shell and socat() conversion.
|
||||
|
@ -3581,10 +3622,10 @@ label(TYPE_LONG)dit(long)
|
|||
label(TYPE_LONGLONG)dit(long long)
|
||||
A number read with code(strtoll()). The value must fit into a C long long.
|
||||
label(TYPE_OFF)dit(off_t)
|
||||
An implementation dependend signed number, usually 32 bits, read with strtol
|
||||
An implementation dependent signed number, usually 32 bits, read with strtol
|
||||
or strtoll.
|
||||
label(TYPE_OFF64)dit(off64_t)
|
||||
An implementation dependend signed number, usually 64 bits, read with strtol
|
||||
An implementation dependent signed number, usually 64 bits, read with strtol
|
||||
or strtoll.
|
||||
label(TYPE_MODE_T)dit(mode_t)
|
||||
An unsigned integer, read with code(strtoul()), specifying mode (permission)
|
||||
|
@ -3972,7 +4013,7 @@ prompts.
|
|||
label(EXAMPLE_ADDRESS_PTY)
|
||||
label(EXAMPLE_OPTION_SYMBOLIC_LINK)
|
||||
label(EXAMPLE_OPTION_WAIT_SLAVE)
|
||||
label(EXAMPLE_OPTION_NONBLOCK)
|
||||
label(EXAMPLE_OPTION_O_NONBLOCK)
|
||||
mancommand(\.LP)
|
||||
mancommand(\.nf)
|
||||
mancommand(\fBsocat \\)
|
||||
|
@ -4445,14 +4486,14 @@ both devices. Use pppd on device tt(/var/run/ppp) then.
|
|||
label(EXAMPLE_POSIXMQ_SEND)
|
||||
mancommand(\.LP)
|
||||
mancommand(\.nf)
|
||||
mancommand(\fBsocat --experimental -u \\)
|
||||
mancommand(\fBsocat -u \\)
|
||||
mancommand(\.RS)
|
||||
mancommand(\fBSTDIO \\
|
||||
POSIXMQ-SEND:/queue1,unlink-early,mq-prio=10\fP)
|
||||
mancommand(\.RE)
|
||||
mancommand(\.fi)
|
||||
|
||||
htmlcommand(<hr><div class="shell">socat --experimental -u \
|
||||
htmlcommand(<hr><div class="shell">socat -u \
|
||||
STDIO \
|
||||
POSIXMQ-SEND:/queue1,unlink-early,mq-prio=10</div>)
|
||||
|
||||
|
@ -4464,7 +4505,7 @@ label(EXAMPLE_POSIXMQ_RECV_FORK)
|
|||
|
||||
mancommand(\.LP)
|
||||
mancommand(\.nf)
|
||||
mancommand(\fBsocat --experimental -u \\)
|
||||
mancommand(\fBsocat -u \\)
|
||||
mancommand(\.RS)
|
||||
mancommand(\fBPOSIXMQ-RECV:/queue1,fork,max-children=3 \\
|
||||
SYSTEM:"worker.sh"\fP)
|
||||
|
@ -4472,7 +4513,7 @@ mancommand(\fBPOSIXMQ-RECV:/queue1,fork,max-children=3 \\
|
|||
mancommand(\.RE)
|
||||
mancommand(\.fi)
|
||||
|
||||
htmlcommand(<hr><div class="shell">socat --experimental -u \
|
||||
htmlcommand(<hr><div class="shell">socat -u \
|
||||
POSIXMQ-RECV:/queue1,fork,max-children=3 \
|
||||
SYSTEM:"worker.sh"</div>)
|
||||
|
||||
|
|
2
error.h
2
error.h
|
@ -183,7 +183,7 @@
|
|||
#define Debug18(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18)
|
||||
#endif /* !(WITH_MSGLEVEL <= E_DEBUG) */
|
||||
|
||||
/* message with software controlled serverity */
|
||||
/* message with software controlled severity */
|
||||
#if WITH_MSGLEVEL <= E_FATAL
|
||||
#define Msg(l,m) msg(l,"%s",m)
|
||||
#define Msg1(l,m,a1) msg(l,m,a1)
|
||||
|
|
4
fdname.c
4
fdname.c
|
@ -226,7 +226,7 @@ int sockname(int fd, FILE *outfile, char style) {
|
|||
#define FDNAME_OPTLEN 256
|
||||
#define FDNAME_NAMELEN 256
|
||||
socklen_t optlen;
|
||||
#if HAVE_GETPROTOBYNUMBER || HAVE_GETPROTOBYNUMBER_R
|
||||
#if (WITH_IP4 || WITH_IP6) && ( HAVE_GETPROTOBYNUMBER || HAVE_GETPROTOBYNUMBER_R )
|
||||
struct protoent protoent, *protoentp;
|
||||
#endif
|
||||
#define PROTONAMEMAX 1024
|
||||
|
@ -278,7 +278,7 @@ int sockname(int fd, FILE *outfile, char style) {
|
|||
Getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &optacceptconn, &optlen);
|
||||
#endif
|
||||
|
||||
#if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)
|
||||
#if (WITH_IP4 || WITH_IP6) && ( defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) )
|
||||
#if HAVE_GETPROTOBYNUMBER_R==1 /* Linux */
|
||||
rc = getprotobynumber_r(proto, &protoent, protoname, sizeof(protoname), &protoentp);
|
||||
if (protoentp == NULL) {
|
||||
|
|
10
filan.c
10
filan.c
|
@ -393,7 +393,7 @@ int filan_stat(
|
|||
break;
|
||||
#ifdef S_IFLNK
|
||||
case (S_IFLNK): /* 10, symbolic link */
|
||||
/* we wait for freadlink() sytem call */
|
||||
/* we wait for freadlink() system call */
|
||||
break;
|
||||
#endif /* S_IFLNK */
|
||||
break;
|
||||
|
@ -804,13 +804,13 @@ int ipan(int fd, FILE *outfile) {
|
|||
}
|
||||
/* want to pass the fd to the next layer protocol. */
|
||||
#if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)
|
||||
if (Getsockopt(fd, SOL_SOCKET,
|
||||
if (
|
||||
#ifdef SO_PROTOCOL
|
||||
SO_PROTOCOL,
|
||||
Getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &optproto, &optlen)
|
||||
#elif defined(SO_PROTOTYPE)
|
||||
SO_PROTOTYPE,
|
||||
Getsockopt(fd, SOL_SOCKET, SO_PROTOTYPE, &optproto, &optlen)
|
||||
#endif
|
||||
&optproto, &optlen) >= 0) {
|
||||
>= 0) {
|
||||
switch (optproto) {
|
||||
#if WITH_TCP
|
||||
case IPPROTO_TCP: tcpan(fd, outfile); break;
|
||||
|
|
|
@ -167,7 +167,7 @@ int main(int argc, const char *argv[]) {
|
|||
Nanosleep(&waittime, NULL);
|
||||
|
||||
if (style == 0) {
|
||||
/* this style gives detailled infos, but requires a file descriptor */
|
||||
/* This style gives detailed infos, but requires a file descriptor */
|
||||
if (filename) {
|
||||
#if LATER /* this is just in case that S_ISSOCK does not work */
|
||||
struct stat buf;
|
||||
|
|
5
hostan.c
5
hostan.c
|
@ -33,6 +33,11 @@ int hostan(FILE *outfile) {
|
|||
#endif
|
||||
fprintf(outfile, "sizeof(size_t) = %u\n", (unsigned int)sizeof(size_t));
|
||||
|
||||
if ((char)-1 > 0)
|
||||
fprintf(outfile, "typedef unsigned char char;\n");
|
||||
else
|
||||
fprintf(outfile, "typedef signed char char;\n");
|
||||
|
||||
# if HAVE_BASIC_SIZE_T==2
|
||||
fprintf(outfile, "typedef unsigned short size_t; /* sizeof(size_t) = %u */\n", (unsigned int)sizeof(size_t));
|
||||
#elif HAVE_BASIC_SIZE_T==4
|
||||
|
|
176
procan-cdefs.c
176
procan-cdefs.c
|
@ -15,30 +15,91 @@
|
|||
#include "procan.h"
|
||||
|
||||
int procan_cdefs(FILE *outfile) {
|
||||
/* basic C/system constants */
|
||||
/* System constants */
|
||||
#ifdef __KERNEL__
|
||||
fprintf(outfile, "__KERNEL__ = \"%s\"\n", __KERNEL__);
|
||||
#endif
|
||||
#ifdef __GLIBC__
|
||||
fprintf(outfile, "__GLIBC__ = %d\n", __GLIBC__);
|
||||
#endif
|
||||
/* Basic C/system constants */
|
||||
#ifdef FD_SETSIZE
|
||||
fprintf(outfile, "#define FD_SETSIZE %u\n", FD_SETSIZE);
|
||||
fprintf(outfile, "#define FD_SETSIZE %u\n", FD_SETSIZE);
|
||||
#endif
|
||||
#ifdef NFDBITS
|
||||
fprintf(outfile, "#define NFDBITS %d\n", (int)NFDBITS);
|
||||
fprintf(outfile, "#define NFDBITS %d\n", (int)NFDBITS);
|
||||
#endif
|
||||
#ifdef O_RDONLY
|
||||
fprintf(outfile, "#define O_RDONLY %u\n", O_RDONLY);
|
||||
fprintf(outfile, "#define O_RDONLY %u\n", O_RDONLY);
|
||||
#endif
|
||||
#ifdef O_WRONLY
|
||||
fprintf(outfile, "#define O_WRONLY %u\n", O_WRONLY);
|
||||
fprintf(outfile, "#define O_WRONLY %u\n", O_WRONLY);
|
||||
#endif
|
||||
#ifdef O_RDWR
|
||||
fprintf(outfile, "#define O_RDWR %u\n", O_RDWR);
|
||||
fprintf(outfile, "#define O_RDWR %u\n", O_RDWR);
|
||||
#endif
|
||||
#ifdef O_CREAT
|
||||
fprintf(outfile, "#define O_CREAT 0x%06x /* 0%08o */\n", O_CREAT, O_CREAT);
|
||||
#endif
|
||||
#ifdef O_EXCL
|
||||
fprintf(outfile, "#define O_EXCL 0x%06x /* 0%08o */\n", O_EXCL, O_EXCL);
|
||||
#endif
|
||||
#ifdef O_NOCTTY
|
||||
fprintf(outfile, "#define O_NOCTTY 0x%06x /* 0%08o */\n", O_NOCTTY, O_NOCTTY);
|
||||
#endif
|
||||
#ifdef O_TRUNC
|
||||
fprintf(outfile, "#define O_TRUNC 0x%06x /* 0%08o */\n", O_TRUNC, O_TRUNC);
|
||||
#endif
|
||||
#ifdef O_APPEND
|
||||
fprintf(outfile, "#define O_APPEND 0x%06x /* 0%08o */\n", O_APPEND, O_APPEND);
|
||||
#endif
|
||||
#ifdef O_NONBLOCK
|
||||
fprintf(outfile, "#define O_NONBLOCK 0x%06x /* 0%08o */\n", O_NONBLOCK, O_NONBLOCK);
|
||||
#endif
|
||||
#ifdef O_NDELAY
|
||||
fprintf(outfile, "#define O_NDELAY 0x%06x /* 0%08o */\n", O_NDELAY, O_NDELAY);
|
||||
#endif
|
||||
#ifdef O_SYNC
|
||||
fprintf(outfile, "#define O_SYNC 0x%06x /* 0%08o */\n", O_SYNC, O_SYNC);
|
||||
#endif
|
||||
#ifdef O_FSYNC
|
||||
fprintf(outfile, "#define O_FSYNC 0x%06x /* 0%08o */\n", O_FSYNC, O_FSYNC);
|
||||
#endif
|
||||
#ifdef O_LARGEFILE
|
||||
fprintf(outfile, "#define O_LARGEFILE 0x%06x /* 0%08o */\n", O_LARGEFILE, O_LARGEFILE);
|
||||
#endif
|
||||
#ifdef O_DIRECTORY
|
||||
fprintf(outfile, "#define O_DIRECTORY 0x%06x /* 0%08o */\n", O_DIRECTORY, O_DIRECTORY);
|
||||
#endif
|
||||
#ifdef O_NOFOLLOW
|
||||
fprintf(outfile, "#define O_NOFOLLOW 0x%06x /* 0%08o */\n", O_NOFOLLOW, O_NOFOLLOW);
|
||||
#endif
|
||||
#ifdef O_CLOEXEC
|
||||
fprintf(outfile, "#define O_CLOEXEC 0x%06x /* 0%08o */\n", O_CLOEXEC, O_CLOEXEC);
|
||||
#endif
|
||||
#ifdef O_DIRECT
|
||||
fprintf(outfile, "#define O_DIRECT 0x%06x /* 0%08o */\n", O_DIRECT, O_DIRECT);
|
||||
#endif
|
||||
#ifdef O_NOATIME
|
||||
fprintf(outfile, "#define O_NOATIME 0x%06x /* 0%08o */\n", O_NOATIME, O_NOATIME);
|
||||
#endif
|
||||
#ifdef O_PATH
|
||||
fprintf(outfile, "#define O_PATH 0x%06x /* 0%08o */\n", O_PATH, O_PATH);
|
||||
#endif
|
||||
#ifdef O_DSYNC
|
||||
fprintf(outfile, "#define O_DSYNC 0x%06x /* 0%08o */\n", O_SYNC, O_SYNC);
|
||||
#endif
|
||||
#ifdef O_TMPFILE
|
||||
fprintf(outfile, "#define O_TMPFILE 0x%06x /* 0%08o */\n", O_TMPFILE, O_TMPFILE);
|
||||
#endif
|
||||
#ifdef SHUT_RD
|
||||
fprintf(outfile, "#define SHUT_RD %u\n", SHUT_RD);
|
||||
fprintf(outfile, "#define SHUT_RD %u\n", SHUT_RD);
|
||||
#endif
|
||||
#ifdef SHUT_WR
|
||||
fprintf(outfile, "#define SHUT_WR %u\n", SHUT_WR);
|
||||
fprintf(outfile, "#define SHUT_WR %u\n", SHUT_WR);
|
||||
#endif
|
||||
#ifdef SHUT_RDWR
|
||||
fprintf(outfile, "#define SHUT_RDWR %u\n", SHUT_RDWR);
|
||||
fprintf(outfile, "#define SHUT_RDWR %u\n", SHUT_RDWR);
|
||||
#endif
|
||||
|
||||
/* Compile time controls */
|
||||
|
@ -51,40 +112,40 @@ int procan_cdefs(FILE *outfile) {
|
|||
|
||||
/* termios constants */
|
||||
#ifdef CRDLY
|
||||
fprintf(outfile, "#define CRDLY 0%011o\n", CRDLY);
|
||||
fprintf(outfile, "#define CRDLY 0x%08x /* 0%011o */\n", CRDLY, CRDLY);
|
||||
#endif
|
||||
#ifdef CR0
|
||||
fprintf(outfile, "#define CR0 0%011o\n", CR0);
|
||||
fprintf(outfile, "#define CR0 0x%08x /* 0%011o */\n", CR0, CR0);
|
||||
#endif
|
||||
#ifdef CR1
|
||||
fprintf(outfile, "#define CR1 0%011o\n", CR1);
|
||||
fprintf(outfile, "#define CR1 0x%08x /* 0%011o */\n", CR1, CR1);
|
||||
#endif
|
||||
#ifdef CR2
|
||||
fprintf(outfile, "#define CR2 0%011o\n", CR2);
|
||||
fprintf(outfile, "#define CR2 0x%08x /* 0%011o */\n", CR2, CR2);
|
||||
#endif
|
||||
#ifdef CR3
|
||||
fprintf(outfile, "#define CR3 0%011o\n", CR3);
|
||||
fprintf(outfile, "#define CR3 0x%08x /* 0%011o */\n", CR3, CR3);
|
||||
#endif
|
||||
#ifdef TABDLY
|
||||
fprintf(outfile, "#define TABDLY 0%011o\n", TABDLY);
|
||||
fprintf(outfile, "#define TABDLY 0x%08x /* 0%011o */\n", TABDLY, TABDLY);
|
||||
#endif
|
||||
#ifdef TAB0
|
||||
fprintf(outfile, "#define TAB0 0%011o\n", TAB0);
|
||||
fprintf(outfile, "#define TAB0 0x%08x /* 0%011o */\n", TAB0, TAB0);
|
||||
#endif
|
||||
#ifdef TAB1
|
||||
fprintf(outfile, "#define TAB1 0%011o\n", TAB1);
|
||||
fprintf(outfile, "#define TAB1 0x%08x /* 0%011o */\n", TAB1, TAB1);
|
||||
#endif
|
||||
#ifdef TAB2
|
||||
fprintf(outfile, "#define TAB2 0%011o\n", TAB2);
|
||||
fprintf(outfile, "#define TAB2 0x%08x /* 0%011o */\n", TAB2, TAB2);
|
||||
#endif
|
||||
#ifdef TAB3
|
||||
fprintf(outfile, "#define TAB3 0%011o\n", TAB3);
|
||||
fprintf(outfile, "#define TAB3 0x%08x /* 0%011o */\n", TAB3, TAB3);
|
||||
#endif
|
||||
#ifdef CSIZE
|
||||
fprintf(outfile, "#define CSIZE 0%011o\n", CSIZE);
|
||||
fprintf(outfile, "#define CSIZE 0x%08x /* 0%011o */\n", CSIZE, CSIZE);
|
||||
#endif
|
||||
#ifdef TIOCEXCL
|
||||
fprintf(outfile, "#define TIOCEXCL 0x%lx\n", (unsigned long)TIOCEXCL);
|
||||
fprintf(outfile, "#define TIOCEXCL 0x%lx\n", (unsigned long)TIOCEXCL);
|
||||
#endif
|
||||
|
||||
/* stdio constants */
|
||||
|
@ -188,5 +249,78 @@ int procan_cdefs(FILE *outfile) {
|
|||
#ifdef TCP_MAXSEG
|
||||
fprintf(outfile, "#define TCP_MAXSEG %d\n", TCP_MAXSEG);
|
||||
#endif
|
||||
#ifdef AI_PASSIVE
|
||||
fprintf(outfile, "#define AI_PASSIVE 0x%02x\n", AI_PASSIVE);
|
||||
#endif
|
||||
#ifdef AI_CANONNAME
|
||||
fprintf(outfile, "#define AI_CANONNAME 0x%02x\n", AI_CANONNAME);
|
||||
#endif
|
||||
#ifdef AI_NUMERICHOST
|
||||
fprintf(outfile, "#define AI_NUMERICHOST 0x%02x\n", AI_NUMERICHOST);
|
||||
#endif
|
||||
#ifdef AI_V4MAPPED
|
||||
fprintf(outfile, "#define AI_V4MAPPED 0x%02x\n", AI_V4MAPPED);
|
||||
#endif
|
||||
#ifdef AI_ALL
|
||||
fprintf(outfile, "#define AI_ALL 0x%02x\n", AI_ALL);
|
||||
#endif
|
||||
#ifdef AI_ADDRCONFIG
|
||||
fprintf(outfile, "#define AI_ADDRCONFIG 0x%02x\n", AI_ADDRCONFIG);
|
||||
#endif
|
||||
#ifdef EAI_BADFLAGS
|
||||
fprintf(outfile, "#define EAI_BADFLAGS %d\n", EAI_BADFLAGS);
|
||||
#endif
|
||||
#ifdef EAI_NONAME
|
||||
fprintf(outfile, "#define EAI_NONAME %d\n", EAI_NONAME);
|
||||
#endif
|
||||
#ifdef EAI_AGAIN
|
||||
fprintf(outfile, "#define EAI_AGAIN %d\n", EAI_AGAIN);
|
||||
#endif
|
||||
#ifdef EAI_FAIL
|
||||
fprintf(outfile, "#define EAI_FAIL %d\n", EAI_FAIL);
|
||||
#endif
|
||||
#ifdef EAI_FAMILY
|
||||
fprintf(outfile, "#define EAI_FAMILY %d\n", EAI_FAMILY);
|
||||
#endif
|
||||
#ifdef EAI_SOCKTYPE
|
||||
fprintf(outfile, "#define EAI_SOCKTYPE %d\n", EAI_SOCKTYPE);
|
||||
#endif
|
||||
#ifdef EAI_SERVICE
|
||||
fprintf(outfile, "#define EAI_SERVICE %d\n", EAI_SERVICE);
|
||||
#endif
|
||||
#ifdef EAI_MEMORY
|
||||
fprintf(outfile, "#define EAI_MEMORY %d\n", EAI_MEMORY);
|
||||
#endif
|
||||
#ifdef EAI_SYSTEM
|
||||
fprintf(outfile, "#define EAI_SYSTEM %d\n", EAI_SYSTEM);
|
||||
#endif
|
||||
#ifdef EAI_OVERFLOW
|
||||
fprintf(outfile, "#define EAI_OVERFLOW %d\n", EAI_OVERFLOW);
|
||||
#endif
|
||||
#ifdef EAI_NODATA
|
||||
fprintf(outfile, "#define EAI_NODATA %d\n", EAI_NODATA);
|
||||
#endif
|
||||
#ifdef EAI_ADDRFAMILY
|
||||
fprintf(outfile, "#define EAI_ADDRFAMILY %d\n", EAI_ADDRFAMILY);
|
||||
#endif
|
||||
#ifdef EAI_INPROGRESS
|
||||
fprintf(outfile, "#define EAI_INPROGRESS %d\n", EAI_INPROGRESS);
|
||||
#endif
|
||||
#ifdef EAI_CANCELED
|
||||
fprintf(outfile, "#define EAI_CANCELED %d\n", EAI_CANCELED);
|
||||
#endif
|
||||
#ifdef EAI_NOTCANCELED
|
||||
fprintf(outfile, "#define EAI_NOTCANCELED %d\n", EAI_NOTCANCELED);
|
||||
#endif
|
||||
#ifdef EAI_ALLDONE
|
||||
fprintf(outfile, "#define EAI_ALLDONE %d\n", EAI_ALLDONE);
|
||||
#endif
|
||||
#ifdef EAI_INTR
|
||||
fprintf(outfile, "#define EAI_INTR %d\n", EAI_INTR);
|
||||
#endif
|
||||
#ifdef EAI_IDN_ENCODE
|
||||
fprintf(outfile, "#define EAI_IDN_ENCODE %d\n", EAI_IDN_ENCODE);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
20
procan.c
20
procan.c
|
@ -187,10 +187,30 @@ int procan(FILE *outfile) {
|
|||
fprintf(outfile, "process group id if fg process / stderr = "F_pid"\n", Tcgetpgrp(2));
|
||||
|
||||
/* process owner, groups */
|
||||
#if HAVE_GETRESUID
|
||||
{
|
||||
uid_t ruid, euid, suid;
|
||||
getresuid(&ruid, &euid, &suid);
|
||||
fprintf(outfile, "user id = "F_uid"\n", ruid);
|
||||
fprintf(outfile, "effective user id = "F_uid"\n", euid);
|
||||
fprintf(outfile, "saved set-user id = "F_uid"\n", suid);
|
||||
}
|
||||
#else /* !HAVE_GETRESUID */
|
||||
fprintf(outfile, "user id = "F_uid"\n", Getuid());
|
||||
fprintf(outfile, "effective user id = "F_uid"\n", Geteuid());
|
||||
#endif /* !HAVE_GETRESUID */
|
||||
#if HAVE_GETRESGID
|
||||
{
|
||||
gid_t rgid, egid, sgid;
|
||||
getresgid(&rgid, &egid, &sgid);
|
||||
fprintf(outfile, "group id = "F_gid"\n", rgid);
|
||||
fprintf(outfile, "effective group id = "F_gid"\n", egid);
|
||||
fprintf(outfile, "saved set-group id = "F_gid"\n", sgid);
|
||||
}
|
||||
#else /* !HAVE_GETRESGID */
|
||||
fprintf(outfile, "group id = "F_gid"\n", Getgid());
|
||||
fprintf(outfile, "effective group id = "F_gid"\n", Getegid());
|
||||
#endif /* !HAVE_GETRESGID */
|
||||
|
||||
/* Simple process features */
|
||||
fprintf(outfile, "\n");
|
||||
|
|
|
@ -13,6 +13,9 @@ const char copyright[] = "procan by Gerhard Rieger and contributors - send bug r
|
|||
#if HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h> /* select(), fdset on FreeBSD */
|
||||
#endif
|
||||
#if HAVE_SYS_UTSNAME_H
|
||||
#include <sys/utsname.h> /* uname(), struct utsname */
|
||||
#endif
|
||||
#include "mytypes.h"
|
||||
#include "error.h"
|
||||
#include "procan.h"
|
||||
|
@ -22,6 +25,13 @@ const char copyright[] = "procan by Gerhard Rieger and contributors - send bug r
|
|||
#define WITH_HELP 1
|
||||
|
||||
static void procan_usage(FILE *fd);
|
||||
static void procan_version(FILE *fd);
|
||||
|
||||
const char copyright_procan[] = "procan by Gerhard Rieger and contributors - see www.dest-unreach.org";
|
||||
static const char procanversion[] =
|
||||
#include "./VERSION"
|
||||
;
|
||||
static const char timestamp[] = BUILD_DATE;
|
||||
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
@ -39,8 +49,8 @@ int main(int argc, const char *argv[]) {
|
|||
case '?': case 'h': procan_usage(stdout); exit(0);
|
||||
#endif /* WITH_HELP */
|
||||
case 'c': procan_cdefs(stdout); exit(0);
|
||||
#if LATER
|
||||
case 'V': procan_version(stdout); exit(0);
|
||||
#if LATER
|
||||
case 'l': diag_set(arg1[0][2], &arg1[0][3]); break;
|
||||
case 'd': diag_set('d', NULL); break;
|
||||
#endif
|
||||
|
@ -80,9 +90,7 @@ static void procan_usage(FILE *fd) {
|
|||
fputs("Usage:\n", fd);
|
||||
fputs("procan [options]\n", fd);
|
||||
fputs(" options:\n", fd);
|
||||
#if LATER
|
||||
fputs(" -V print version information to stdout, and exit\n", fd);
|
||||
#endif
|
||||
#if WITH_HELP
|
||||
fputs(" -?|-h print a help text describing command line options\n", fd);
|
||||
#endif
|
||||
|
@ -100,3 +108,17 @@ static void procan_usage(FILE *fd) {
|
|||
#endif
|
||||
}
|
||||
#endif /* WITH_HELP */
|
||||
|
||||
|
||||
void procan_version(
|
||||
FILE *fd)
|
||||
{
|
||||
struct utsname ubuf;
|
||||
|
||||
fputs(copyright_procan, fd); fputc('\n', fd);
|
||||
fprintf(fd, "procan version %s on %s\n", procanversion, timestamp);
|
||||
uname(&ubuf);
|
||||
fprintf(fd, " running on %s version %s, release %s, machine %s\n",
|
||||
ubuf.sysname, ubuf.version, ubuf.release, ubuf.machine);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ $ECHO
|
|||
|
||||
if [ "$USERNAME" != "$CREDUSER" -o "$PASSWORD" != "$CREDPASS" ]; then
|
||||
$ECHO "Authentication failed" >&2
|
||||
exit -1
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while $ECHO "$PROMPT\c"; read -r COMMAND; do
|
||||
|
|
22
readline.sh
22
readline.sh
|
@ -4,15 +4,19 @@
|
|||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# this is an attempt for a socat based readline wrapper
|
||||
# usage: readline.sh <command>
|
||||
# usage: readline.sh [options] <program>
|
||||
|
||||
withhistfile=1
|
||||
|
||||
STDERR=
|
||||
while true; do
|
||||
case "X$1" in
|
||||
X-nh|X-nohist*) withhistfile=; shift; continue ;;
|
||||
*) break;;
|
||||
X-lf?*) STDERR="${1:3}" ;;
|
||||
X-lf) shift; STDERR="$1" ;;
|
||||
X-nh|X-nohist*) withhistfile= ;;
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
PROGRAM="$@"
|
||||
|
@ -25,12 +29,18 @@ fi
|
|||
#
|
||||
#
|
||||
|
||||
if test -w .; then
|
||||
#if test -w .; then
|
||||
if [ -z "$STDERR" ] && find . -maxdepth 0 -user $USER ! -perm /022 -print |grep ^ >/dev/null; then
|
||||
# When cwd is owned by $USER and it is neither group nor world writable
|
||||
STDERR=./socat-readline.${1##*/}.log
|
||||
rm -f $STDERR
|
||||
else
|
||||
echo "$0: logs go to $STDERR" >&2
|
||||
elif [ -z "$STDERR" ]; then
|
||||
echo "$0: insecure working directory, no logs are written" >&2
|
||||
STDERR=/dev/null
|
||||
else
|
||||
echo "$0: logs go to $STDERR" >&2
|
||||
fi
|
||||
|
||||
exec socat -d readline"$HISTOPT",noecho='[Pp]assword:' exec:"$PROGRAM",sigint,pty,setsid,ctty,raw,echo=0,stderr 2>$STDERR
|
||||
exec socat -d READLINE"$HISTOPT",noecho='[Pp]assword:' EXEC:"$PROGRAM",sigint,pty,setsid,ctty,raw,echo=0,stderr 2>$STDERR
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ while [ "$1" ]; do
|
|||
X-q) QUIET=1; OPTS="-d0" ;;
|
||||
X-d*|X-l?*) OPTS="$OPTS $1" ;;
|
||||
X-b|X-S|X-t|X-T|X-l) OPT=$1; shift; OPTS="$OPTS $OPT $1" ;;
|
||||
X--experimental) ;;
|
||||
X-) break ;;
|
||||
X-*) echo "Unknown option \"$1\"" >&2
|
||||
usage >&2
|
||||
|
|
|
@ -77,6 +77,7 @@ while [ "$1" ]; do
|
|||
X-q) QUIET=1; OPTS="-d0" ;;
|
||||
X-d*|X-l?*) OPTS="$OPTS $1" ;;
|
||||
X-b|X-S|X-t|X-T|X-l) OPT=$1; shift; OPTS="$OPTS $OPT $1" ;;
|
||||
X--experimental) ;;
|
||||
X-) break ;;
|
||||
X-*) echo "$0: Unknown option \"$1\"" >&2
|
||||
usage >&2
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# Shell script to build a many-to-one, one-to-all communication
|
||||
# Shell script to establish many-to-one, one-to-all communications.
|
||||
# It starts two Socat instances that communicate via IPv4 broadcast,
|
||||
# the first of which forks a child process for each connected client.
|
||||
|
||||
|
@ -43,6 +43,7 @@ while [ "$1" ]; do
|
|||
X-q) QUIET=1; OPTS="-d0" ;;
|
||||
X-d*|X-l?*) OPTS="$OPTS $1" ;;
|
||||
X-b|X-S|X-t|X-T|X-l) OPT=$1; shift; OPTS="$OPTS $OPT $1" ;;
|
||||
X--experimental) ;;
|
||||
X-) break ;;
|
||||
X-*) echo "$0: Unknown option \"$1\"" >&2
|
||||
usage >&2
|
||||
|
|
31
socat.c
31
socat.c
|
@ -282,6 +282,8 @@ int main(int argc, const char *argv[]) {
|
|||
socat_opts.total_timeout.tv_usec =
|
||||
(rto-socat_opts.total_timeout.tv_sec) * 1000000;
|
||||
}
|
||||
xioparms.total_timeout.tv_sec = socat_opts.total_timeout.tv_sec;
|
||||
xioparms.total_timeout.tv_usec = socat_opts.total_timeout.tv_usec;
|
||||
break;
|
||||
case 'u': if (arg1[0][2]) { socat_opt_hint(stderr, arg1[0][1], arg1[0][2]); Exit(1); }
|
||||
socat_opts.lefttoright = true; break;
|
||||
|
@ -783,7 +785,7 @@ int socat(const char *address1, const char *address2) {
|
|||
int i;
|
||||
for (i = 0; i < NUMUNKNOWN; ++i) {
|
||||
if (XIO_RDSTREAM(sock1)->para.exec.pid == diedunknown[i]) {
|
||||
/* child has alread died... but it might have put regular data into
|
||||
/* Child has already died... but it might have put regular data into
|
||||
the communication channel, so continue */
|
||||
Info2("child "F_pid" has already died with status %d",
|
||||
XIO_RDSTREAM(sock1)->para.exec.pid, statunknown[i]);
|
||||
|
@ -826,7 +828,7 @@ int socat(const char *address1, const char *address2) {
|
|||
int i;
|
||||
for (i = 0; i < NUMUNKNOWN; ++i) {
|
||||
if (XIO_RDSTREAM(sock2)->para.exec.pid == diedunknown[i]) {
|
||||
/* child has alread died... but it might have put regular data into
|
||||
/* Child has already died... but it might have put regular data into
|
||||
the communication channel, so continue */
|
||||
Info2("child "F_pid" has already died with status %d",
|
||||
XIO_RDSTREAM(sock2)->para.exec.pid, statunknown[i]);
|
||||
|
@ -863,11 +865,12 @@ int childleftdata(xiofile_t *xfd) {
|
|||
XIO_RDSTREAM(xfd)->para.exec.pid == 0) {
|
||||
struct timeval timeout = { 0, 0 };
|
||||
|
||||
if (XIO_READABLE(xfd) && !(XIO_RDSTREAM(xfd)->eof >= 2 && !XIO_RDSTREAM(xfd)->ignoreeof)) {
|
||||
in.fd = XIO_GETRDFD(xfd);
|
||||
in.events = POLLIN/*|POLLRDBAND*/;
|
||||
in.revents = 0;
|
||||
}
|
||||
if (XIO_RDSTREAM(xfd)->eof >= 2 && !XIO_RDSTREAM(xfd)->ignoreeof)
|
||||
return 0;
|
||||
|
||||
in.fd = XIO_GETRDFD(xfd);
|
||||
in.events = POLLIN/*|POLLRDBAND*/;
|
||||
in.revents = 0;
|
||||
do {
|
||||
int _errno;
|
||||
retval = xiopoll(&in, 1, &timeout);
|
||||
|
@ -875,7 +878,7 @@ int childleftdata(xiofile_t *xfd) {
|
|||
} while (retval < 0 && errno == EINTR);
|
||||
|
||||
if (retval < 0) {
|
||||
Error5("xiopoll({%d,%0o}, 1, {"F_tv_sec"."F_tv_usec"}): %s",
|
||||
Error5("xiopoll({%d,0%o}, 1, {"F_tv_sec"."F_tv_usec"}): %s",
|
||||
in.fd, in.events, timeout.tv_sec, timeout.tv_usec,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
|
@ -1013,7 +1016,7 @@ int _socat(void) {
|
|||
/* for ignoreeof */
|
||||
if (polling) {
|
||||
if (!wasaction) {
|
||||
if (socat_opts.total_timeout.tv_usec <= 1000000) {
|
||||
if (socat_opts.total_timeout.tv_usec < 1000000) {
|
||||
if (total_timeout.tv_usec < socat_opts.pollintv.tv_usec) {
|
||||
total_timeout.tv_usec += 1000000;
|
||||
total_timeout.tv_sec -= 1;
|
||||
|
@ -1131,7 +1134,7 @@ int _socat(void) {
|
|||
*/
|
||||
|
||||
if (retval < 0) {
|
||||
Error11("xiopoll({%d,%0o}{%d,%0o}{%d,%0o}{%d,%0o}, 4, {"F_tv_sec"."F_tv_usec"}): %s",
|
||||
Error11("xiopoll({%d,0%o}{%d,0%o}{%d,0%o}{%d,0%o}, 4, {"F_tv_sec"."F_tv_usec"}): %s",
|
||||
fds[0].fd, fds[0].events, fds[1].fd, fds[1].events,
|
||||
fds[2].fd, fds[2].events, fds[3].fd, fds[3].events,
|
||||
timeout.tv_sec, timeout.tv_usec, strerror(errno));
|
||||
|
@ -1336,7 +1339,6 @@ int _socat(void) {
|
|||
should be at least MAXTIMESTAMPLEN bytes long.
|
||||
returns 0 on success or -1 if an error occurred */
|
||||
int gettimestamp(char *timestamp) {
|
||||
size_t bytes;
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
struct timespec now;
|
||||
#elif HAVE_PROTOTYPE_LIB_gettimeofday
|
||||
|
@ -1364,17 +1366,16 @@ int gettimestamp(char *timestamp) {
|
|||
}
|
||||
#endif
|
||||
#if HAVE_STRFTIME
|
||||
bytes = strftime(timestamp, 20, "%Y/%m/%d %H:%M:%S", localtime(&nowt));
|
||||
strftime(timestamp, 20, "%Y/%m/%d %H:%M:%S", localtime(&nowt));
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
bytes += sprintf(timestamp+19, "."F_tv_nsec" ", now.tv_nsec/1000);
|
||||
sprintf(timestamp+19, "."F_tv_nsec" ", now.tv_nsec/1000);
|
||||
#elif HAVE_PROTOTYPE_LIB_gettimeofday
|
||||
bytes += sprintf(timestamp+19, "."F_tv_usec" ", now.tv_usec);
|
||||
sprintf(timestamp+19, "."F_tv_usec" ", now.tv_usec);
|
||||
#else
|
||||
strncpy(×tamp[bytes++], " ", 2);
|
||||
#endif
|
||||
#else
|
||||
strcpy(timestamp, ctime(&nowt));
|
||||
bytes = strlen(timestamp);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
%define majorver 1.8
|
||||
%define minorver 0.2
|
||||
%define minorver 0.3
|
||||
|
||||
Summary: socat - multipurpose relay
|
||||
Name: socat
|
||||
|
|
|
@ -37,7 +37,7 @@ esac
|
|||
if [ $(echo "x\c") = "x" ]; then E=""
|
||||
elif [ $(echo -e "x\c") = "x" ]; then E="-e"
|
||||
else
|
||||
echo "cannot suppress trailing newline on echo" >&2
|
||||
echo "$0: cannot suppress trailing newline on echo" >&2
|
||||
exit 1
|
||||
fi
|
||||
ECHO="echo $E"
|
||||
|
@ -58,7 +58,7 @@ else
|
|||
fi
|
||||
if [ "$vn" != $($ECHO "\04") ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "invalid socks version requested" >&2
|
||||
echo "$0 invalid socks version requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
|
@ -69,7 +69,7 @@ else
|
|||
fi
|
||||
if [ "$cd" != $($ECHO "\01") ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "invalid socks operation requested" >&2
|
||||
echo "$0: invalid socks operation requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
|
@ -82,7 +82,7 @@ a=$(dd bs=1 count=6 2>/dev/null)
|
|||
if [ "$a" != "$($ECHO "}m\0\0\0\01")" ]; then
|
||||
sleep 1
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "wrong socks address or port requested" >&2
|
||||
echo "$0: wrong socks address or port requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
|
@ -93,7 +93,7 @@ else
|
|||
fi
|
||||
if [ "$u" != "nobody" ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "wrong socks user requested" >&2
|
||||
echo "$0: wrong socks user requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
|
@ -104,7 +104,7 @@ else
|
|||
fi
|
||||
if [ "$h" != "localhost" ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "wrong socks address requested" >&2
|
||||
echo "$0: wrong socks address requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
# it is required for test.sh
|
||||
# for TCP, use this script as:
|
||||
# socat tcp-l:1080,reuseaddr,crlf system:"socks4echo.sh"
|
||||
# Then connect with a socks4 request for 32.98.76.54:32109 and user nobody
|
||||
|
||||
# older bash and ksh do not have -n option to read command; we try dd then
|
||||
#if echo a |read -n 1 null >/dev/null 2>&1; then
|
||||
|
@ -36,7 +37,7 @@ esac
|
|||
if [ $(echo "x\c") = "x" ]; then E=""
|
||||
elif [ $(echo -e "x\c") = "x" ]; then E="-e"
|
||||
else
|
||||
echo "cannot suppress trailing newline on echo" >&2
|
||||
echo "$0: cannot suppress trailing newline on echo" >&2
|
||||
exit 1
|
||||
fi
|
||||
ECHO="echo $E"
|
||||
|
@ -57,7 +58,7 @@ else
|
|||
fi
|
||||
if [ "$vn" != $($ECHO "\04") ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "invalid socks version requested" >&2
|
||||
echo "$0: invalid socks version requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
|
@ -68,7 +69,7 @@ else
|
|||
fi
|
||||
if [ "$cd" != $($ECHO "\01") ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "invalid socks operation requested" >&2
|
||||
echo "$0: invalid socks operation requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
|
@ -91,7 +92,7 @@ else
|
|||
fi
|
||||
if [ "$u" != "nobody" ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "wrong socks user requested (expected \"nobody\")" >&2
|
||||
echo "$0: wrong socks user requested (expected \"nobody\")" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
|
|
67
socks5server-echo.sh
Executable file
67
socks5server-echo.sh
Executable file
|
@ -0,0 +1,67 @@
|
|||
#! /usr/bin/env bash
|
||||
# Source: socks5connect-echo.sh
|
||||
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# Performs primitive simulation of a socks5 server with echo function via stdio.
|
||||
# Accepts and answers SOCKS5 CONNECT request without authentication to
|
||||
# 8.8.8.8:80, however is does not connect there but just echoes data.
|
||||
# It is required for test.sh
|
||||
# For TCP, use this script as:
|
||||
# socat TCP-L:1080,reuseaddr EXEC:"socks5connect-echo.sh"
|
||||
|
||||
#set -vx
|
||||
|
||||
if [ "$SOCAT" ]; then
|
||||
:
|
||||
elif type socat >/dev/null 2>&1; then
|
||||
SOCAT=socat
|
||||
else
|
||||
SOCAT=./socat
|
||||
fi
|
||||
|
||||
case `uname` in
|
||||
HP-UX|OSF1)
|
||||
CAT="$SOCAT -u STDIN STDOUT"
|
||||
;;
|
||||
*)
|
||||
CAT=cat
|
||||
;;
|
||||
esac
|
||||
|
||||
A="7f000001"
|
||||
P="0050"
|
||||
|
||||
# Read and parse SOCKS5 greeting
|
||||
read _ v b c _ <<<"$($SOCAT -u -,readbytes=3 - |od -t x1)"
|
||||
#echo "$v $b $c" >&2
|
||||
if [ "$v" != 05 ]; then echo "$0: Packet1: expected version x05, got \"$v\"" >&2; exit 1; fi
|
||||
if [ "$b" != 01 ]; then echo "$0: Packet1: expected 01 auth methods, got \"$b\"" >&2; exit 1; fi
|
||||
if [ "$c" != 00 ]; then echo "$0: Packet1: expected auth method 00, got \"$c\"" >&2; exit 1; fi
|
||||
# Send answer
|
||||
echo -en "\x05\x00"
|
||||
|
||||
# Read and parse SOCKS5 connect request
|
||||
read _ v b c d a1 a2 a3 a4 p1 p2 _ <<<"$($SOCAT -u -,readbytes=10 - |od -t x1)"
|
||||
#echo "$v $b $c $d $a1 $a2 $a3 $a4 $p1 $p2" >&2
|
||||
a="$a1$a2$a3$a4"
|
||||
p="$p1$p2"
|
||||
if [ "$v" != 05 ]; then echo "$0: Packet2: expected version x05, got \"$v\"" >&2; exit 1; fi
|
||||
if [ "$b" != 01 ] && [ "$b" != 02 ]; then echo "$0: Packet2: expected connect request 01 or bind request 02, got \"$b\"" >&2; exit 1; fi
|
||||
if [ "$c" != 00 ]; then echo "$0: Packet2: expected reserved 00, got \"$c\"" >&2; exit 1; fi
|
||||
if [ "$d" != 01 ]; then echo "$0: Packet2: expected address type 01, got \"$d\"" >&2; exit 1; fi
|
||||
if [ "$a" != "$A" ]; then echo "$0: Packet2: expected address $A, got \"$a\"" >&2; exit 1; fi
|
||||
if [ "$p" != "$P" ]; then echo "$0: Packet2: expected port $P, got \"$p\"" >&2; exit 1; fi
|
||||
if [ "$z" != "" ]; then echo "$0: Packet2: trailing data \"$z\"" >&2; exit 1; fi
|
||||
# Send answer
|
||||
echo -en "\x05\x00\x00\x01\x10\x00\x1f\x64\x1f\x64"
|
||||
|
||||
# Bind/listen/passive mode
|
||||
if [ "$b" == 02 ]; then
|
||||
sleep 1 # pretend to be waiting for connection
|
||||
echo -en "\x05\x00\x00\x01\x10\xff\x1f\x64\x23\x28"
|
||||
fi
|
||||
|
||||
# perform echo function
|
||||
$CAT
|
1
sslcls.c
1
sslcls.c
|
@ -368,6 +368,7 @@ int sycSSL_connect(SSL *ssl) {
|
|||
int result;
|
||||
Debug1("SSL_connect(%p)", ssl);
|
||||
result = SSL_connect(ssl);
|
||||
if (!diag_in_handler) diag_flush();
|
||||
Debug1("SSL_connect() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
|
19
sycls.c
19
sycls.c
|
@ -1421,11 +1421,11 @@ unsigned int Sleep(unsigned int seconds) {
|
|||
#if HAVE_NANOSLEEP
|
||||
unsigned int Nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
int retval, _errno;
|
||||
Debug3("nanosleep({"F_time",%ld},%p)", req->tv_sec, req->tv_nsec, rem);
|
||||
Debug3("nanosleep({"F_time".%09ld}, %p)", req->tv_sec, req->tv_nsec, rem);
|
||||
retval = nanosleep(req, rem);
|
||||
_errno = errno;
|
||||
if (rem) {
|
||||
Debug3("nanosleep(,{"F_time",%ld}) -> %d",
|
||||
Debug3("nanosleep(,{"F_time".%09ld}) -> %d",
|
||||
rem->tv_sec, rem->tv_nsec, retval);
|
||||
} else {
|
||||
Debug1("nanosleep() -> %d", retval);
|
||||
|
@ -1513,6 +1513,9 @@ void *Malloc(size_t size) {
|
|||
Error1("malloc("F_Zd"): out of memory", size);
|
||||
return NULL;
|
||||
}
|
||||
#if WITH_DEVTESTS
|
||||
memset(result, 0x55, size);
|
||||
#endif /* WITH_DEVTESTS */
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1540,6 +1543,18 @@ void *Realloc(void *ptr, size_t size) {
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Like Realloc(), but gets info about old size for overwrite test */
|
||||
void *Realloc3(void *ptr, size_t size, size_t oldsize) {
|
||||
void *result = Realloc(ptr, size);
|
||||
if (result == NULL)
|
||||
return result;
|
||||
#if WITH_DEVTESTS
|
||||
if (size > oldsize)
|
||||
memset(result+oldsize, 0x55, size-oldsize);
|
||||
#endif /* WITH_DEVTESTS */
|
||||
return result;
|
||||
}
|
||||
|
||||
#if _WITH_TERMIOS
|
||||
int Tcgetattr(int fd, struct termios *termios_p) {
|
||||
int i, result, _errno;
|
||||
|
|
2
sycls.h
2
sycls.h
|
@ -148,6 +148,7 @@ struct hostent *Getipnodebyname(const char *name, int af, int flags,
|
|||
void *Malloc(size_t size);
|
||||
void *Calloc(size_t nmemb, size_t size);
|
||||
void *Realloc(void *ptr, size_t size);
|
||||
void *Realloc3(void *ptr, size_t size, size_t oldsize);
|
||||
int Tcgetattr(int fd, struct termios *termios_p);
|
||||
int Tcsetattr(int fd, int optional_actions, struct termios *termios_p);
|
||||
char *Ttyname(int fd);
|
||||
|
@ -257,6 +258,7 @@ void Add_history(const char *string);
|
|||
#define Malloc(s) malloc(s)
|
||||
#define Calloc(n,s) calloc(n,s)
|
||||
#define Realloc(p,s) realloc(p,s)
|
||||
#define Realloc3(p,s,o) realloc(p,s)
|
||||
#define Tcgetattr(f,t) tcgetattr(f,t)
|
||||
#define Tcsetattr(f,o,t) tcsetattr(f,o,t)
|
||||
#define Ttyname(f) ttyname(f)
|
||||
|
|
|
@ -150,6 +150,9 @@
|
|||
#if HAVE_LINUX_IF_TUN_H
|
||||
#include <linux/if_tun.h>
|
||||
#endif
|
||||
#if HAVE_NETINET_DCCP_H
|
||||
#include <netinet/dccp.h>
|
||||
#endif
|
||||
#if HAVE_LINUX_DCCP_H
|
||||
#include <linux/dccp.h>
|
||||
#endif
|
||||
|
@ -182,7 +185,7 @@
|
|||
#if WITH_NAMESPACES && HAVE_SCHED_H
|
||||
#include <sched.h>
|
||||
#endif
|
||||
#if WITH_POSIXMQ
|
||||
#if WITH_POSIXMQ && HAVE_MQUEUE_H
|
||||
#include <mqueue.h> /* POSIX MQ */
|
||||
#endif
|
||||
#if WITH_READLINE
|
||||
|
|
62
sysutils.c
62
sysutils.c
|
@ -27,9 +27,22 @@ const int one = 1;
|
|||
Returns <0 on unhandled error, errno valid
|
||||
Will only return <0 or bytes
|
||||
*/
|
||||
ssize_t writefull(int fd, const void *buff, size_t bytes) {
|
||||
/* Assuming your pipe size is 65536 - find out with:
|
||||
filan -i 1 |grep F_GETPIPE_SZ |sed 's|.*\(F_GETPIPE_SZ=[1-9][0-9]*\).*|\1|'
|
||||
Then we can test partial write with something like:
|
||||
socat -d4 -lu -b 262144 -u /dev/zero,readbytes=262144 -,o-nonblock |{ sleep 3; wc -c; }
|
||||
*/
|
||||
ssize_t writefull(
|
||||
int fd,
|
||||
const void *buff,
|
||||
size_t bytes,
|
||||
const struct timeval *tmo0) {
|
||||
size_t writt = 0;
|
||||
ssize_t chk;
|
||||
struct pollfd pfd;
|
||||
struct timeval tmo = { 0 };
|
||||
int rc;
|
||||
|
||||
while (1) {
|
||||
chk = Write(fd, (const char *)buff + writt, bytes - writt);
|
||||
if (chk < 0) {
|
||||
|
@ -40,15 +53,34 @@ ssize_t writefull(int fd, const void *buff, size_t bytes) {
|
|||
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;
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLOUT;
|
||||
pfd.revents = 0;
|
||||
if (tmo0 != NULL) {
|
||||
tmo.tv_sec = tmo0->tv_sec;
|
||||
tmo.tv_usec = tmo0->tv_usec;
|
||||
}
|
||||
rc = xiopoll(&pfd, 1, (tmo.tv_sec!=0 || tmo.tv_usec!=0) ? &tmo : NULL);
|
||||
if (rc == 0) {
|
||||
Notice("inactivity timeout triggered");
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
} else if (chk == bytes) {
|
||||
/* First attempt, complete write */
|
||||
return chk;
|
||||
} else if (writt+chk < bytes) {
|
||||
Warn4("write(%d, %p, "F_Zu"): only wrote "F_Zu" bytes, trying to continue (rev.direction is blocked)",
|
||||
Warn4("write(%d, %p, "F_Zu"): only wrote "F_Zu" bytes, trying to continue (meanwhile, other direction is blocked)",
|
||||
fd, (const char *)buff+writt, bytes-writt, chk);
|
||||
writt += chk;
|
||||
} else {
|
||||
writt = bytes;
|
||||
} else if (writt == 0) {
|
||||
/* First attempt, write complete - no extra message */
|
||||
return chk;
|
||||
} else { /* write completed */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -548,7 +580,7 @@ int getusergroups(const char *user, gid_t *list, int *ngroups) {
|
|||
/* 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. */
|
||||
/* 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 arbitrary supplementary group id that we then pass in a second call to getgrouplist. */
|
||||
grp = 0;
|
||||
Getgrouplist(user, grp, twogrps, &two);
|
||||
if (two == 1) {
|
||||
|
@ -677,7 +709,7 @@ int xiopoll(struct pollfd fds[], unsigned long nfds, struct timeval *timeout) {
|
|||
}
|
||||
|
||||
|
||||
#if WITH_TCP || WITH_UDP
|
||||
#if WITH_TCP || WITH_UDP || WITH_SCTP || WITH_DCCP || WITH_UDPLITE
|
||||
/* returns port in network byte order;
|
||||
ipproto==IPPROTO_UDP resolves as UDP service, every other value resolves as
|
||||
TCP */
|
||||
|
@ -702,10 +734,10 @@ int parseport(const char *portname, int ipproto) {
|
|||
|
||||
return se->s_port;
|
||||
}
|
||||
#endif /* WITH_TCP || WITH_UDP */
|
||||
#endif /* WITH_TCP || WITH_UDP || WITH_SCTP || WITH_DCCP || WITH_UDPLITE */
|
||||
|
||||
|
||||
#if WITH_IP4 || WITH_IP6 || WITH_INTERFACE
|
||||
#if WITH_IP4 || WITH_IP6 || _WITH_INTERFACE
|
||||
/* check the systems interfaces for ifname and return its index
|
||||
or -1 if no interface with this name was found
|
||||
The system calls require an arbitrary socket; the calling program may
|
||||
|
@ -729,8 +761,8 @@ int ifindexbyname(const char *ifname, int anysock) {
|
|||
}
|
||||
if (anysock >= 0) {
|
||||
s = anysock;
|
||||
} else if ((s = Socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
|
||||
Error1("socket(PF_INET, SOCK_DGRAM, IPPROTO_IP): %s", strerror(errno));
|
||||
} else if ((s = Socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
Error1("socket(PF_INET, SOCK_DGRAM, 0): %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -756,10 +788,10 @@ int ifindexbyname(const char *ifname, int anysock) {
|
|||
return -1;
|
||||
#endif /* !defined(HAVE_ STRUCT_IFREQ) && defined(SIOCGIFCONF) && defined(SIOCGIFINDEX) */
|
||||
}
|
||||
#endif /* WITH_IP4 || WITH_IP6 || WITH_INTERFACE */
|
||||
#endif /* WITH_IP4 || WITH_IP6 || _WITH_INTERFACE */
|
||||
|
||||
|
||||
#if WITH_IP4 || WITH_IP6 || WITH_INTERFACE
|
||||
#if WITH_IP4 || WITH_IP6 || _WITH_INTERFACE
|
||||
/* like ifindexbyname(), but also allows the index number as input - in this
|
||||
case it does not lookup the index.
|
||||
writes the resulting index to *ifindex and returns 0,
|
||||
|
@ -783,7 +815,7 @@ int ifindex(const char *ifname, unsigned int *ifindex, int anysock) {
|
|||
*ifindex = val;
|
||||
return 0;
|
||||
}
|
||||
#endif /* WITH_IP4 || WITH_IP6 || WITH_INTERFACE */
|
||||
#endif /* WITH_IP4 || WITH_IP6 || _WITH_INTERFACE */
|
||||
|
||||
|
||||
int _xiosetenv(const char *envname, const char *value, int overwrite, const char *sep) {
|
||||
|
|
|
@ -47,7 +47,7 @@ struct xiorange {
|
|||
extern const int one;
|
||||
#endif
|
||||
|
||||
extern ssize_t writefull(int fd, const void *buff, size_t bytes);
|
||||
extern ssize_t writefull(int fd, const void *buff, size_t bytes, const struct timeval *tmo0);
|
||||
|
||||
#if _WITH_SOCKET
|
||||
extern socklen_t socket_init(int af, union sockaddr_union *sa);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include "xio-ascii.h"
|
||||
|
||||
/* for each 6 bit pattern we have an ASCII character in the arry */
|
||||
/* For each 6 bit pattern we have an ASCII character in the array */
|
||||
const static int base64chars[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
|
|
|
@ -84,7 +84,8 @@ static int xioopen_exec(
|
|||
while (*strp == ' ') {
|
||||
while (*++strp == ' ') ;
|
||||
if ((pargc & 0x07) == 0) {
|
||||
pargv = Realloc(pargv, (pargc+8)*sizeof(char *));
|
||||
/*0 pargv = Realloc(pargv, (pargc+8)*sizeof(char *)); */
|
||||
pargv = Realloc3(pargv, (pargc+8)*sizeof(char *), pargc*sizeof(char *));
|
||||
if (pargv == NULL) return STAT_RETRYLATER;
|
||||
}
|
||||
pargv[pargc++] = tokp;
|
||||
|
|
2
xio-fd.c
2
xio-fd.c
|
@ -31,7 +31,7 @@ const struct optdesc opt_o_noinherit = { "o-noinherit", "noinherit", OPT_O_NOINH
|
|||
const struct optdesc opt_o_noatime = { "o-noatime", "noatime", OPT_O_NOATIME, GROUP_OPEN|GROUP_FD, PH_FD, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_NOATIME };
|
||||
#endif
|
||||
/****** for ALL addresses - with fcntl(F_SETFD) ******/
|
||||
const struct optdesc opt_cloexec = { "cloexec", NULL, OPT_CLOEXEC, GROUP_FD, PH_LATE, TYPE_BOOL, OFUNC_FCNTL, F_SETFD, FD_CLOEXEC };
|
||||
const struct optdesc opt_cloexec = { "cloexec", NULL, OPT_O_CLOEXEC, GROUP_FD, PH_LATE, TYPE_BOOL, OFUNC_FCNTL, F_SETFD, FD_CLOEXEC };
|
||||
/****** ftruncate() ******/
|
||||
/* this record is good for ftruncate() or ftruncate64() if available */
|
||||
#if HAVE_FTRUNCATE64
|
||||
|
|
|
@ -20,7 +20,7 @@ static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xiof
|
|||
const struct optdesc opt_o_rdonly = { "o-rdonly", "rdonly", OPT_O_RDONLY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG_PATTERN, O_RDONLY, O_ACCMODE };
|
||||
const struct optdesc opt_o_wronly = { "o-wronly", "wronly", OPT_O_WRONLY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG_PATTERN, O_WRONLY, O_ACCMODE };
|
||||
const struct optdesc opt_o_rdwr = { "o-rdwr", "rdwr", OPT_O_RDWR, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG_PATTERN, O_RDWR, O_ACCMODE };
|
||||
const struct optdesc opt_o_create = { "o-create", "creat", OPT_O_CREATE, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_CREAT };
|
||||
const struct optdesc opt_o_creat = { "o-creat", "creat", OPT_O_CREAT, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_CREAT };
|
||||
const struct optdesc opt_o_excl = { "o-excl", "excl", OPT_O_EXCL, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_EXCL };
|
||||
const struct optdesc opt_o_noctty = { "o-noctty", "noctty", OPT_O_NOCTTY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_NOCTTY };
|
||||
#ifdef O_SYNC
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
extern const struct optdesc opt_o_rdonly;
|
||||
extern const struct optdesc opt_o_wronly;
|
||||
extern const struct optdesc opt_o_rdwr;
|
||||
extern const struct optdesc opt_o_create;
|
||||
extern const struct optdesc opt_o_creat;
|
||||
extern const struct optdesc opt_o_excl;
|
||||
extern const struct optdesc opt_o_noctty;
|
||||
extern const struct optdesc opt_o_sync;
|
||||
|
|
2
xio-fs.c
2
xio-fs.c
|
@ -87,7 +87,7 @@ const struct optdesc opt_fs_noatime = { "fs-noatime", "noatime",
|
|||
#endif /* FS_NOATIME_FL */
|
||||
|
||||
/* FS_DIRTY_FL ??? */
|
||||
/* FS_COMPRBLK_FL one ore more compress clusters */
|
||||
/* FS_COMPRBLK_FL one or more compress clusters */
|
||||
/* FS_NOCOMPR_FL access raw compressed data */
|
||||
/* FS_ECOMPR_FL compression error */
|
||||
/* FS_BTREE_FL btree format dir */
|
||||
|
|
|
@ -71,7 +71,7 @@ int _xioopen_interface(const char *ifname,
|
|||
|
||||
if (ifindex(ifname, &ifidx, -1) < 0) {
|
||||
Error1("unknown interface \"%s\"", ifname);
|
||||
ifidx = 0; /* desparate attempt to continue */
|
||||
ifidx = 0; /* desperate attempt to continue */
|
||||
}
|
||||
|
||||
if (sfd->howtoend == END_UNSPEC)
|
||||
|
@ -276,7 +276,7 @@ int _xiointerface_apply_iff(
|
|||
|
||||
|
||||
#if HAVE_STRUCT_CMSGHDR && HAVE_STRUCT_TPACKET_AUXDATA
|
||||
/* Converts the ancillary message in *cmsg into a form useable for further
|
||||
/* Converts the ancillary message in *cmsg into a form usable for further
|
||||
processing. Knows the specifics of common message types.
|
||||
On PACKET_AUXDATA it stored the ancillary data in the XFD.
|
||||
For other types:
|
||||
|
|
122
xio-ip.c
122
xio-ip.c
|
@ -68,7 +68,7 @@ const struct optdesc opt_ip_multicast_if ={"ip-multicast-if", "multicast-if",
|
|||
#ifdef IP_PKTOPTIONS
|
||||
const struct optdesc opt_ip_pktoptions = { "ip-pktoptions", "pktopts", OPT_IP_PKTOPTIONS, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_PKTOPTIONS };
|
||||
#endif
|
||||
#ifdef IP_ADD_MEMBERSHIP
|
||||
#if defined(HAVE_STRUCT_IP_MREQ) || defined(HAVE_STRUCT_IP_MREQN)
|
||||
const struct optdesc opt_ip_add_membership = { "ip-add-membership", "membership",OPT_IP_ADD_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SPEC, SOL_IP, IP_ADD_MEMBERSHIP };
|
||||
#endif
|
||||
#if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP)
|
||||
|
@ -161,6 +161,79 @@ int Res_init(void) {
|
|||
#endif /* HAVE_RESOLV_H */
|
||||
|
||||
|
||||
/* Looks for a bind option and, if found, passes it to resolver;
|
||||
for IP (v4, v6) and raw (PF_UNSPEC);
|
||||
returns list of addrinfo results;
|
||||
returns STAT_OK if option exists and could be resolved,
|
||||
STAT_NORETRY if option exists but had error,
|
||||
or STAT_NOACTION if it does not exist */
|
||||
int retropt_bind_ip(
|
||||
struct opt *opts,
|
||||
int af,
|
||||
int socktype,
|
||||
int ipproto,
|
||||
struct addrinfo ***bindlist,
|
||||
int feats, /* TCP etc: 1..address allowed,
|
||||
3..address and port allowed
|
||||
*/
|
||||
const int ai_flags[2])
|
||||
{
|
||||
const char portsep[] = ":";
|
||||
const char *ends[] = { portsep, NULL };
|
||||
const char *nests[] = { "[", "]", NULL };
|
||||
bool portallowed;
|
||||
char *bindname, *bindp;
|
||||
char hostname[512], *hostp = hostname, *portp = NULL;
|
||||
size_t hostlen = sizeof(hostname)-1;
|
||||
int parsres;
|
||||
int ai_flags2[2];
|
||||
int result;
|
||||
|
||||
if (retropt_string(opts, OPT_BIND, &bindname) < 0) {
|
||||
return STAT_NOACTION;
|
||||
}
|
||||
bindp = bindname;
|
||||
|
||||
portallowed = (feats>=2);
|
||||
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) {
|
||||
Error("port specification not allowed in this bind option");
|
||||
return STAT_NORETRY;
|
||||
} else {
|
||||
portp = bindp + strlen(portsep);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set AI_PASSIVE, except when it is explicitely disabled */
|
||||
ai_flags2[0] = ai_flags[0];
|
||||
ai_flags2[1] = ai_flags[1];
|
||||
if (!(ai_flags2[1] & AI_PASSIVE))
|
||||
ai_flags2[0] |= AI_PASSIVE;
|
||||
|
||||
if ((result =
|
||||
xiogetaddrinfo(hostname[0]!='\0'?hostname:NULL, portp,
|
||||
af, socktype, ipproto,
|
||||
bindlist, ai_flags2))
|
||||
!= STAT_OK) {
|
||||
Error2("error resolving bind option \"%s\" with af=%d", bindname, af);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
||||
#if WITH_DEVTESTS
|
||||
|
||||
/* Have a couple of hard coded sockaddr records, to be copied and adapted when
|
||||
|
@ -386,6 +459,7 @@ int _xiogetaddrinfo(const char *node, const char *service,
|
|||
#else /* HAVE_PROTOTYPE_LIB_getipnodebyname || nothing */
|
||||
struct hostent *host;
|
||||
#endif
|
||||
bool restore_proto = false;
|
||||
int error_num;
|
||||
|
||||
Debug8("_xiogetaddrinfo(node=\"%s\", service=\"%s\", family=%d, socktype=%d, protoco=%d, ai_flags={0x%04x/0x%04x} }, res=%p",
|
||||
|
@ -512,15 +586,16 @@ int _xiogetaddrinfo(const char *node, const char *service,
|
|||
return EAI_SERVICE;
|
||||
}
|
||||
/* Probably unsupported protocol (e.g. UDP-Lite), fallback to 0 */
|
||||
restore_proto = true;
|
||||
hints.ai_protocol = 0;
|
||||
continue;
|
||||
}
|
||||
if ((error_num = Getaddrinfo(node, service, &hints, res)) != 0) {
|
||||
Warn7("getaddrinfo(\"%s\", \"%s\", {0x%02x,%d,%d,%d}, {}): %d",
|
||||
Warn7("getaddrinfo(\"%s\", \"%s\", {0x%02x,%d,%d,%d}, {}): %s",
|
||||
node?node:"NULL", service?service:"NULL",
|
||||
hints.ai_flags, hints.ai_family,
|
||||
hints.ai_socktype, hints.ai_protocol,
|
||||
error_num);
|
||||
gai_strerror(error_num));
|
||||
if (numnode)
|
||||
free(numnode);
|
||||
|
||||
|
@ -540,6 +615,14 @@ int _xiogetaddrinfo(const char *node, const char *service,
|
|||
#endif /* WITH_MSGLEVEL <= E_DEBUG */
|
||||
}
|
||||
|
||||
if (restore_proto) {
|
||||
struct addrinfo *record = *res;
|
||||
while (record) {
|
||||
record->ai_protocol = protocol;
|
||||
record = record->ai_next;
|
||||
}
|
||||
}
|
||||
|
||||
#elif HAVE_PROTOTYPE_LIB_getipnodebyname /* !HAVE_GETADDRINFO */
|
||||
|
||||
if (node != NULL) {
|
||||
|
@ -592,7 +675,7 @@ int _xiogetaddrinfo(const char *node, const char *service,
|
|||
freehostent(host);
|
||||
}
|
||||
|
||||
#elsif 0 /* !HAVE_PROTOTYPE_LIB_getipnodebyname */
|
||||
#elif 0 /* !HAVE_PROTOTYPE_LIB_getipnodebyname */
|
||||
|
||||
if (node != NULL) {
|
||||
/* this is not a typical IP6 resolver function - but Linux
|
||||
|
@ -760,6 +843,9 @@ void xiofreeaddrinfo(struct addrinfo **ai_sorted) {
|
|||
int ain;
|
||||
struct addrinfo *res;
|
||||
|
||||
if (ai_sorted == NULL)
|
||||
return;
|
||||
|
||||
/* Find the original *res from getaddrinfo past NULL */
|
||||
ain = 0;
|
||||
while (ai_sorted[ain] != NULL)
|
||||
|
@ -843,7 +929,7 @@ int xioresolve(const char *node, const char *service,
|
|||
}
|
||||
|
||||
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
|
||||
/* Converts the ancillary message in *cmsg into a form useable for further
|
||||
/* Converts the ancillary message in *cmsg into a form usable 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
|
||||
|
@ -902,16 +988,20 @@ int xiolog_ancillary_ip(
|
|||
'\0',
|
||||
inet4addr_info(ntohl(pktinfo->ipi_addr.s_addr),
|
||||
scratch3, sizeof(scratch3)));
|
||||
#if HAVE_PKTINFO_IPI_SPEC_DST
|
||||
Notice3("Ancillary message: interface \"%s\", locaddr=%s, dstaddr=%s",
|
||||
xiogetifname(pktinfo->ipi_ifindex, scratch1, -1),
|
||||
#if HAVE_PKTINFO_IPI_SPEC_DST
|
||||
inet4addr_info(ntohl(pktinfo->ipi_spec_dst.s_addr),
|
||||
scratch2, sizeof(scratch2)),
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
inet4addr_info(ntohl(pktinfo->ipi_addr.s_addr),
|
||||
scratch3, sizeof(scratch3)));
|
||||
#else
|
||||
Notice3("Ancillary message: interface \"%s\", locaddr=%s, dstaddr=%s",
|
||||
xiogetifname(pktinfo->ipi_ifindex, scratch1, -1),
|
||||
"",
|
||||
inet4addr_info(ntohl(pktinfo->ipi_addr.s_addr),
|
||||
scratch3, sizeof(scratch3)));
|
||||
#endif
|
||||
}
|
||||
return STAT_OK;
|
||||
#endif /* defined(IP_PKTINFO) && HAVE_STRUCT_IN_PKTINFO */
|
||||
|
@ -1001,7 +1091,7 @@ int xiolog_ancillary_ip(
|
|||
cmsgtype = "IP_OPTIONS"; cmsgname = "options"; cmsgctr = -1;
|
||||
/*!!!*/
|
||||
break;
|
||||
#if XIO_ANCILLARY_TYPE_SOLARIS
|
||||
#if defined(IP_RECVTOS) && XIO_ANCILLARY_TYPE_SOLARIS
|
||||
case IP_RECVTOS:
|
||||
#else
|
||||
case IP_TOS:
|
||||
|
@ -1112,13 +1202,14 @@ int xiotype_ip_add_membership(
|
|||
opt->value2.u_string/*param2*/,
|
||||
opt->value3.u_string/*ifindex*/);
|
||||
} else {
|
||||
/*0 opt->value3.u_string = NULL; / * is NULL from init */
|
||||
opt->value3.u_string = NULL; /* is not NULL from init! */
|
||||
Info3("setting option \"%s\" to {\"%s\",\"%s\"}",
|
||||
ent->desc->defname,
|
||||
opt->value.u_string/*multiaddr*/,
|
||||
opt->value2.u_string/*param2*/);
|
||||
}
|
||||
#else /* !HAVE_STRUCT_IP_MREQN */
|
||||
opt->value3.u_string = NULL;
|
||||
Info3("setting option \"%s\" to {\"%s\",\"%s\"}",
|
||||
ent->desc->defname,
|
||||
opt->value.u_string/*multiaddr*/,
|
||||
|
@ -1128,6 +1219,9 @@ int xiotype_ip_add_membership(
|
|||
}
|
||||
#endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */
|
||||
|
||||
|
||||
#if _WITH_IP4
|
||||
|
||||
#if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
|
||||
int xioapply_ip_add_membership(
|
||||
struct single *sfd,
|
||||
|
@ -1352,7 +1446,7 @@ int xioapply_ip_add_source_membership(struct single *sfd, struct opt *opt) {
|
|||
}
|
||||
ip4_mreq_src.imr_multiaddr = sockaddr1.ip4.sin_addr;
|
||||
/* second parameter is interface address */
|
||||
rc = xioresolve(opt->value.u_string/*ifaddr*/, NULL,
|
||||
rc = xioresolve(opt->value2.u_string/*ifaddr*/, NULL,
|
||||
sfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr2, &socklen2, sfd->para.socket.ip.ai_flags);
|
||||
|
@ -1361,7 +1455,7 @@ int xioapply_ip_add_source_membership(struct single *sfd, struct opt *opt) {
|
|||
}
|
||||
ip4_mreq_src.imr_interface = sockaddr2.ip4.sin_addr;
|
||||
/* third parameter is source address */
|
||||
rc = xioresolve(opt->value.u_string/*srcaddr*/, NULL,
|
||||
rc = xioresolve(opt->value3.u_string/*srcaddr*/, NULL,
|
||||
sfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr3, &socklen3, sfd->para.socket.ip.ai_flags);
|
||||
|
@ -1386,6 +1480,8 @@ int xioapply_ip_add_source_membership(struct single *sfd, struct opt *opt) {
|
|||
|
||||
#endif /* HAVE_STRUCT_IP_MREQ_SOURCE */
|
||||
|
||||
#endif /* _WITH_IP4 */
|
||||
|
||||
|
||||
#if WITH_RESOLVE
|
||||
#if HAVE_RESOLV_H
|
||||
|
|
1
xio-ip.h
1
xio-ip.h
|
@ -49,6 +49,7 @@ extern const struct optdesc opt_res_nsaddr;
|
|||
|
||||
extern int xioinit_ip(int *pf, char ipv);
|
||||
|
||||
extern int retropt_bind_ip(struct opt *opts, int af, int socktype, int ipproto, struct addrinfo ***bindlist, int feats, const int ai_flags[2]);
|
||||
extern int xiogetaddrinfo(const char *node, const char *service, int family, int socktype, int protocol, struct addrinfo ***ai_sorted, const int ai_flags[2]);
|
||||
extern void xiofreeaddrinfo(struct addrinfo **ai_sorted);
|
||||
extern int _xio_sort_ip_addresses(struct addrinfo *themlist, struct addrinfo **ai_sorted);
|
||||
|
|
|
@ -23,7 +23,7 @@ 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_PREBIND, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_V6ONLY };
|
||||
#endif
|
||||
#ifdef IPV6_JOIN_GROUP
|
||||
#if defined(HAVE_STRUCT_IP_MREQ) || defined(HAVE_STRUCT_IP_MREQN)
|
||||
const struct optdesc opt_ipv6_join_group = { "ipv6-join-group", "join-group", OPT_IPV6_JOIN_GROUP, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SPEC, SOL_IPV6, IPV6_JOIN_GROUP };
|
||||
#endif
|
||||
#ifdef MCAST_JOIN_SOURCE_GROUP
|
||||
|
@ -249,7 +249,7 @@ int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range) {
|
|||
|
||||
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
|
||||
/* provides info about the ancillary message:
|
||||
converts the ancillary message in *cmsg into a form useable for further
|
||||
converts the ancillary message in *cmsg into a form usable 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
|
||||
|
|
444
xio-ipapp.c
444
xio-ipapp.c
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "xiosysincludes.h"
|
||||
|
||||
#if WITH_TCP || WITH_UDP
|
||||
#if WITH_TCP || WITH_UDP || WITH_SCTP || WITH_DCCP || WITH_UDPLITE
|
||||
|
||||
#include "xioopen.h"
|
||||
#include "xio-socket.h"
|
||||
|
@ -19,7 +19,8 @@ const struct optdesc opt_sourceport = { "sourceport", "sp", OPT_SOURCEPORT
|
|||
/*const struct optdesc opt_port = { "port", NULL, OPT_PORT, GROUP_IPAPP, PH_BIND, TYPE_USHORT, OFUNC_SPEC };*/
|
||||
const struct optdesc opt_lowport = { "lowport", NULL, OPT_LOWPORT, GROUP_IPAPP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
|
||||
|
||||
#if WITH_IP4
|
||||
|
||||
#if _WITH_IP4 || _WITH_IP6
|
||||
/* we expect the form "host:port" */
|
||||
int xioopen_ipapp_connect(
|
||||
int argc,
|
||||
|
@ -31,20 +32,18 @@ int xioopen_ipapp_connect(
|
|||
{
|
||||
struct single *sfd = &xxfd->stream;
|
||||
struct opt *opts0 = NULL;
|
||||
const char *hostname = argv[1], *portname = argv[2];
|
||||
int pf = addrdesc->arg3;
|
||||
int socktype = addrdesc->arg1;
|
||||
int ipproto = addrdesc->arg2;
|
||||
int pf = addrdesc->arg3;
|
||||
const char *hostname = argv[1], *portname = argv[2];
|
||||
bool dofork = false;
|
||||
int maxchildren = 0;
|
||||
union sockaddr_union us_sa, *us = &us_sa;
|
||||
socklen_t uslen = sizeof(us_sa);
|
||||
struct addrinfo **themarr, *themp;
|
||||
char infobuff[256];
|
||||
struct addrinfo **bindarr = NULL;
|
||||
struct addrinfo **themarr = NULL;
|
||||
uint16_t bindport = 0;
|
||||
bool needbind = false;
|
||||
bool lowport = false;
|
||||
int level;
|
||||
int i;
|
||||
int level = E_ERROR;
|
||||
int result;
|
||||
|
||||
if (argc != 3) {
|
||||
|
@ -52,97 +51,84 @@ int xioopen_ipapp_connect(
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
if (sfd->howtoend == END_UNSPEC)
|
||||
sfd->howtoend = END_SHUTDOWN;
|
||||
/* Apply and retrieve some options */
|
||||
result = _xioopen_ipapp_init(sfd, xioflags, opts,
|
||||
&dofork, &maxchildren,
|
||||
&pf, &socktype, &ipproto);
|
||||
if (result != STAT_OK)
|
||||
return result;
|
||||
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
opts0 = opts; /* save remaining options for each loop */
|
||||
opts = NULL;
|
||||
|
||||
retropt_bool(opts, OPT_FORK, &dofork);
|
||||
if (dofork) {
|
||||
if (!(xioflags & XIO_MAYFORK)) {
|
||||
Error("option fork not allowed here");
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
sfd->flags |= XIO_DOESFORK;
|
||||
}
|
||||
Notice2("opening connection to %s:%s", hostname, portname);
|
||||
|
||||
retropt_int(opts, OPT_MAX_CHILDREN, &maxchildren);
|
||||
|
||||
if (! dofork && maxchildren) {
|
||||
Error("option max-children not allowed without option fork");
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
if (_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
|
||||
sfd->para.socket.ip.ai_flags,
|
||||
&themarr, us, &uslen, &needbind, &lowport,
|
||||
socktype) != STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
if (dofork) {
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
if (xioparms.logopt == 'm') {
|
||||
Info("starting connect loop, switching to syslog");
|
||||
diag_set('y', xioparms.syslogfac); xioparms.logopt = 'y';
|
||||
} else {
|
||||
Info("starting connect loop");
|
||||
}
|
||||
|
||||
do { /* loop over retries, and forks */
|
||||
|
||||
/* Loop over themarr (which had been "ai_sorted") */
|
||||
result = STAT_RETRYLATER;
|
||||
i = 0;
|
||||
themp = themarr[i++];
|
||||
while (themp != NULL) {
|
||||
Notice1("opening connection to %s",
|
||||
sockaddr_info(themp->ai_addr, themp->ai_addrlen,
|
||||
infobuff, sizeof(infobuff)));
|
||||
do { /* loop over retries and/or forks */
|
||||
int _errno;
|
||||
|
||||
#if WITH_RETRY
|
||||
if (sfd->forever || sfd->retry) {
|
||||
level = E_INFO;
|
||||
} else if (themarr[i] != NULL) {
|
||||
level = E_WARN;
|
||||
} else
|
||||
if (sfd->forever || sfd->retry) {
|
||||
level = E_NOTICE;
|
||||
} else
|
||||
#endif /* WITH_RETRY */
|
||||
level = E_ERROR;
|
||||
level = E_WARN;
|
||||
|
||||
result =
|
||||
_xioopen_connect(sfd,
|
||||
needbind?us:NULL, uslen,
|
||||
themp->ai_addr, themp->ai_addrlen,
|
||||
opts, pf?pf:themp->ai_family, socktype, ipproto,
|
||||
lowport, level);
|
||||
if (result == STAT_OK)
|
||||
break;
|
||||
themp = themarr[i++];
|
||||
if (themp == NULL) {
|
||||
result = STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
opts = copyopts(opts0, GROUP_ALL);
|
||||
|
||||
result =
|
||||
_xioopen_ipapp_prepare(&opts, opts0, hostname, portname,
|
||||
pf, socktype, ipproto,
|
||||
sfd->para.socket.ip.ai_flags,
|
||||
&themarr, &bindarr, &bindport, &needbind, &lowport);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry) {
|
||||
--sfd->retry;
|
||||
if (result == STAT_RETRYLATER) {
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER)
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
dropopts(opts, PH_ALL); free(opts); opts = copyopts(opts0, GROUP_ALL);
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
default:
|
||||
/* FALLTHROUGH */
|
||||
case STAT_NORETRY:
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
free(opts0);free(opts);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
result =
|
||||
_xioopen_ipapp_connect(sfd, hostname, opts, themarr,
|
||||
needbind, bindarr, bindport, lowport, level);
|
||||
_errno = errno;
|
||||
if (bindarr != NULL)
|
||||
xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER) {
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
Error4("%s:%s:%s: %s", argv[0], argv[1], argv[2],
|
||||
_errno?strerror(_errno):"(See above)");
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -155,16 +141,18 @@ int xioopen_ipapp_connect(
|
|||
so Notice is too weak */
|
||||
}
|
||||
while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
|
||||
if (sfd->forever || --sfd->retry) {
|
||||
Nanosleep(&sfd->intervall, NULL); continue;
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
continue;
|
||||
}
|
||||
xiofreeaddrinfo(themarr);
|
||||
free(opts0);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
if (pid == 0) { /* child process */
|
||||
sfd->forever = false; sfd->retry = 0;
|
||||
sfd->forever = false;
|
||||
sfd->retry = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -176,107 +164,269 @@ int xioopen_ipapp_connect(
|
|||
Info1("all %d allowed children are active, waiting", maxchildren);
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
dropopts(opts, PH_ALL); free(opts); opts = copyopts(opts0, GROUP_ALL);
|
||||
freeopts(opts);
|
||||
continue; /* with next socket() bind() connect() */
|
||||
} else
|
||||
#endif /* WITH_RETRY */
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
} while (true); /* end of loop over retries and/or forks */
|
||||
/* only "active" process breaks (master without fork, or child) */
|
||||
xiofreeaddrinfo(themarr);
|
||||
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0) {
|
||||
free(opts0);free(opts);
|
||||
return result;
|
||||
}
|
||||
free(opts0); free(opts);
|
||||
return 0;
|
||||
Notice2("successfully connected to %s:%s", hostname, portname);
|
||||
|
||||
result = _xio_openlate(sfd, opts);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* returns STAT_OK on success or some other value on failure
|
||||
/* This function performs static initializations for addresses like TCP-CONNECT
|
||||
before start of the outer loop:
|
||||
it retrieves some options
|
||||
returns STAT_OK on success or some other value on failure;
|
||||
applies and consumes the following options:
|
||||
PH_INIT, OPT_FORK, OPT_MAX_CHILDREN, OPT_PROTOCOL_FAMILY, OPT_SO_TYPE,
|
||||
OPT_SO_PROTOTYPE
|
||||
*/
|
||||
int _xioopen_ipapp_init(
|
||||
struct single *sfd,
|
||||
int xioflags,
|
||||
struct opt *opts,
|
||||
bool *dofork,
|
||||
int *maxchildren,
|
||||
int *pf,
|
||||
int *socktype,
|
||||
int *ipproto)
|
||||
{
|
||||
if (sfd->howtoend == END_UNSPEC)
|
||||
sfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
if (applyopts(sfd, -1, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
|
||||
retropt_bool(opts, OPT_FORK, dofork);
|
||||
if (dofork) {
|
||||
if (!(xioflags & XIO_MAYFORK)) {
|
||||
Error1("%s: option fork not allowed here", sfd->addr->defname);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
sfd->flags |= XIO_DOESFORK;
|
||||
}
|
||||
|
||||
retropt_int(opts, OPT_MAX_CHILDREN, maxchildren);
|
||||
if (! dofork && maxchildren) {
|
||||
Error1("%s: option max-children not allowed without option fork", sfd->addr->defname);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
retropt_socket_pf(opts, pf);
|
||||
retropt_int(opts, OPT_SO_TYPE, socktype);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, ipproto);
|
||||
|
||||
if (dofork) {
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
}
|
||||
|
||||
if (xioparms.logopt == 'm') {
|
||||
Info("starting connect loop, switching to syslog");
|
||||
diag_set('y', xioparms.syslogfac);
|
||||
xioparms.logopt = 'y';
|
||||
} else {
|
||||
Info("starting connect loop");
|
||||
}
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
||||
/* This function performs preparations for addresses like TCP-CONNECT
|
||||
at the beginning of the outer (retry/fork) loop:
|
||||
it evaluates some options and performs name resolution of both server
|
||||
(target, "them") address and bind ("us") address.
|
||||
It is intended to be invoked before the connect loop starts;
|
||||
returns STAT_OK on success or some other value on failure;
|
||||
applies and consumes the following options:
|
||||
PH_EARLY
|
||||
OPT_PROTOCOL_FAMILY, OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT
|
||||
*/
|
||||
int
|
||||
_xioopen_ipapp_prepare(
|
||||
struct opt *opts,
|
||||
struct opt **opts0,
|
||||
const char *hostname,
|
||||
const char *portname,
|
||||
int *pf,
|
||||
int protocol,
|
||||
const int ai_flags[2],
|
||||
struct addrinfo ***themarr,
|
||||
union sockaddr_union *us,
|
||||
socklen_t *uslen,
|
||||
bool *needbind,
|
||||
bool *lowport,
|
||||
int socktype) {
|
||||
OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT
|
||||
returns STAT_OK, STAT_RETRYLATER, or STAT_NORETRY (+errno)
|
||||
*/
|
||||
int _xioopen_ipapp_prepare(
|
||||
struct opt **opts,
|
||||
struct opt *opts0,
|
||||
const char *hostname,
|
||||
const char *portname,
|
||||
int pf,
|
||||
int socktype,
|
||||
int protocol,
|
||||
const int ai_flags[2],
|
||||
struct addrinfo ***themarr, /* always from getaddrinfo(); xiofreeaddrinfo()! */
|
||||
struct addrinfo ***bindarr, /* on bind from getaddrinfo(); xiofreeaddrinfo()! */
|
||||
uint16_t *bindport, /* for bind without address */
|
||||
bool *needbind,
|
||||
bool *lowport)
|
||||
{
|
||||
uint16_t port;
|
||||
int rc;
|
||||
|
||||
retropt_socket_pf(opts, pf);
|
||||
*opts = copyopts(opts0, GROUP_ALL);
|
||||
|
||||
if (hostname != NULL || portname != NULL) {
|
||||
rc = xiogetaddrinfo(hostname, portname, *pf, socktype, protocol,
|
||||
rc = xiogetaddrinfo(hostname, portname, pf, socktype, protocol,
|
||||
themarr, ai_flags);
|
||||
if (rc == EAI_AGAIN) {
|
||||
Warn4("_xioopen_ipapp_prepare(node=\"%s\", service=\"%s\", pf=%d, ...): %s",
|
||||
hostname?hostname:"NULL", portname?portname:"NULL",
|
||||
*pf, gai_strerror(rc));
|
||||
pf, gai_strerror(rc));
|
||||
errno = EAGAIN;
|
||||
return STAT_RETRYLATER;
|
||||
} else if (rc != 0) {
|
||||
Error4("_xioopen_ipapp_prepare(node=\"%s\", service=\"%s\", pf=%d, ...): %s",
|
||||
hostname?hostname:"NULL", portname?portname:"NULL",
|
||||
*pf, (rc == EAI_SYSTEM)?strerror(errno):gai_strerror(rc));
|
||||
pf, (rc == EAI_SYSTEM)?strerror(errno):gai_strerror(rc));
|
||||
errno = 0; /* unspecified */
|
||||
return STAT_NORETRY; /*! STAT_RETRYLATER? */
|
||||
}
|
||||
}
|
||||
|
||||
applyopts(NULL, -1, opts, PH_EARLY);
|
||||
applyopts(NULL, -1, *opts, PH_EARLY);
|
||||
|
||||
/* 3 means: IP address AND port accepted */
|
||||
if (retropt_bind(opts, (*pf!=PF_UNSPEC)?*pf:(**themarr)->ai_family,
|
||||
socktype, protocol, (struct sockaddr *)us, uslen, 3,
|
||||
ai_flags)
|
||||
if (retropt_bind_ip(*opts, pf, socktype, protocol, bindarr, 3, ai_flags)
|
||||
!= STAT_NOACTION) {
|
||||
*needbind = true;
|
||||
} else {
|
||||
switch ((*pf!=PF_UNSPEC)?*pf:(**themarr)->ai_family) {
|
||||
#if WITH_IP4
|
||||
case PF_INET: socket_in_init(&us->ip4); *uslen = sizeof(us->ip4); break;
|
||||
#endif /* WITH_IP4 */
|
||||
#if WITH_IP6
|
||||
case PF_INET6: socket_in6_init(&us->ip6); *uslen = sizeof(us->ip6); break;
|
||||
#endif /* WITH_IP6 */
|
||||
default: Error("unsupported protocol family");
|
||||
}
|
||||
}
|
||||
|
||||
if (retropt_2bytes(opts, OPT_SOURCEPORT, &port) >= 0) {
|
||||
switch ((*pf!=PF_UNSPEC)?*pf:(**themarr)->ai_family) {
|
||||
if (retropt_2bytes(*opts, OPT_SOURCEPORT, &port) >= 0) {
|
||||
if (*bindarr) {
|
||||
struct addrinfo **bindp;
|
||||
bindp = *bindarr;
|
||||
switch ((*bindp)->ai_family) {
|
||||
#if WITH_IP4
|
||||
case PF_INET: us->ip4.sin_port = htons(port); break;
|
||||
case PF_INET: ((struct sockaddr_in *)(*bindp)->ai_addr)->sin_port = htons(port); break;
|
||||
#endif /* WITH_IP4 */
|
||||
#if WITH_IP6
|
||||
case PF_INET6: us->ip6.sin6_port = htons(port); break;
|
||||
case PF_INET6: ((struct sockaddr_in6 *)(*bindp)->ai_addr)->sin6_port = htons(port); break;
|
||||
#endif /* WITH_IP6 */
|
||||
default: Error("unsupported protocol family");
|
||||
default:
|
||||
Error("unsupported protocol family");
|
||||
errno = EPROTONOSUPPORT;
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
} else {
|
||||
*bindport = port;
|
||||
}
|
||||
*needbind = true;
|
||||
}
|
||||
|
||||
retropt_bool(opts, OPT_LOWPORT, lowport);
|
||||
|
||||
*opts0 = copyopts(opts, GROUP_ALL);
|
||||
retropt_bool(*opts, OPT_LOWPORT, lowport);
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
#endif /* WITH_IP4 */
|
||||
|
||||
#endif /* _WITH_IP4 || _WITH_IP6 */
|
||||
|
||||
|
||||
/* Tries to connect to the addresses in themarr, for each one it tries to bind
|
||||
to the addresses in bindarr.
|
||||
Ends on success or when all attempts failed.
|
||||
Returns STAT_OK on success, or STAT_RETRYLATER (+errno) on failure. */
|
||||
int _xioopen_ipapp_connect(struct single *sfd,
|
||||
const char *hostname,
|
||||
struct opt *opts,
|
||||
struct addrinfo **themarr,
|
||||
bool needbind,
|
||||
struct addrinfo **bindarr,
|
||||
uint16_t bindport,
|
||||
bool lowport,
|
||||
int level)
|
||||
{
|
||||
struct addrinfo **themp;
|
||||
struct addrinfo **bindp;
|
||||
union sockaddr_union bindaddr = {0};
|
||||
union sockaddr_union *bindaddrp = NULL;
|
||||
socklen_t bindlen = 0;
|
||||
char infobuff[256];
|
||||
int _errno;
|
||||
int result = STAT_OK;
|
||||
|
||||
--level;
|
||||
|
||||
/* Loop over server addresses (themarr) */
|
||||
themp = themarr;
|
||||
while (*themp != NULL) {
|
||||
Notice1("opening connection to %s",
|
||||
sockaddr_info((*themp)->ai_addr, (*themp)->ai_addrlen,
|
||||
infobuff, sizeof(infobuff)));
|
||||
|
||||
if (*(themp+1) == NULL) {
|
||||
++level; /* last attempt */
|
||||
}
|
||||
|
||||
/* Loop over array (list) of bind addresses */
|
||||
if (needbind && bindarr != NULL) {
|
||||
/* Bind by hostname, use resolvers results list */
|
||||
bindp = bindarr;
|
||||
while (*bindp != NULL) {
|
||||
if ((*bindp)->ai_family == (*themp)->ai_family)
|
||||
break;
|
||||
++bindp;
|
||||
}
|
||||
if (*bindp == NULL) {
|
||||
Warn3("%s: No bind address with matching address family (%d) of %s available",
|
||||
sfd->addr->defname, (*themp)->ai_family, hostname);
|
||||
++themp;
|
||||
if ((*themp) == NULL) {
|
||||
result = STAT_RETRYLATER;
|
||||
}
|
||||
_errno = ENOPROTOOPT;
|
||||
continue;
|
||||
}
|
||||
bindaddrp = (union sockaddr_union *)(*bindp)->ai_addr;
|
||||
bindlen = (*bindp)->ai_addrlen;
|
||||
} else if (needbind && bindport) {
|
||||
/* Bind by sourceport option */
|
||||
switch ((*themp)->ai_family) {
|
||||
#if WITH_IP4
|
||||
case PF_INET:
|
||||
bindaddr.ip4.sin_family = (*themp)->ai_family;
|
||||
bindaddr.ip4.sin_port = htons(bindport);
|
||||
bindaddrp = &bindaddr;
|
||||
bindlen = sizeof(bindaddr.ip4);
|
||||
break;
|
||||
#endif
|
||||
#if WITH_IP6
|
||||
case PF_INET6:
|
||||
bindaddr.ip6.sin6_family = (*themp)->ai_family;
|
||||
bindaddr.ip6.sin6_port = htons(bindport);
|
||||
bindaddrp = &bindaddr;
|
||||
bindlen = sizeof(bindaddr.ip6);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
result =
|
||||
_xioopen_connect(sfd,
|
||||
bindaddrp, bindlen,
|
||||
(*themp)->ai_addr, (*themp)->ai_addrlen,
|
||||
opts, /*pf?pf:*/(*themp)->ai_family, (*themp)->ai_socktype, (*themp)->ai_protocol,
|
||||
lowport, level);
|
||||
if (result == STAT_OK)
|
||||
break;
|
||||
_errno = errno;
|
||||
++themp;
|
||||
if (*themp == NULL)
|
||||
result = STAT_RETRYLATER;
|
||||
} /* end of loop over target addresses */
|
||||
|
||||
if (result != STAT_OK)
|
||||
errno = _errno;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#if WITH_TCP && WITH_LISTEN
|
||||
|
@ -303,7 +453,7 @@ int _xioopen_ipapp_listen_prepare(
|
|||
|
||||
retropt_string(opts, OPT_BIND, &bindname);
|
||||
|
||||
/* Set AI_PASSIVE, except when it is explicitely disabled */
|
||||
/* Set AI_PASSIVE, except when it is explicitly disabled */
|
||||
ai_flags2[0] = ai_flags[0];
|
||||
ai_flags2[1] = ai_flags[1];
|
||||
if (!(ai_flags2[1] & AI_PASSIVE))
|
||||
|
@ -382,6 +532,6 @@ int xioopen_ipapp_listen(
|
|||
return result;
|
||||
return 0;
|
||||
}
|
||||
#endif /* WITH_IP4 && WITH_TCP && WITH_LISTEN */
|
||||
#endif /* WITH_TCP && WITH_LISTEN */
|
||||
|
||||
#endif /* WITH_TCP || WITH_UDP */
|
||||
#endif /* WITH_TCP || WITH_UDP || WITH_SCTP || WITH_DCCP || WITH_UDPLITE */
|
||||
|
|
|
@ -15,11 +15,9 @@ extern const struct optdesc opt_sourceport;
|
|||
extern const struct optdesc opt_lowport;
|
||||
|
||||
extern int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
|
||||
extern int _xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0, const char *hostname, const char *portname, int *pf, int protocol, const int ai_flags[2], struct addrinfo ***themlist, union sockaddr_union *us, socklen_t *uslen, bool *needbind, bool *lowport, int socktype);
|
||||
extern int _xioopen_ip4app_connect(const char *hostname, const char *portname,
|
||||
struct single *xfd,
|
||||
int socktype, int ipproto, void *protname,
|
||||
struct opt *opts);
|
||||
extern int _xioopen_ipapp_init(struct single *sfd, int xioflags, struct opt *opts, bool *dofork, int *maxchildren, int *pf, int *socktype, int *protocol);
|
||||
extern int _xioopen_ipapp_prepare(struct opt **opts, struct opt *opts0, const char *hostname, const char *portname, int pf, int socktype, int protocol, const int ai_flags[2], struct addrinfo ***themarr, struct addrinfo ***bindarr, uint16_t *bindport, bool *needbind, bool *lowport);
|
||||
extern int _xioopen_ipapp_connect(struct single *sfd, const char *hostname, struct opt *opts, struct addrinfo **themarr, bool needbind, struct addrinfo **bindarr, uint16_t bindport, bool lowport, int level);
|
||||
extern int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
|
||||
extern int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0, const char *portname, int *pf, int ipproto, const int ai_flags[2], union sockaddr_union *us, socklen_t *uslen, int socktype);
|
||||
|
||||
|
|
199
xio-openssl.c
199
xio-openssl.c
|
@ -5,7 +5,7 @@
|
|||
/* this file contains the implementation of the openssl addresses */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
#if WITH_OPENSSL /* make this address configure dependend */
|
||||
#if WITH_OPENSSL /* make this address configure dependent */
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
|||
(not only tcp, but also pipes, stdin, files...)
|
||||
for tcp we want to provide support for socks and proxy.
|
||||
read and write functions must use the openssl crypt versions.
|
||||
but currently only plain tcp4 is implemented.
|
||||
*/
|
||||
|
||||
/* Linux: "man 3 ssl" */
|
||||
|
@ -239,13 +238,13 @@ static int xioopen_openssl_connect(
|
|||
int socktype = SOCK_STREAM;
|
||||
int ipproto = IPPROTO_TCP;
|
||||
bool dofork = false;
|
||||
union sockaddr_union us_sa, *us = &us_sa;
|
||||
socklen_t uslen = sizeof(us_sa);
|
||||
struct addrinfo **themarr, *themp;
|
||||
int maxchildren = 0;
|
||||
struct addrinfo **bindarr = NULL;
|
||||
struct addrinfo **themarr = NULL;
|
||||
uint16_t bindport = 0;
|
||||
bool needbind = false;
|
||||
bool lowport = false;
|
||||
int level = E_ERROR;
|
||||
int i;
|
||||
SSL_CTX* ctx;
|
||||
bool opt_ver = true; /* verify peer certificate */
|
||||
char *opt_cert = NULL; /* file name of client certificate */
|
||||
|
@ -255,7 +254,7 @@ static int xioopen_openssl_connect(
|
|||
int result;
|
||||
|
||||
if (!(xioflags & XIO_MAYCONVERT)) {
|
||||
Error("address with data processing not allowed here");
|
||||
Error1("%s: address with data processing not allowed here", argv[0]);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
sfd->flags |= XIO_DOESCONVERT;
|
||||
|
@ -267,20 +266,12 @@ static int xioopen_openssl_connect(
|
|||
hostname = argv[1];
|
||||
portname = argv[2];
|
||||
if (hostname[0] == '\0') {
|
||||
/* we catch this explicitely because empty commonname (peername) disables
|
||||
/* We catch this explicitly because empty commonname (peername) disables
|
||||
commonName check of peer certificate */
|
||||
Error1("%s: empty host name", argv[0]);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
if (sfd->howtoend == END_UNSPEC)
|
||||
sfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
retropt_bool(opts, OPT_FORK, &dofork);
|
||||
|
||||
retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
|
||||
retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname);
|
||||
#if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name)
|
||||
|
@ -316,73 +307,83 @@ static int xioopen_openssl_connect(
|
|||
socktype = SOCK_DGRAM;
|
||||
ipproto = IPPROTO_UDP;
|
||||
}
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto);
|
||||
|
||||
result =
|
||||
_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
|
||||
sfd->para.socket.ip.ai_flags,
|
||||
&themarr, us, &uslen,
|
||||
&needbind, &lowport, socktype);
|
||||
if (result != STAT_OK) return STAT_NORETRY;
|
||||
/* Apply and retrieve some options */
|
||||
result = _xioopen_ipapp_init(sfd, xioflags, opts,
|
||||
&dofork, &maxchildren,
|
||||
&pf, &socktype, &ipproto);
|
||||
if (result != STAT_OK)
|
||||
return result;
|
||||
|
||||
if (xioparms.logopt == 'm') {
|
||||
Info("starting connect loop, switching to syslog");
|
||||
diag_set('y', xioparms.syslogfac); xioparms.logopt = 'y';
|
||||
} else {
|
||||
Info("starting connect loop");
|
||||
}
|
||||
opts0 = opts; /* save remaining options for each loop */
|
||||
opts = NULL;
|
||||
|
||||
do { /* loop over failed connect and SSL handshake attempts */
|
||||
Notice2("opening OpenSSL connection to %s:%s", hostname, portname);
|
||||
|
||||
/* Loop over themarr (which had been "ai_sorted") */
|
||||
i = 0;
|
||||
themp = themarr[i++];
|
||||
while (themp != NULL) {
|
||||
do { /* loop over retries (failed connect and SSL handshake attempts) and/or forks */
|
||||
int _errno;
|
||||
|
||||
#if WITH_RETRY
|
||||
if (sfd->forever || sfd->retry || themarr[i] != NULL) {
|
||||
level = E_INFO;
|
||||
} else
|
||||
if (sfd->forever || sfd->retry) {
|
||||
level = E_NOTICE;
|
||||
} else
|
||||
#endif /* WITH_RETRY */
|
||||
level = E_ERROR;
|
||||
level = E_WARN;
|
||||
|
||||
/* This cannot fork because we retrieved fork option above */
|
||||
result =
|
||||
_xioopen_connect(sfd,
|
||||
needbind?us:NULL, uslen,
|
||||
themp->ai_addr, themp->ai_addrlen,
|
||||
opts, pf?pf:themp->ai_addr->sa_family, socktype, ipproto, lowport, level);
|
||||
if (result == STAT_OK)
|
||||
break;
|
||||
themp = themarr[i++];
|
||||
if (themp == NULL) {
|
||||
result = STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
opts = copyopts(opts0, GROUP_ALL);
|
||||
|
||||
result =
|
||||
_xioopen_ipapp_prepare(&opts, opts0, hostname, portname,
|
||||
pf, socktype, ipproto,
|
||||
sfd->para.socket.ip.ai_flags,
|
||||
&themarr, &bindarr, &bindport, &needbind, &lowport);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry) {
|
||||
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER)
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
case STAT_NORETRY:
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
Notice2("opening connection to server %s:%s", hostname, portname);
|
||||
result =
|
||||
_xioopen_ipapp_connect(sfd, hostname, opts, themarr,
|
||||
needbind, bindarr, bindport, lowport, level);
|
||||
_errno = errno;
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER) {
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
--sfd->retry;
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
xiofreeaddrinfo(themarr);
|
||||
return STAT_NORETRY;
|
||||
#endif /* WITH_RETRY */
|
||||
default:
|
||||
xiofreeaddrinfo(themarr);
|
||||
return result;
|
||||
}
|
||||
/*! isn't this too early? */
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0) {
|
||||
xiofreeaddrinfo(themarr);
|
||||
Error4("%s:%s:%s: %s", argv[0], hostname, portname,
|
||||
_errno?strerror(_errno):"(See above)");
|
||||
freeopts(opts0);
|
||||
freeopts(opts);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -393,19 +394,19 @@ static int xioopen_openssl_connect(
|
|||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry) {
|
||||
Close(sfd->fd);
|
||||
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER) {
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
--sfd->retry;
|
||||
freeopts(opts);
|
||||
Close(sfd->fd);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
default:
|
||||
xiofreeaddrinfo(themarr);
|
||||
return STAT_NORETRY;
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (dofork) {
|
||||
|
@ -420,15 +421,19 @@ static int xioopen_openssl_connect(
|
|||
level = E_WARN;
|
||||
}
|
||||
while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
|
||||
if (sfd->forever || --sfd->retry) {
|
||||
Nanosleep(&sfd->intervall, NULL); continue;
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
if (pid == 0) { /* child process */
|
||||
sfd->forever = false; sfd->retry = 0;
|
||||
sfd->forever = false;
|
||||
sfd->retry = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -438,21 +443,29 @@ static int xioopen_openssl_connect(
|
|||
sfd->para.openssl.ssl = NULL;
|
||||
/* with and without retry */
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
||||
while (maxchildren > 0 && num_child >= maxchildren) {
|
||||
Info1("all %d allowed children are active, waiting", maxchildren);
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
freeopts(opts);
|
||||
continue; /* with next socket() bind() connect() */
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
break;
|
||||
|
||||
} while (true); /* drop out on success */
|
||||
xiofreeaddrinfo(themarr);
|
||||
|
||||
openssl_conn_loginfo(sfd->para.openssl.ssl);
|
||||
|
||||
free((void *)opt_commonname);
|
||||
free((void *)opt_snihost);
|
||||
|
||||
/* fill in the fd structure */
|
||||
return STAT_OK;
|
||||
Notice2("successfully connected to SSL server %s:%s", hostname, portname);
|
||||
|
||||
result = _xio_openlate(sfd, opts);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -702,7 +715,7 @@ int _xioopen_openssl_listen(struct single *sfd,
|
|||
const char *opt_commonname,
|
||||
SSL_CTX *ctx,
|
||||
int level) {
|
||||
char error_string[120];
|
||||
char error_string[256];
|
||||
unsigned long err;
|
||||
int errint, ret;
|
||||
|
||||
|
@ -764,7 +777,7 @@ int _xioopen_openssl_listen(struct single *sfd,
|
|||
while (err = ERR_get_error()) {
|
||||
ERR_error_string_n(err, error_string, sizeof(error_string));
|
||||
Msg4(level, "SSL_accept(): %s / %s / %s / %s", error_string,
|
||||
ERR_lib_error_string(err), ERR_func_error_string(err),
|
||||
ERR_lib_error_string(err), error_string,
|
||||
ERR_reason_error_string(err));
|
||||
}
|
||||
/* Msg1(level, "SSL_accept(): %s", ERR_error_string(e, buf));*/
|
||||
|
@ -793,7 +806,7 @@ int _xioopen_openssl_listen(struct single *sfd,
|
|||
|
||||
#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
|
||||
* SSL_COMP_add_compression_method(3), but the implementation is not compatible
|
||||
* with the standard (RFC3749).
|
||||
*/
|
||||
static int openssl_setup_compression(SSL_CTX *ctx, char *method)
|
||||
|
@ -1976,12 +1989,20 @@ static int xioSSL_set_fd(struct single *sfd, int level) {
|
|||
should not retry for any reason. */
|
||||
static int xioSSL_connect(struct single *sfd, const char *opt_commonname,
|
||||
bool opt_ver, int level) {
|
||||
char error_string[120];
|
||||
int errint, status, ret;
|
||||
sigset_t masksigs, oldsigs;
|
||||
char error_string[256];
|
||||
int errint, status, _errno, ret;
|
||||
unsigned long err;
|
||||
|
||||
sigemptyset(&masksigs);
|
||||
sigaddset(&masksigs, SIGCHLD);
|
||||
sigaddset(&masksigs, SIGUSR1);
|
||||
Sigprocmask(SIG_BLOCK, &masksigs, &oldsigs);
|
||||
/* connect via SSL by performing handshake */
|
||||
if ((ret = sycSSL_connect(sfd->para.openssl.ssl)) <= 0) {
|
||||
ret = sycSSL_connect(sfd->para.openssl.ssl);
|
||||
_errno = errno;
|
||||
Sigprocmask(SIG_SETMASK, &oldsigs, NULL);
|
||||
if (ret <= 0) {
|
||||
/*if (ERR_peek_error() == 0) Msg(level, "SSL_connect() failed");*/
|
||||
errint = SSL_get_error(sfd->para.openssl.ssl, ret);
|
||||
switch (errint) {
|
||||
|
@ -2005,14 +2026,14 @@ static int xioSSL_connect(struct single *sfd, const char *opt_commonname,
|
|||
if (ret == 0) {
|
||||
Msg(level, "SSL_connect(): socket closed by peer");
|
||||
} else if (ret == -1) {
|
||||
Msg1(level, "SSL_connect(): %s", strerror(errno));
|
||||
Msg1(level, "SSL_connect(): %s", strerror(_errno));
|
||||
}
|
||||
} else {
|
||||
Msg(level, "I/O error"); /*!*/
|
||||
while (err = ERR_get_error()) {
|
||||
ERR_error_string_n(err, error_string, sizeof(error_string));
|
||||
Msg4(level, "SSL_connect(): %s / %s / %s / %s", error_string,
|
||||
ERR_lib_error_string(err), ERR_func_error_string(err),
|
||||
ERR_lib_error_string(err), error_string,
|
||||
ERR_reason_error_string(err));
|
||||
}
|
||||
}
|
||||
|
@ -2037,7 +2058,7 @@ static int xioSSL_connect(struct single *sfd, const char *opt_commonname,
|
|||
/* on result < 0: errno is set (at least to EIO) */
|
||||
ssize_t xioread_openssl(struct single *pipe, void *buff, size_t bufsiz) {
|
||||
unsigned long err;
|
||||
char error_string[120];
|
||||
char error_string[256];
|
||||
int _errno = EIO; /* if we have no better idea about nature of error */
|
||||
int errint, ret;
|
||||
|
||||
|
@ -2072,7 +2093,7 @@ ssize_t xioread_openssl(struct single *pipe, void *buff, size_t bufsiz) {
|
|||
while (err = ERR_get_error()) {
|
||||
ERR_error_string_n(err, error_string, sizeof(error_string));
|
||||
Error4("SSL_read(): %s / %s / %s / %s", error_string,
|
||||
ERR_lib_error_string(err), ERR_func_error_string(err),
|
||||
ERR_lib_error_string(err), error_string,
|
||||
ERR_reason_error_string(err));
|
||||
}
|
||||
}
|
||||
|
@ -2098,7 +2119,7 @@ ssize_t xiopending_openssl(struct single *pipe) {
|
|||
/* on result < 0: errno is set (at least to EIO) */
|
||||
ssize_t xiowrite_openssl(struct single *pipe, const void *buff, size_t bufsiz) {
|
||||
unsigned long err;
|
||||
char error_string[120];
|
||||
char error_string[256];
|
||||
int _errno = EIO; /* if we have no better idea about nature of error */
|
||||
int errint, ret;
|
||||
|
||||
|
@ -2131,7 +2152,7 @@ ssize_t xiowrite_openssl(struct single *pipe, const void *buff, size_t bufsiz) {
|
|||
while (err = ERR_get_error()) {
|
||||
ERR_error_string_n(err, error_string, sizeof(error_string));
|
||||
Error4("SSL_write(): %s / %s / %s / %s", error_string,
|
||||
ERR_lib_error_string(err), ERR_func_error_string(err),
|
||||
ERR_lib_error_string(err), error_string,
|
||||
ERR_reason_error_string(err));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#ifndef __xio_openssl_included
|
||||
#define __xio_openssl_included 1
|
||||
|
||||
#if WITH_OPENSSL /* make this address configure dependend */
|
||||
#if WITH_OPENSSL /* make this address configure dependent */
|
||||
|
||||
#define SSLIO_BASE 0x53530000 /* "SSxx" */
|
||||
#define SSLIO_MASK 0xffff0000
|
||||
|
|
217
xio-posixmq.c
217
xio-posixmq.c
|
@ -15,18 +15,21 @@
|
|||
|
||||
#if WITH_POSIXMQ
|
||||
|
||||
static int _posixmq_unlink(
|
||||
const char *name,
|
||||
int level); /* message level on error */
|
||||
static int _posixmq_flush(struct single *sfd);
|
||||
static int _posixmq_unlink(const char *name, int level);
|
||||
|
||||
static int xioopen_posixmq(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
|
||||
|
||||
const struct addrdesc xioaddr_posixmq_bidir = { "POSIXMQ-BIDIRECTIONAL", 1+XIO_RDWR, xioopen_posixmq, GROUP_FD|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY, XIO_RDWR, 0, 0 HELP(":<mqname>") };
|
||||
const struct addrdesc xioaddr_posixmq_read = { "POSIXMQ-READ", 1+XIO_RDONLY, xioopen_posixmq, GROUP_FD|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY, XIO_RDONLY, 0, 0 HELP(":<mqname>") };
|
||||
const struct addrdesc xioaddr_posixmq_receive = { "POSIXMQ-RECEIVE", 1+XIO_RDONLY, xioopen_posixmq, GROUP_FD|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY|GROUP_CHILD, XIO_RDONLY, XIOREAD_RECV_ONESHOT, 0 HELP(":<mqname>") };
|
||||
const struct addrdesc xioaddr_posixmq_send = { "POSIXMQ-SEND", 1+XIO_WRONLY, xioopen_posixmq, GROUP_FD|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY|GROUP_CHILD, XIO_WRONLY, 0, 0 HELP(":<mqname>") };
|
||||
const struct addrdesc xioaddr_posixmq_bidir = { "POSIXMQ-BIDIRECTIONAL", 1+XIO_RDWR, xioopen_posixmq, GROUP_FD|GROUP_OPEN|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY, XIO_RDWR, 0, 0 HELP(":<mqname>") };
|
||||
const struct addrdesc xioaddr_posixmq_read = { "POSIXMQ-READ", 1+XIO_RDONLY, xioopen_posixmq, GROUP_FD|GROUP_OPEN|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY, XIO_RDONLY, 0, 0 HELP(":<mqname>") };
|
||||
const struct addrdesc xioaddr_posixmq_receive = { "POSIXMQ-RECEIVE", 1+XIO_RDONLY, xioopen_posixmq, GROUP_FD|GROUP_OPEN|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY|GROUP_CHILD, XIO_RDONLY, XIOREAD_RECV_ONESHOT, 0 HELP(":<mqname>") };
|
||||
const struct addrdesc xioaddr_posixmq_send = { "POSIXMQ-SEND", 1+XIO_WRONLY, xioopen_posixmq, GROUP_FD|GROUP_OPEN|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY|GROUP_CHILD, XIO_WRONLY, 0, 0 HELP(":<mqname>") };
|
||||
const struct addrdesc xioaddr_posixmq_write = { "POSIXMQ-WRITE", 1+XIO_WRONLY, xioopen_posixmq, GROUP_FD|GROUP_OPEN|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY|GROUP_CHILD, XIO_WRONLY, 0, 0 HELP(":<mqname>") };
|
||||
|
||||
const struct optdesc opt_posixmq_priority = { "posixmq-priority", "mq-pri", OPT_POSIXMQ_PRIORITY, GROUP_POSIXMQ, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, XIO_OFFSETOF(para.posixmq.prio), XIO_SIZEOF(para.posixmq.prio), 0 };
|
||||
const struct optdesc opt_posixmq_priority = { "posixmq-priority", "mq-prio", OPT_POSIXMQ_PRIORITY, GROUP_POSIXMQ, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, XIO_OFFSETOF(para.posixmq.prio), XIO_SIZEOF(para.posixmq.prio), 0 };
|
||||
const struct optdesc opt_posixmq_flush = { "posixmq-flush", "mq-flush", OPT_POSIXMQ_FLUSH, GROUP_POSIXMQ, PH_EARLY, TYPE_BOOL, OFUNC_SPEC, 0, 0, 0 };
|
||||
const struct optdesc opt_posixmq_maxmsg = { "posixmq-maxmsg", "mq-maxmsg", OPT_POSIXMQ_MAXMSG, GROUP_POSIXMQ, PH_OPEN, TYPE_LONG, OFUNC_SPEC, 0, 0, 0 };
|
||||
const struct optdesc opt_posixmq_msgsize = { "posixmq-msgsize", "mq-msgsize", OPT_POSIXMQ_MSGSIZE, GROUP_POSIXMQ, PH_OPEN, TYPE_LONG, OFUNC_SPEC, 0, 0, 0 };
|
||||
|
||||
/* _read(): open immediately, stay in transfer loop
|
||||
_recv(): wait until data (how we know there is??), oneshot, opt.fork
|
||||
|
@ -45,8 +48,18 @@ static int xioopen_posixmq(
|
|||
int dirs = addrdesc->arg1;
|
||||
int oneshot = addrdesc->arg2;
|
||||
bool opt_unlink_early = false;
|
||||
bool nonblock = 0;
|
||||
bool flush = false;
|
||||
long maxmsg;
|
||||
long msgsize;
|
||||
struct mq_attr attr = { 0 };
|
||||
bool setopts = false;
|
||||
int oflag;
|
||||
bool opt_o_creat = true;
|
||||
bool opt_o_excl = false;
|
||||
#ifdef O_CLOEXEC
|
||||
bool opt_o_cloexec = true;
|
||||
#endif
|
||||
mode_t opt_mode = 0666;
|
||||
mqd_t mqd;
|
||||
int _errno;
|
||||
|
@ -55,10 +68,6 @@ static int xioopen_posixmq(
|
|||
bool with_intv = false;
|
||||
int result = 0;
|
||||
|
||||
if (!xioparms.experimental) {
|
||||
Error1("%s: use option --experimental to acknowledge unmature state", argv[0]);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
if (argc != 2) {
|
||||
xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
|
||||
return STAT_NORETRY;
|
||||
|
@ -77,7 +86,10 @@ static int xioopen_posixmq(
|
|||
with_intv = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirs == XIO_RDWR) {
|
||||
/* Bidirectional ADDRESS in unidirectional mode? Adapt dirs */
|
||||
dirs = (xioflags & XIO_ACCMODE);
|
||||
}
|
||||
retropt_int(opts, OPT_MAX_CHILDREN, &maxchildren);
|
||||
if (! dofork && maxchildren) {
|
||||
Error("option max-children not allowed without option fork");
|
||||
|
@ -94,8 +106,54 @@ static int xioopen_posixmq(
|
|||
Error1("strdup(\"%s\"): out of memory", name);
|
||||
}
|
||||
|
||||
retropt_bool(opts, OPT_O_EXCL, &opt_o_excl);
|
||||
retropt_mode(opts, OPT_PERM, &opt_mode);
|
||||
retropt_bool(opts, OPT_O_CREAT, &opt_o_creat);
|
||||
retropt_bool(opts, OPT_O_EXCL, &opt_o_excl);
|
||||
#ifdef O_CLOEXEC
|
||||
retropt_bool(opts, OPT_O_CLOEXEC, &opt_o_cloexec);
|
||||
#endif
|
||||
retropt_mode(opts, OPT_PERM, &opt_mode);
|
||||
retropt_bool(opts, OPT_POSIXMQ_FLUSH, &flush);
|
||||
retropt_long(opts, OPT_POSIXMQ_MAXMSG, &maxmsg) ||
|
||||
(setopts = true);
|
||||
retropt_long(opts, OPT_POSIXMQ_MSGSIZE, &msgsize) ||
|
||||
(setopts = true);
|
||||
|
||||
/* When just one of mq-maxmsg and mq-msgsize options has been provided,
|
||||
we must nevertheless set the other option value in struct mq_attr.
|
||||
For this we have to find the default, read it from /proc fs */
|
||||
if (setopts) {
|
||||
int pfd;
|
||||
const static char *PROC_MAXMSG = "/proc/sys/fs/mqueue/msg_default";
|
||||
const static char *PROC_MSGSIZE = "/proc/sys/fs/mqueue/msgsize_default";
|
||||
char buff[21]; /* fit a 64bit num in decimal */
|
||||
ssize_t bytes;
|
||||
|
||||
if (maxmsg == 0) {
|
||||
if ((pfd = Open(PROC_MAXMSG, O_RDONLY, 0)) < 0) {
|
||||
Warn2("open(\"%s\", O_RDONLY, 0): %s", PROC_MAXMSG, strerror(errno));
|
||||
} else if ((bytes = Read(pfd, buff, sizeof(buff)-1)) < 0) {
|
||||
Warn4("read(%d /* \"%s\" */, buff, "F_Zd"): %s",
|
||||
pfd, PROC_MAXMSG, sizeof(buff)-1, strerror (errno));
|
||||
Close(pfd);
|
||||
} else {
|
||||
sscanf(buff, "%ld", &maxmsg);
|
||||
Close(pfd);
|
||||
}
|
||||
}
|
||||
|
||||
if (msgsize == 0) {
|
||||
if ((pfd = Open(PROC_MSGSIZE, O_RDONLY, 0)) < 0) {
|
||||
Warn2("open(\"%s\", O_RDONLY, 0): %s", PROC_MSGSIZE, strerror(errno));
|
||||
} else if ((bytes = Read(pfd, buff, sizeof(buff)-1)) < 0) {
|
||||
Warn4("read(%d /* \"%s\" */, buff, "F_Zd"): %s",
|
||||
pfd, PROC_MSGSIZE, sizeof(buff)-1, strerror (errno));
|
||||
Close(pfd);
|
||||
} else {
|
||||
sscanf(buff, "%ld", &msgsize);
|
||||
Close(pfd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
|
||||
if (opt_unlink_early) {
|
||||
|
@ -106,26 +164,65 @@ static int xioopen_posixmq(
|
|||
sfd->howtoend = END_CLOSE;
|
||||
sfd->dtype = XIODATA_POSIXMQ | oneshot;
|
||||
|
||||
oflag = O_CREAT;
|
||||
if (opt_o_excl) oflag |= O_EXCL;
|
||||
oflag = 0;
|
||||
if (opt_o_creat) oflag |= O_CREAT;
|
||||
if (opt_o_excl) oflag |= O_EXCL;
|
||||
#ifdef O_CLOEXEC
|
||||
if (opt_o_cloexec) oflag |= O_CLOEXEC; /* does not seem to work (Ubuntu-20) */
|
||||
#endif
|
||||
switch (dirs) {
|
||||
case XIO_RDWR: oflag |= O_RDWR; break;
|
||||
case XIO_RDONLY: oflag |= O_RDONLY; break;
|
||||
case XIO_WRONLY: oflag |= O_WRONLY; break;
|
||||
}
|
||||
if (retropt_bool(opts, OPT_O_NONBLOCK, &nonblock) >= 0 && nonblock)
|
||||
oflag |= O_NONBLOCK;
|
||||
|
||||
if (flush) {
|
||||
if (_posixmq_flush(sfd) != STAT_OK)
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
/* Now open the message queue */
|
||||
Debug3("mq_open(\"%s\", %d, "F_mode", NULL)", name, oflag, opt_mode);
|
||||
mqd = mq_open(name, oflag, opt_mode, NULL);
|
||||
if (setopts) {
|
||||
attr.mq_maxmsg = maxmsg;
|
||||
attr.mq_msgsize = msgsize;
|
||||
Debug8("%s: mq_open(\"%s\", "F_mode", "F_mode", {flags=%ld, maxmsg=%ld, msgsize=%ld, curmsgs=%ld} )", argv[0], name, oflag, opt_mode, attr.mq_flags, attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
|
||||
} else {
|
||||
Debug4("%s: mq_open(\"%s\", "F_mode", "F_mode", NULL)", argv[0], name, oflag, opt_mode);
|
||||
}
|
||||
mqd = mq_open(name, oflag, opt_mode, setopts ? &attr : NULL);
|
||||
_errno = errno;
|
||||
Debug1("mq_open() -> %d", mqd);
|
||||
if (mqd < 0) {
|
||||
Error3("%s: mq_open(\"%s\"): %s", argv[0], name, strerror(errno));
|
||||
if (setopts)
|
||||
Error9("%s: mq_open(\"%s\", "F_mode", "F_mode", {flags=%ld, maxmsg=%ld, msgsize=%ld, curmsgs=%ld} ): %s", argv[0], name, oflag, opt_mode, attr.mq_flags, attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs, strerror(errno));
|
||||
else
|
||||
Error5("%s: mq_open(\"%s\", "F_mode", "F_mode", NULL): %s", argv[0], name, oflag, opt_mode, strerror(errno));
|
||||
errno = _errno;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
/* applyopts_cloexec(mqd, opts); */ /* does not seem to work too (Ubuntu-20) */
|
||||
sfd->fd = mqd;
|
||||
|
||||
Debug1("mq_getattr(%d, ...)", mqd);
|
||||
if (mq_getattr(mqd, &attr) < 0) {
|
||||
Warn4("mq_getattr(%d[\"%s\"], %p): %s",
|
||||
mqd, sfd->para.posixmq.name, &attr, strerror(errno));
|
||||
mq_close(mqd);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
Info5("POSIXMQ queue \"%s\" attrs: { flags=%ld, maxmsg=%ld, msgsize=%ld, curmsgs=%ld }",
|
||||
name, attr.mq_flags, attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
|
||||
if (setopts) {
|
||||
if (attr.mq_maxmsg != maxmsg)
|
||||
Warn2("mq_open(): requested maxmsg=%ld, but result is %ld",
|
||||
maxmsg, attr.mq_maxmsg);
|
||||
if (attr.mq_msgsize != msgsize)
|
||||
Warn2("mq_open(): requested msgsize=%ld, but result is %ld",
|
||||
msgsize, attr.mq_msgsize);
|
||||
}
|
||||
|
||||
if (!dofork && !oneshot) {
|
||||
return STAT_OK;
|
||||
}
|
||||
|
@ -155,6 +252,8 @@ static int xioopen_posixmq(
|
|||
do {
|
||||
struct pollfd pollfd;
|
||||
|
||||
if (oflag & O_NONBLOCK)
|
||||
break;
|
||||
pollfd.fd = sfd->fd;
|
||||
pollfd.events = (dirs==XIO_RDONLY?POLLIN:POLLOUT);
|
||||
if (xiopoll(&pollfd, 1, NULL) > 0) {
|
||||
|
@ -231,6 +330,81 @@ static int xioopen_posixmq(
|
|||
}
|
||||
|
||||
|
||||
/* With option flush try to open the queue and "consume" its current contents */
|
||||
static int _posixmq_flush(
|
||||
struct single *sfd)
|
||||
{
|
||||
mqd_t mqd;
|
||||
struct mq_attr attr;
|
||||
void *buff;
|
||||
size_t bufsiz;
|
||||
int _errno;
|
||||
int p = 0; /* number of messages flushed */
|
||||
size_t b = 0; /* number of bytes flushed */
|
||||
|
||||
Info1("flushing POSIXMQ queue \"%s\"", sfd->para.posixmq.name);
|
||||
Debug1("mq_open(\"%s\", O_RDONLY|O_NONBLOCK, 0, NULL)",
|
||||
sfd->para.posixmq.name);
|
||||
mqd = mq_open(sfd->para.posixmq.name, O_RDONLY|O_NONBLOCK, 0, NULL);
|
||||
_errno = errno;
|
||||
Debug1("mq_open() -> %d", mqd);
|
||||
if (mqd < 0 && _errno == ENOENT) {
|
||||
Info("this queue does not exist, no need to flush it");
|
||||
return STAT_OK;
|
||||
}
|
||||
if (mqd < 0) {
|
||||
Warn2("mq_open(\"%s\", ...): %s", sfd->para.posixmq.name,
|
||||
strerror(_errno));
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
Debug1("mq_getattr(%d, ...)", mqd);
|
||||
if (mq_getattr(mqd, &attr) < 0) {
|
||||
Warn4("mq_getattr(%d[\"%s\"], %p): %s",
|
||||
mqd, sfd->para.posixmq.name, &attr, strerror(errno));
|
||||
mq_close(mqd);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
if (attr.mq_curmsgs == 0) {
|
||||
Info1("POSIXMQ \"%s\" is empty", sfd->para.posixmq.name);
|
||||
mq_close(mqd);
|
||||
return STAT_OK;
|
||||
}
|
||||
bufsiz = attr.mq_msgsize;
|
||||
if ((buff = Malloc(bufsiz)) == NULL) {
|
||||
mq_close(mqd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
/* Now read all messages to null */
|
||||
while (true) {
|
||||
ssize_t bytes;
|
||||
|
||||
Debug3("mq_receive(mqd=%d, %p, "F_Zu", {} )", mqd, buff, bufsiz);
|
||||
bytes = mq_receive(mqd, buff, bufsiz, &sfd->para.posixmq.prio);
|
||||
_errno = errno;
|
||||
Debug1("mq_receive() -> "F_Zd, bytes);
|
||||
errno = _errno;
|
||||
if (bytes == 0 || (bytes < 0 && _errno == EAGAIN)) {
|
||||
break;
|
||||
}
|
||||
if (bytes < 0) {
|
||||
Warn2("flushing POSIXMQ \"%s\" failed: %s",
|
||||
sfd->para.posixmq.name, strerror(_errno));
|
||||
free(buff);
|
||||
mq_close(mqd);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
++p;
|
||||
b += bytes;
|
||||
}
|
||||
Info3("flushed "F_Zu" bytes in %u packets from queue \"%s\"", b, p,
|
||||
sfd->para.posixmq.name);
|
||||
free(buff);
|
||||
mq_close(mqd);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
ssize_t xiowrite_posixmq(
|
||||
struct single *sfd,
|
||||
const void *buff,
|
||||
|
@ -283,6 +457,9 @@ ssize_t xioclose_posixmq(
|
|||
struct single *sfd)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (sfd->fd < 0)
|
||||
return 0;
|
||||
Debug1("xioclose_posixmq(): mq_close(%d)", sfd->fd);
|
||||
res = mq_close(sfd->fd);
|
||||
if (res < 0) {
|
||||
|
|
|
@ -9,8 +9,12 @@ extern const struct addrdesc xioaddr_posixmq_bidir;
|
|||
extern const struct addrdesc xioaddr_posixmq_read;
|
||||
extern const struct addrdesc xioaddr_posixmq_receive;
|
||||
extern const struct addrdesc xioaddr_posixmq_send;
|
||||
extern const struct addrdesc xioaddr_posixmq_write;
|
||||
|
||||
extern const struct optdesc opt_posixmq_maxmsg;
|
||||
extern const struct optdesc opt_posixmq_msgsize;
|
||||
extern const struct optdesc opt_posixmq_priority;
|
||||
extern const struct optdesc opt_posixmq_flush;
|
||||
|
||||
extern ssize_t xioread_posixmq(struct single *file, void *buff, size_t bufsiz);
|
||||
extern ssize_t xiopending_posixmq(struct single *pipe);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "xio-progcall.h"
|
||||
|
||||
#include "xio-socket.h"
|
||||
#include "xio-socketpair.h"
|
||||
|
||||
|
||||
/* these options are used by address pty too */
|
||||
|
@ -23,7 +24,7 @@ const struct optdesc opt_ptmx = { "ptmx", NULL, OPT_PTMX, GROUP_P
|
|||
#endif
|
||||
const struct optdesc opt_sitout_eio = { "sitout-eio", NULL, OPT_SITOUT_EIO, GROUP_PTY, PH_OFFSET, TYPE_TIMEVAL, OFUNC_OFFSET, XIO_OFFSETOF(para.exec.sitout_eio), XIO_SIZEOF(para.exec.sitout_eio) };
|
||||
|
||||
#if WITH_EXEC || WITH_SYSTEM
|
||||
#if WITH_EXEC || WITH_SYSTEM || WITH_SHELL
|
||||
|
||||
#define MAXPTYNAMELEN 64
|
||||
|
||||
|
@ -623,7 +624,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
*optsp = popts;
|
||||
return pid; /* indicate parent (main) process */
|
||||
}
|
||||
#endif /* WITH_EXEC || WITH_SYSTEM */
|
||||
#endif /* WITH_EXEC || WITH_SYSTEM || WITH_SHELL */
|
||||
|
||||
|
||||
int setopt_path(struct opt *opts, char **path) {
|
||||
|
|
237
xio-proxy.c
237
xio-proxy.c
|
@ -83,18 +83,18 @@ static int xioopen_proxy_connect(
|
|||
xiofile_t *xxfd,
|
||||
const struct addrdesc *addrdesc)
|
||||
{
|
||||
/* we expect the form: host:host:port */
|
||||
/* we expect the form: host:host:port */
|
||||
struct single *sfd = &xxfd->stream;
|
||||
struct opt *opts0 = NULL;
|
||||
struct proxyvars struct_proxyvars = { 0 }, *proxyvars = &struct_proxyvars;
|
||||
/* variables to be filled with address option values */
|
||||
bool dofork = false;
|
||||
int maxchildren = 0;
|
||||
/* */
|
||||
int pf = PF_UNSPEC;
|
||||
union sockaddr_union us_sa, *us = &us_sa;
|
||||
socklen_t uslen = sizeof(us_sa);
|
||||
struct addrinfo **themarr, *themp;
|
||||
int i;
|
||||
struct addrinfo **bindarr = NULL;
|
||||
struct addrinfo **themarr = NULL;
|
||||
uint16_t bindport = 0;
|
||||
const char *proxyname; char *proxyport = NULL;
|
||||
const char *targetname, *targetport;
|
||||
int ipproto = IPPROTO_TCP;
|
||||
|
@ -112,90 +112,123 @@ static int xioopen_proxy_connect(
|
|||
targetname = argv[2];
|
||||
targetport = argv[3];
|
||||
|
||||
if (sfd->howtoend == END_UNSPEC)
|
||||
sfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
applyopts(sfd, 1, opts, PH_INIT);
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
retropt_bool(opts, OPT_FORK, &dofork);
|
||||
|
||||
if (retropt_string(opts, OPT_PROXYPORT, &proxyport) < 0) {
|
||||
if ((proxyport = strdup(PROXYPORT)) == NULL) {
|
||||
errno = ENOMEM; return -1;
|
||||
}
|
||||
}
|
||||
|
||||
result = _xioopen_proxy_prepare(proxyvars, opts, targetname, targetport,
|
||||
sfd->para.socket.ip.ai_flags);
|
||||
if (result != STAT_OK)
|
||||
return result;
|
||||
|
||||
Notice4("opening connection to %s:%u via proxy %s:%s",
|
||||
proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
|
||||
|
||||
i = 0;
|
||||
do { /* loop over retries (failed connect and proxy-request attempts) */
|
||||
|
||||
level = E_INFO;
|
||||
|
||||
result =
|
||||
_xioopen_ipapp_prepare(opts, &opts0, proxyname, proxyport,
|
||||
&pf, ipproto,
|
||||
sfd->para.socket.ip.ai_flags,
|
||||
&themarr, us, &uslen,
|
||||
&needbind, &lowport, socktype);
|
||||
result =
|
||||
_xioopen_ipapp_init(sfd, xioflags, opts,
|
||||
&dofork, &maxchildren,
|
||||
&pf, &socktype, &ipproto);
|
||||
if (result != STAT_OK)
|
||||
return result;
|
||||
|
||||
/* Loop over themlist */
|
||||
i = 0;
|
||||
themp = themarr[i++];
|
||||
while (themp != NULL) {
|
||||
Notice4("opening connection to %s:%u via proxy %s:%s",
|
||||
proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
|
||||
#if WITH_RETRY
|
||||
if (sfd->forever || sfd->retry || themarr[i] != NULL) {
|
||||
level = E_INFO;
|
||||
} else
|
||||
#endif /* WITH_RETRY */
|
||||
level = E_ERROR;
|
||||
result = _xioopen_proxy_init(proxyvars, opts, targetname, targetport);
|
||||
if (result != STAT_OK)
|
||||
return result;
|
||||
|
||||
result =
|
||||
_xioopen_connect(sfd,
|
||||
needbind?us:NULL, uslen,
|
||||
themp->ai_addr, themp->ai_addrlen,
|
||||
opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
|
||||
if (result == STAT_OK)
|
||||
break;
|
||||
themp = themarr[i++];
|
||||
if (themp == NULL) {
|
||||
result = STAT_RETRYLATER;
|
||||
}
|
||||
opts0 = opts; /* save remaining options for each loop */
|
||||
opts = NULL;
|
||||
|
||||
Notice4("opening connection to %s:%s via proxy %s:%s",
|
||||
targetname, targetport, proxyname, proxyport);
|
||||
|
||||
do { /* loop over retries (failed connect and proxy-request attempts)
|
||||
and/or forks */
|
||||
int _errno;
|
||||
|
||||
#if WITH_RETRY
|
||||
if (sfd->forever || sfd->retry) {
|
||||
level = E_NOTICE;
|
||||
} else
|
||||
#endif /* WITH_RETRY */
|
||||
level = E_WARN;
|
||||
|
||||
opts = copyopts(opts0, GROUP_ALL);
|
||||
|
||||
result =
|
||||
_xioopen_ipapp_prepare(&opts, opts0, proxyname, proxyport,
|
||||
pf, socktype, ipproto,
|
||||
sfd->para.socket.ip.ai_flags,
|
||||
&themarr, &bindarr, &bindport, &needbind, &lowport);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry) {
|
||||
--sfd->retry;
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER)
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
default:
|
||||
/* FALLTHROUGH */
|
||||
case STAT_NORETRY:
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
xiofreeaddrinfo(themarr);
|
||||
applyopts(sfd, -1, opts, PH_ALL);
|
||||
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||
result =
|
||||
_xioopen_proxy_prepare(proxyvars, opts, targetname, targetport,
|
||||
sfd->para.socket.ip.ai_flags);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER)
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
Notice2("opening connection to proxy %s:%s", proxyname, proxyport);
|
||||
result =
|
||||
_xioopen_ipapp_connect(sfd, proxyname, opts, themarr,
|
||||
needbind, bindarr, bindport, lowport, level);
|
||||
_errno = errno;
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER)
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
Error4("%s:%s:...,proxyport=%s: %s", argv[0], proxyname, proxyport,
|
||||
_errno?strerror(_errno):"(See above)");
|
||||
freeopts(opts0);
|
||||
freeopts(opts);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = _xioopen_proxy_connect(sfd, proxyvars, level);
|
||||
switch (result) {
|
||||
|
@ -204,11 +237,16 @@ static int xioopen_proxy_connect(
|
|||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER) Nanosleep(&sfd->intervall, NULL);
|
||||
if (result == STAT_RETRYLATER)
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -225,21 +263,32 @@ static int xioopen_proxy_connect(
|
|||
}
|
||||
while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
|
||||
if (sfd->forever || --sfd->retry) {
|
||||
Nanosleep(&sfd->intervall, NULL); continue;
|
||||
if (sfd->retry > 0)
|
||||
--sfd->retry;
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
if (pid == 0) { /* child process */
|
||||
sfd->forever = false; sfd->retry = 0;
|
||||
sfd->forever = false;
|
||||
sfd->retry = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* parent process */
|
||||
Close(sfd->fd);
|
||||
/* With and without retry */
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
dropopts(opts, PH_ALL);
|
||||
opts = copyopts(opts0, GROUP_ALL);
|
||||
while (maxchildren > 0 && num_child >= maxchildren) {
|
||||
Info1("all %d allowed children are active, waiting", maxchildren);
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
freeopts(opts);
|
||||
continue;
|
||||
} else
|
||||
#endif /* WITH_RETRY */
|
||||
|
@ -248,25 +297,25 @@ static int xioopen_proxy_connect(
|
|||
}
|
||||
|
||||
} while (true); /* end of complete open loop - drop out on success */
|
||||
/* Only "active" process breaks (master without fork, or child) */
|
||||
|
||||
Notice4("successfully connected to %s:%u via proxy %s:%s",
|
||||
proxyvars->targetaddr, proxyvars->targetport,
|
||||
proxyname, proxyport);
|
||||
|
||||
return 0;
|
||||
result = _xio_openlate(sfd, opts);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int _xioopen_proxy_prepare(
|
||||
int _xioopen_proxy_init(
|
||||
struct proxyvars *proxyvars,
|
||||
struct opt *opts,
|
||||
const char *targetname,
|
||||
const char *targetport,
|
||||
const int ai_flags[2]) {
|
||||
union sockaddr_union host;
|
||||
socklen_t socklen = sizeof(host);
|
||||
int rc;
|
||||
|
||||
const char *targetport)
|
||||
{
|
||||
retropt_bool(opts, OPT_IGNORECR, &proxyvars->ignorecr);
|
||||
retropt_bool(opts, OPT_PROXY_RESOLVE, &proxyvars->doresolve);
|
||||
retropt_string(opts, OPT_HTTP_VERSION, &proxyvars->version);
|
||||
|
@ -316,6 +365,28 @@ int _xioopen_proxy_prepare(
|
|||
Close(authfd);
|
||||
}
|
||||
|
||||
if (!proxyvars->doresolve) {
|
||||
proxyvars->targetaddr = strdup(targetname);
|
||||
if (proxyvars->targetaddr == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", targetname);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
int _xioopen_proxy_prepare(
|
||||
struct proxyvars *proxyvars,
|
||||
struct opt *opts,
|
||||
const char *targetname,
|
||||
const char *targetport,
|
||||
const int ai_flags[2])
|
||||
{
|
||||
union sockaddr_union host;
|
||||
socklen_t socklen = sizeof(host);
|
||||
int rc;
|
||||
|
||||
if (proxyvars->doresolve) {
|
||||
/* currently we only resolve to IPv4 addresses. This is in accordance to
|
||||
RFC 2396; however once it becomes clear how IPv6 addresses should be
|
||||
|
@ -325,6 +396,10 @@ int _xioopen_proxy_prepare(
|
|||
&host, &socklen, ai_flags);
|
||||
if (rc != STAT_OK) {
|
||||
proxyvars->targetaddr = strdup(targetname);
|
||||
if (proxyvars->targetaddr == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", targetname);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
} else {
|
||||
#define LEN 16 /* www.xxx.yyy.zzz\0 */
|
||||
if ((proxyvars->targetaddr = Malloc(LEN)) == NULL) {
|
||||
|
@ -337,8 +412,6 @@ int _xioopen_proxy_prepare(
|
|||
((unsigned char *)&host.ip4.sin_addr.s_addr)[3]);
|
||||
#undef LEN
|
||||
}
|
||||
} else {
|
||||
proxyvars->targetaddr = strdup(targetname);
|
||||
}
|
||||
|
||||
proxyvars->targetport = htons(parseport(targetport, IPPROTO_TCP));
|
||||
|
@ -376,7 +449,7 @@ int _xioopen_proxy_connect(struct single *sfd,
|
|||
* xiosanitize(request, strlen(request), textbuff) = '\0';
|
||||
Info1("sending \"%s\"", textbuff);
|
||||
/* write errors are assumed to always be hard errors, no retry */
|
||||
if (writefull(sfd->fd, request, strlen(request)) < 0) {
|
||||
if (writefull(sfd->fd, request, strlen(request), NULL) < 0) {
|
||||
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||
sfd->fd, request, strlen(request), strerror(errno));
|
||||
if (Close(sfd->fd) < 0) {
|
||||
|
@ -406,7 +479,7 @@ int _xioopen_proxy_connect(struct single *sfd,
|
|||
*next = '\0';
|
||||
Info1("sending \"%s\\r\\n\"", header);
|
||||
*next++ = '\r'; *next++ = '\n'; *next++ = '\0';
|
||||
if (writefull(sfd->fd, header, strlen(header)) < 0) {
|
||||
if (writefull(sfd->fd, header, strlen(header), NULL) < 0) {
|
||||
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||
sfd->fd, header, strlen(header), strerror(errno));
|
||||
if (Close(sfd->fd) < 0) {
|
||||
|
@ -419,7 +492,7 @@ int _xioopen_proxy_connect(struct single *sfd,
|
|||
}
|
||||
|
||||
Info("sending \"\\r\\n\"");
|
||||
if (writefull(sfd->fd, "\r\n", 2) < 0) {
|
||||
if (writefull(sfd->fd, "\r\n", 2, NULL) < 0) {
|
||||
Msg2(level, "write(%d, \"\\r\\n\", 2): %s",
|
||||
sfd->fd, strerror(errno));
|
||||
if (Close(sfd->fd) < 0) {
|
||||
|
|
|
@ -25,9 +25,8 @@ extern const struct optdesc opt_proxy_authorization_file;
|
|||
|
||||
extern const struct addrdesc xioaddr_proxy_connect;
|
||||
|
||||
extern int _xioopen_proxy_init(struct proxyvars *proxyvars, struct opt *opts, const char *targetname, const char *targetport);
|
||||
extern int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts, const char *targetname, const char *targetport, const int ai_flags[2]);
|
||||
int _xioopen_proxy_connect(struct single *xfd,
|
||||
struct proxyvars *proxyvars,
|
||||
int level);
|
||||
extern int _xioopen_proxy_connect(struct single *xfd, struct proxyvars *proxyvars, int level);
|
||||
|
||||
#endif /* !defined(__xio_proxy_h_included) */
|
||||
|
|
|
@ -184,7 +184,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;
|
||||
writt = writefull(pipe->fd, "\r", 1);
|
||||
writt = writefull(pipe->fd, "\r", 1, NULL);
|
||||
if (writt < 0) {
|
||||
Warn2("write(%d, \"\\r\", 1): %s",
|
||||
pipe->fd, strerror(errno));
|
||||
|
@ -204,6 +204,9 @@ ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz) {
|
|||
if (line == NULL) {
|
||||
return 0; /* EOF */
|
||||
}
|
||||
if (strlen(line) == 0) {
|
||||
Write(STDOUT_FILENO, "\n", 1);
|
||||
}
|
||||
#if _WITH_TERMIOS
|
||||
xiotermios_clrflag(pipe->fd, 3, ECHO);
|
||||
xiotermios_flush(pipe->fd);
|
||||
|
|
|
@ -81,7 +81,7 @@ static int xioopen_shell(
|
|||
Setenv("SHELL", shellpath, 1);
|
||||
|
||||
Info1("executing shell command \"%s\"", string);
|
||||
Debug3("execl(\"%s\", \"%s\", \"-c\", \"%s\", NULL",
|
||||
Debug3("execl(\"%s\", \"%s\", \"-c\", \"%s\", NULL)",
|
||||
shellpath, shellname, string);
|
||||
result = execl(shellpath, shellname, "-c", string, (char *)NULL);
|
||||
if (result != 0) {
|
||||
|
|
141
xio-socket.c
141
xio-socket.c
|
@ -7,8 +7,6 @@
|
|||
|
||||
#include "xiosysincludes.h"
|
||||
|
||||
#if _WITH_SOCKET
|
||||
|
||||
#include "xioopen.h"
|
||||
#include "xio-ascii.h"
|
||||
#include "xio-socket.h"
|
||||
|
@ -30,6 +28,8 @@
|
|||
#include "xio-tcpwrap.h"
|
||||
|
||||
|
||||
#if _WITH_SOCKET
|
||||
|
||||
static int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
|
||||
static int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
|
||||
static int xioopen_socket_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
|
||||
|
@ -191,6 +191,8 @@ const struct optdesc opt_setsockopt_int = { "setsockopt-int", "sockopt-int
|
|||
const struct optdesc opt_setsockopt_bin = { "setsockopt-bin", "sockopt-bin", OPT_SETSOCKOPT_BIN, GROUP_SOCKET,PH_CONNECTED, TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||
const struct optdesc opt_setsockopt_string = { "setsockopt-string", "sockopt-string", OPT_SETSOCKOPT_STRING, GROUP_SOCKET,PH_CONNECTED, TYPE_INT_INT_STRING, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||
const struct optdesc opt_setsockopt_listen = { "setsockopt-listen", "sockopt-listen", OPT_SETSOCKOPT_LISTEN, GROUP_SOCKET,PH_PREBIND, TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||
const struct optdesc opt_setsockopt_socket = { "setsockopt-socket", "sockopt-sock", OPT_SETSOCKOPT_SOCKET, GROUP_SOCKET,PH_PASTSOCKET, TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||
const struct optdesc opt_setsockopt_connected = { "setsockopt-connected", "sockopt-conn", OPT_SETSOCKOPT_CONNECTED, GROUP_SOCKET,PH_CONNECTED, TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||
|
||||
const struct optdesc opt_null_eof = { "null-eof", NULL, OPT_NULL_EOF, GROUP_SOCKET, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.null_eof) };
|
||||
|
||||
|
@ -262,8 +264,13 @@ static int xioopen_socket_connect(
|
|||
sfd->dtype = XIOREAD_STREAM|XIOWRITE_STREAM;
|
||||
|
||||
socket_init(0, &us);
|
||||
if (retropt_bind(opts, 0 /*pf*/, socktype, proto, (struct sockaddr *)&us, &uslen, 3,
|
||||
sfd->para.socket.ip.ai_flags)
|
||||
if (retropt_bind(opts, pf, socktype, proto, (struct sockaddr *)&us, &uslen, -1,
|
||||
#if _WITH_IP4 || _WITH_IP6
|
||||
sfd->para.socket.ip.ai_flags
|
||||
#else
|
||||
NULL
|
||||
#endif /* _WITH_IP4 || _WITH_IP6 */
|
||||
)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
us.soa.sa_family = pf;
|
||||
|
@ -540,7 +547,12 @@ int xioopen_socket_recvfrom(
|
|||
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, 0, &sfd->para.socket.range,
|
||||
sfd->para.socket.ip.ai_flags)
|
||||
#if _WITH_IP4 || _WITH_IP6
|
||||
sfd->para.socket.ip.ai_flags
|
||||
#else
|
||||
NULL
|
||||
#endif /* _WITH_IP4 */
|
||||
)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
|
@ -626,7 +638,12 @@ int xioopen_socket_recv(
|
|||
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, 0, &sfd->para.socket.range,
|
||||
sfd->para.socket.ip.ai_flags)
|
||||
#if _WITH_IP4 || _WITH_IP6
|
||||
sfd->para.socket.ip.ai_flags
|
||||
#else
|
||||
NULL
|
||||
#endif /* _WITH_IP4 */
|
||||
)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
|
@ -712,7 +729,12 @@ static int xioopen_socket_datagram(
|
|||
/* which reply sockets will accept - determine by range option */
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, 0, &sfd->para.socket.range,
|
||||
sfd->para.socket.ip.ai_flags)
|
||||
#if _WITH_IP4 || _WITH_IP6
|
||||
sfd->para.socket.ip.ai_flags
|
||||
#else
|
||||
NULL
|
||||
#endif /* _WITH_IP4 */
|
||||
)
|
||||
< 0) {
|
||||
free(rangename);
|
||||
return STAT_NORETRY;
|
||||
|
@ -779,13 +801,13 @@ int xiogetpacketinfo(struct single *sfd, int fd)
|
|||
PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECT,
|
||||
PH_CONNECTED, PH_LATE,
|
||||
OFUNC_OFFSET,
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_O_CLOEXEC
|
||||
Does not fork, does not retry.
|
||||
Alternate (alt) bind semantics are:
|
||||
with IP sockets: lowport (selects randomly a free port from 640 to 1023)
|
||||
with UNIX and abstract sockets: uses tmpname() to find a free file system
|
||||
entry.
|
||||
returns 0 on success.
|
||||
Returns STAT_OK on success, or STAT_RETRYLATER (+errno) on failure.
|
||||
*/
|
||||
int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
|
@ -815,7 +837,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
|
|||
applyopts_cloexec(sfd->fd, opts);
|
||||
|
||||
if (xiobind(sfd, us, uslen, opts, pf, alt, level) < 0) {
|
||||
return -1;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
applyopts(sfd, -1, opts, PH_CONNECT);
|
||||
|
@ -855,6 +877,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
|
|||
Msg4(level, "xiopoll({%d,POLLOUT|POLLERR},,{"F_tv_sec"."F_tv_usec"): %s",
|
||||
sfd->fd, timeout.tv_sec, timeout.tv_usec, strerror(errno));
|
||||
Close(sfd->fd);
|
||||
errno = _errno;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
if (result == 0) {
|
||||
|
@ -862,6 +885,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
|
|||
sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
strerror(ETIMEDOUT));
|
||||
Close(sfd->fd);
|
||||
errno = _errno;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
if (writefd.revents & POLLERR) {
|
||||
|
@ -877,15 +901,19 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
|
|||
sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
themlen, strerror(errno));
|
||||
#endif
|
||||
_errno = errno;
|
||||
Close(sfd->fd);
|
||||
errno = _errno;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
/* otherwise OK or network error */
|
||||
result = Getsockopt(sfd->fd, SOL_SOCKET, SO_ERROR, &err, &errlen);
|
||||
if (result != 0) {
|
||||
_errno = errno;
|
||||
Msg2(level, "getsockopt(%d, SOL_SOCKET, SO_ERROR, ...): %s",
|
||||
sfd->fd, strerror(err));
|
||||
Close(sfd->fd);
|
||||
errno = _errno;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
Debug2("getsockopt(%d, SOL_SOCKET, SO_ERROR, { %d }) -> 0",
|
||||
|
@ -895,6 +923,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
|
|||
sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
themlen, strerror(err));
|
||||
Close(sfd->fd);
|
||||
errno = err;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
Fcntl_l(sfd->fd, F_SETFL, fcntl_flags);
|
||||
|
@ -925,6 +954,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
|
|||
sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
themlen, strerror(errno));
|
||||
Close(sfd->fd);
|
||||
errno = _errno;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
} else { /* result >= 0 */
|
||||
|
@ -952,7 +982,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
|
|||
PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECT,
|
||||
PH_CONNECTED, PH_LATE,
|
||||
OFUNC_OFFSET,
|
||||
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_O_CLOEXEC
|
||||
returns 0 on success.
|
||||
*/
|
||||
int xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
|
||||
|
@ -1052,7 +1082,7 @@ int xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
|
|||
applies and consumes the following option:
|
||||
PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE
|
||||
OFUNC_OFFSET
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_O_CLOEXEC
|
||||
*/
|
||||
int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
||||
union sockaddr_union *us, socklen_t uslen,
|
||||
|
@ -1202,6 +1232,7 @@ int _xioopen_dgram_recvfrom(struct single *sfd, int xioflags,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
/* for generic sockets, this has already been retrieved */
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, pf, &sfd->para.socket.range,
|
||||
|
@ -1213,6 +1244,7 @@ int _xioopen_dgram_recvfrom(struct single *sfd, int xioflags,
|
|||
free(rangename);
|
||||
sfd->para.socket.dorange = true;
|
||||
}
|
||||
#endif /* WITH_IP4 || WITH_IP6 */
|
||||
|
||||
#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
|
||||
xio_retropt_tcpwrap(sfd, opts);
|
||||
|
@ -1424,6 +1456,7 @@ int _xioopen_dgram_recv(struct single *sfd, int xioflags,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, pf, &sfd->para.socket.range,
|
||||
sfd->para.socket.ip.ai_flags)
|
||||
|
@ -1434,6 +1467,7 @@ int _xioopen_dgram_recv(struct single *sfd, int xioflags,
|
|||
free(rangename);
|
||||
sfd->para.socket.dorange = true;
|
||||
}
|
||||
#endif /* WITH_IP4 || WITH_IP6 */
|
||||
|
||||
#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
|
||||
xio_retropt_tcpwrap(sfd, opts);
|
||||
|
@ -1449,7 +1483,10 @@ int _xioopen_dgram_recv(struct single *sfd, int xioflags,
|
|||
return STAT_OK;
|
||||
}
|
||||
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
#if _WITH_SOCKET || _WITH_SOCKETPAIR
|
||||
int retropt_socket_pf(struct opt *opts, int *pf) {
|
||||
char *pfname;
|
||||
|
||||
|
@ -1478,8 +1515,11 @@ int retropt_socket_pf(struct opt *opts, int *pf) {
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
#endif /* _WITH_SOCKET || _WITH_SOCKETPAIR */
|
||||
|
||||
|
||||
#if _WITH_SOCKET
|
||||
|
||||
/* This function calls recvmsg(..., MSG_PEEK, ...) to obtain information about
|
||||
the arriving packet, thus it does not "consume" the packet.
|
||||
In msgh the msg_name pointer must refer to an (empty) sockaddr storage.
|
||||
|
@ -1651,7 +1691,7 @@ int xiocheckpeer(xiosingle_t *sfd,
|
|||
char infobuff[256];
|
||||
int result;
|
||||
|
||||
#if WITH_IP4
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
if (sfd->para.socket.dorange) {
|
||||
if (pa == NULL) { return -1; }
|
||||
if (xiocheckrange(pa, &sfd->para.socket.range) < 0) {
|
||||
|
@ -1736,7 +1776,7 @@ int xiocheckpeer(xiosingle_t *sfd,
|
|||
|
||||
|
||||
#if HAVE_STRUCT_CMSGHDR
|
||||
/* converts the ancillary message in *cmsg into a form useable for further
|
||||
/* Converts the ancillary message in *cmsg into a form usable 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
|
||||
|
@ -1957,7 +1997,7 @@ int xioparserange(
|
|||
return -1;
|
||||
}
|
||||
/* we have parsed the address and mask; now we make sure that the stored
|
||||
address has 0 where mask is 0, to simplify comparisions */
|
||||
address has 0 where mask is 0, to simplify comparisons */
|
||||
switch (pf) {
|
||||
#if WITH_IP4
|
||||
case PF_INET:
|
||||
|
@ -2055,15 +2095,12 @@ int xiosetsockaddrenv(const char *lr,
|
|||
# undef XIOSOCKADDRENVLEN
|
||||
}
|
||||
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
/* these do sockets internally */
|
||||
/* These do sockets internally */
|
||||
|
||||
/* 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
|
||||
xiosocket(struct opt *opts, int pf, int socktype, int proto, int msglevel) {
|
||||
returns 0 on success or -1 (and errno) if an error occurred. */
|
||||
int xiosocket(struct opt *opts, int pf, int socktype, int proto, int msglevel) {
|
||||
int result;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
@ -2080,24 +2117,6 @@ xiosocket(struct opt *opts, int pf, int socktype, int proto, int msglevel) {
|
|||
return result;
|
||||
}
|
||||
|
||||
/* retrieves options so-type and so-prototype from opts, calls socketpair, and
|
||||
ev. generates an appropriate error message.
|
||||
returns 0 on success or -1 if an error occurred. */
|
||||
int
|
||||
xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]) {
|
||||
int result;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &proto);
|
||||
result = Socketpair(pf, socktype, proto, sv);
|
||||
if (result < 0) {
|
||||
Error5("socketpair(%d, %d, %d, %p): %s",
|
||||
pf, socktype, proto, sv, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Binds a socket to a socket address. Handles IP (internet protocol), UNIX
|
||||
domain, Linux abstract UNIX domain.
|
||||
The bind address us may be NULL in which case no bind() happens, except with
|
||||
|
@ -2106,6 +2125,7 @@ xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]) {
|
|||
with IP sockets: lowport (selects randomly a free port from 640 to 1023)
|
||||
with UNIX and abstract sockets: uses a method similar to tmpname() to
|
||||
find a free file system entry.
|
||||
On success returns STAT_OK, otherwise errno is set.
|
||||
*/
|
||||
int xiobind(
|
||||
struct single *sfd,
|
||||
|
@ -2142,18 +2162,20 @@ int xiobind(
|
|||
usrname = strndup(us->un.sun_path, sizeof(us->un.sun_path));
|
||||
if (usrname == NULL) {
|
||||
int _errno = errno;
|
||||
Error2("strndup(\"%s\", "F_Zu"): out of memory",
|
||||
Msg2(level, "strndup(\"%s\", "F_Zu"): out of memory",
|
||||
us->un.sun_path, sizeof(us->un.sun_path));
|
||||
errno = _errno;
|
||||
return -1;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
|
||||
do { /* loop over tempnam bind() attempts */
|
||||
sockname = xio_tempnam(usrname, abstract);
|
||||
if (sockname == NULL) {
|
||||
int _errno = errno;
|
||||
Error2("tempnam(\"%s\"): %s", usrname, strerror(errno));
|
||||
free(usrname);
|
||||
errno = _errno;
|
||||
return -1;
|
||||
}
|
||||
strncpy(us->un.sun_path+(abstract?1:0), sockname, sizeof(us->un.sun_path));
|
||||
|
@ -2167,8 +2189,10 @@ int xiobind(
|
|||
infobuff, sizeof(infobuff)),
|
||||
uslen, strerror(errno));
|
||||
if (errno != EADDRINUSE) {
|
||||
int _errno = errno;
|
||||
free(usrname);
|
||||
Close(sfd->fd);
|
||||
errno = _errno;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
} else {
|
||||
|
@ -2181,10 +2205,12 @@ int xiobind(
|
|||
|
||||
if (us != NULL) {
|
||||
if (Bind(sfd->fd, &us->soa, uslen) < 0) {
|
||||
int _errno = errno;
|
||||
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
|
||||
sfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
|
||||
uslen, strerror(errno));
|
||||
Close(sfd->fd);
|
||||
errno = _errno;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
|
||||
|
@ -2206,8 +2232,12 @@ int xiobind(
|
|||
if (us) {
|
||||
sinp = us;
|
||||
} else {
|
||||
if (pf == AF_INET) {
|
||||
if (0) {
|
||||
;
|
||||
#if WITH_IP4
|
||||
} else if (pf == AF_INET) {
|
||||
socket_in_init(&sin.ip4);
|
||||
#endif
|
||||
#if WITH_IP6
|
||||
} else {
|
||||
socket_in6_init(&sin.ip6);
|
||||
|
@ -2252,12 +2282,14 @@ int xiobind(
|
|||
do { /* loop over lowport bind() attempts */
|
||||
*port = htons(i);
|
||||
if (Bind(sfd->fd, &sinp->soa, sizeof(*sinp)) < 0) {
|
||||
int _errno = errno;
|
||||
Msg4(errno==EADDRINUSE?E_INFO:level,
|
||||
"bind(%d, {%s}, "F_Zd"): %s", sfd->fd,
|
||||
sockaddr_info(&sinp->soa, sizeof(*sinp), infobuff, sizeof(infobuff)),
|
||||
sizeof(*sinp), strerror(errno));
|
||||
if (errno != EADDRINUSE) {
|
||||
if (_errno != EADDRINUSE) {
|
||||
Close(sfd->fd);
|
||||
errno = _errno;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
} else {
|
||||
|
@ -2266,8 +2298,8 @@ int xiobind(
|
|||
--i; if (i < XIO_IPPORT_LOWER) i = IPPORT_RESERVED-1;
|
||||
if (i == N) {
|
||||
Msg(level, "no low port available");
|
||||
/*errno = EADDRINUSE; still assigned */
|
||||
Close(sfd->fd);
|
||||
errno = EADDRINUSE;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
} while (i != N);
|
||||
|
@ -2278,24 +2310,26 @@ int xiobind(
|
|||
if (us) {
|
||||
applyopts(sfd, sfd->fd, opts, PH_BIND);
|
||||
if (Bind(sfd->fd, &us->soa, uslen) < 0) {
|
||||
int _errno = errno;
|
||||
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
|
||||
sfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
|
||||
uslen, strerror(errno));
|
||||
Close(sfd->fd);
|
||||
errno = _errno;
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
applyopts(sfd, -1, opts, PH_PASTBIND);
|
||||
return 0;
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
/* Handles the SO_REUSEADDR socket option for TCP LISTEN addresses depending on
|
||||
Socat option so-reuseaddr:
|
||||
Option not applied: set it to 1
|
||||
Option applied with a value: set it to the value
|
||||
Option applied eith empty value "so-reuseaddr=": do not call setsockopt() for
|
||||
Option applied with empty value "so-reuseaddr=": do not call setsockopt() for
|
||||
SO_REUSEADDR
|
||||
Return 0 on success, or -1 with errno when an error occurred.
|
||||
*/
|
||||
|
@ -2303,15 +2337,25 @@ int xiosock_reuseaddr(int fd, int ipproto, struct opt *opts)
|
|||
{
|
||||
union integral val;
|
||||
union integral notnull;
|
||||
int result;
|
||||
int _errno;
|
||||
|
||||
val.u_int = 0;
|
||||
notnull.u_bool = false;
|
||||
#if WITH_TCP
|
||||
if (ipproto == IPPROTO_TCP) {
|
||||
val.u_int = 1;
|
||||
notnull.u_bool = true;
|
||||
}
|
||||
retropt_2integrals(opts, OPT_SO_REUSEADDR, &val, ¬null);
|
||||
#endif /* WITH_TCP */
|
||||
result = retropt_2integrals(opts, OPT_SO_REUSEADDR, &val, ¬null);
|
||||
#if WITH_TCP
|
||||
if (ipproto == IPPROTO_TCP && result < 0) {
|
||||
Info("Setting SO_REUSADDR on TCP listen socket implicitly");
|
||||
val.u_int = 1;
|
||||
notnull.u_bool = true;
|
||||
}
|
||||
#endif /* WITH_TCP */
|
||||
if (notnull.u_bool) {
|
||||
if (Setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val.u_int, sizeof(int))
|
||||
!= 0) {
|
||||
|
@ -2324,3 +2368,6 @@ int xiosock_reuseaddr(int fd, int ipproto, struct opt *opts)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
|
|
@ -83,6 +83,8 @@ extern const struct optdesc opt_setsockopt_bin;
|
|||
extern const struct optdesc opt_setsockopt_string;
|
||||
extern const struct optdesc opt_setsockopt_listen;
|
||||
extern const struct optdesc opt_null_eof;
|
||||
extern const struct optdesc opt_setsockopt_socket;
|
||||
extern const struct optdesc opt_setsockopt_connected;
|
||||
|
||||
|
||||
extern
|
||||
|
@ -135,8 +137,6 @@ extern int xioparserange(const char *rangename, int pf, struct xiorange *range,
|
|||
|
||||
extern int
|
||||
xiosocket(struct opt *opts, int pf, int socktype, int proto, int level);
|
||||
extern int
|
||||
xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]);
|
||||
extern int xiosock_reuseaddr(int fd, int ipproto, struct opt *opts);
|
||||
|
||||
#endif /* !defined(__xio_socket_h_included) */
|
||||
|
|
|
@ -95,3 +95,26 @@ static int xioopen_socketpair(
|
|||
}
|
||||
|
||||
#endif /* WITH_SOCKETPAIR */
|
||||
|
||||
|
||||
#if _WITH_SOCKETPAIR
|
||||
|
||||
/* retrieves options so-type and so-prototype from opts, calls socketpair, and
|
||||
ev. generates an appropriate error message.
|
||||
returns 0 on success or -1 if an error occurred. */
|
||||
int
|
||||
xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]) {
|
||||
int result;
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &proto);
|
||||
result = Socketpair(pf, socktype, proto, sv);
|
||||
if (result < 0) {
|
||||
Error5("socketpair(%d, %d, %d, %p): %s",
|
||||
pf, socktype, proto, sv, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* _WITH_SOCKETPAIR */
|
||||
|
|
|
@ -7,4 +7,6 @@
|
|||
|
||||
const extern struct addrdesc xioaddr_socketpair;
|
||||
|
||||
extern int xiosocketpair(struct opt *opts, int pf, int socktype, int proto, int sv[2]);
|
||||
|
||||
#endif /* !defined(__xio_socketpair_h_included) */
|
||||
|
|
221
xio-socks.c
221
xio-socks.c
|
@ -6,14 +6,16 @@
|
|||
|
||||
#include "xiosysincludes.h"
|
||||
|
||||
#if WITH_SOCKS4 || WITH_SOCKS4A
|
||||
|
||||
#include "xioopen.h"
|
||||
#include "xio-ascii.h"
|
||||
#include "xio-socket.h"
|
||||
#include "xio-ip.h"
|
||||
#include "xio-ipapp.h"
|
||||
|
||||
#define SOCKSPORT "1080"
|
||||
|
||||
#if WITH_SOCKS4 || WITH_SOCKS4A
|
||||
|
||||
#include "xio-socks.h"
|
||||
|
||||
|
||||
|
@ -24,7 +26,6 @@ enum {
|
|||
SOCKS_CD_IDENTFAILED
|
||||
} ;
|
||||
|
||||
#define SOCKSPORT "1080"
|
||||
#define BUFF_LEN (SIZEOF_STRUCT_SOCKS4+512)
|
||||
|
||||
static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
|
||||
|
@ -53,13 +54,12 @@ static int xioopen_socks4_connect(
|
|||
int pf = PF_UNSPEC;
|
||||
int ipproto = IPPROTO_TCP;
|
||||
bool dofork = false;
|
||||
union sockaddr_union us_sa, *us = &us_sa;
|
||||
socklen_t uslen = sizeof(us_sa);
|
||||
struct addrinfo **themarr, *themp;
|
||||
int i;
|
||||
int maxchildren = 0;
|
||||
struct addrinfo **bindarr = NULL;
|
||||
struct addrinfo **themarr = NULL;
|
||||
uint16_t bindport = 0;
|
||||
bool needbind = false;
|
||||
bool lowport = false;
|
||||
char infobuff[256];
|
||||
unsigned char buff[BUFF_LEN];
|
||||
struct socks4 *sockhead = (struct socks4 *)buff;
|
||||
size_t buflen = sizeof(buff);
|
||||
|
@ -75,41 +75,43 @@ static int xioopen_socks4_connect(
|
|||
targetname = argv[2];
|
||||
targetport = argv[3];
|
||||
|
||||
if (sfd->howtoend == END_UNSPEC)
|
||||
sfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(sfd, 1, opts, PH_INIT);
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
retropt_bool(opts, OPT_FORK, &dofork);
|
||||
|
||||
result = _xioopen_socks4_prepare(targetport, opts, &socksport, sockhead, &buflen);
|
||||
/* Apply and retrieve some options */
|
||||
result = _xioopen_ipapp_init(sfd, xioflags, opts,
|
||||
&dofork, &maxchildren,
|
||||
&pf, &socktype, &ipproto);
|
||||
if (result != STAT_OK)
|
||||
return result;
|
||||
|
||||
result = _xioopen_socks4_init(targetport, opts, &socksport, sockhead,
|
||||
&buflen);
|
||||
if (result != STAT_OK)
|
||||
return result;
|
||||
|
||||
opts0 = opts; /* save remaining options for each loop */
|
||||
opts = NULL;
|
||||
|
||||
Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
|
||||
targetname,
|
||||
ntohs(sockhead->port),
|
||||
targetname, ntohs(sockhead->port),
|
||||
sockdname, socksport, sockhead->userid);
|
||||
|
||||
i = 0;
|
||||
do { /* loop over retries (failed connect and socks-request attempts) */
|
||||
do { /* loop over retries (failed connect and socks-request attempts)
|
||||
and/or forks */
|
||||
int _errno;
|
||||
|
||||
level = E_INFO;
|
||||
#if WITH_RETRY
|
||||
if (sfd->forever || sfd->retry) {
|
||||
level = E_NOTICE;
|
||||
} else
|
||||
#endif /* WITH_RETRY */
|
||||
level = E_WARN;
|
||||
|
||||
opts = copyopts(opts0, GROUP_ALL);
|
||||
|
||||
result =
|
||||
_xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
|
||||
&pf, ipproto,
|
||||
_xioopen_ipapp_prepare(&opts, opts0, sockdname, socksport,
|
||||
pf, socktype, ipproto,
|
||||
sfd->para.socket.ip.ai_flags,
|
||||
&themarr, us, &uslen,
|
||||
&needbind, &lowport, socktype);
|
||||
|
||||
/* we try to resolve the target address _before_ connecting to the socks
|
||||
server: this avoids unnecessary socks connects and timeouts */
|
||||
result =
|
||||
_xioopen_socks4_connect0(sfd, targetname, socks4a, sockhead,
|
||||
(ssize_t *)&buflen, level);
|
||||
&themarr, &bindarr, &bindport, &needbind, &lowport);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
|
@ -118,60 +120,78 @@ static int xioopen_socks4_connect(
|
|||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER)
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
default:
|
||||
/* FALLTHROUGH */
|
||||
case STAT_NORETRY:
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* loop over themarr */
|
||||
i = 0;
|
||||
themp = themarr[i++];
|
||||
while (themp != NULL) {
|
||||
Notice1("opening connection to %s",
|
||||
sockaddr_info(themp->ai_addr, themp->ai_addrlen,
|
||||
infobuff, sizeof(infobuff)));
|
||||
#if WITH_RETRY
|
||||
if (sfd->forever || sfd->retry || themarr[i] != NULL) {
|
||||
level = E_INFO;
|
||||
} else
|
||||
#endif /* WITH_RETRY */
|
||||
level = E_ERROR;
|
||||
|
||||
/* this cannot fork because we retrieved fork option above */
|
||||
result =
|
||||
_xioopen_connect(sfd,
|
||||
needbind?us:NULL, uslen,
|
||||
themp->ai_addr, themp->ai_addrlen,
|
||||
opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
|
||||
if (result == STAT_OK)
|
||||
break;
|
||||
themp = themarr[i++];
|
||||
if (themp == NULL)
|
||||
result = STAT_RETRYLATER;
|
||||
}
|
||||
/* we try to resolve the target address _before_ connecting to the socks
|
||||
server: this may avoid unnecessary connects and timeouts */
|
||||
result =
|
||||
_xioopen_socks4_prepare(sfd, targetname, socks4a, sockhead,
|
||||
(ssize_t *)&buflen, level);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry) {
|
||||
--sfd->retry;
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER)
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
xiofreeaddrinfo(themarr);
|
||||
applyopts(sfd, -1, opts, PH_ALL);
|
||||
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||
Notice2("opening connection to sockd %s:%s", sockdname, socksport);
|
||||
result =
|
||||
_xioopen_ipapp_connect(sfd, sockdname, opts, themarr,
|
||||
needbind, bindarr, bindport, lowport, level);
|
||||
_errno = errno;
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER) {
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
errno = _errno;
|
||||
Error4("%s:%s:...,socksport=%s: %s", argv[0], sockdname, socksport,
|
||||
_errno?strerror(_errno):"(See above)");
|
||||
freeopts(opts0);
|
||||
freeopts(opts);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = _xioopen_socks4_connect(sfd, sockhead, buflen, level);
|
||||
switch (result) {
|
||||
|
@ -180,11 +200,16 @@ static int xioopen_socks4_connect(
|
|||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER) Nanosleep(&sfd->intervall, NULL);
|
||||
if (result == STAT_RETRYLATER)
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -201,10 +226,13 @@ static int xioopen_socks4_connect(
|
|||
so Notice is too weak */
|
||||
}
|
||||
while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
|
||||
if (sfd->forever || --sfd->retry) {
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
|
@ -216,8 +244,13 @@ static int xioopen_socks4_connect(
|
|||
|
||||
/* parent process */
|
||||
Close(sfd->fd);
|
||||
/* with and without retry */
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
||||
while (maxchildren > 0 && num_child >= maxchildren) {
|
||||
Info1("all %d allowed children are active, waiting", maxchildren);
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
freeopts(opts);
|
||||
continue;
|
||||
} else
|
||||
#endif /* WITH_RETRY */
|
||||
|
@ -226,9 +259,19 @@ static int xioopen_socks4_connect(
|
|||
}
|
||||
|
||||
} while (true); /* end of complete open loop - drop out on success */
|
||||
return 0;
|
||||
/* only "active" process breaks (master without fork, or child) */
|
||||
|
||||
Notice4("successfully connected to %s:%s via sockd %s:%s",
|
||||
targetname, targetport, sockdname, socksport);
|
||||
|
||||
result = _xio_openlate(sfd, opts);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* WITH_SOCKS4 || WITH_SOCKS4A */
|
||||
#if WITH_SOCKS4 || WITH_SOCKS4A || WITH_SOCKS5
|
||||
|
||||
int _xioopen_opt_socksport(
|
||||
struct opt *opts,
|
||||
|
@ -236,7 +279,8 @@ int _xioopen_opt_socksport(
|
|||
{
|
||||
struct servent *se;
|
||||
|
||||
if (retropt_string(opts, OPT_SOCKSPORT, socksport) < 0) {
|
||||
if (retropt_string(opts, OPT_SOCKSPORT, socksport) < 0 &&
|
||||
*socksport == NULL) {
|
||||
if ((se = getservbyname("socks", "tcp")) != NULL) {
|
||||
Debug1("\"socks/tcp\" resolves to %u", ntohs(se->s_port));
|
||||
if ((*socksport = Malloc(6)) == NULL) {
|
||||
|
@ -253,8 +297,16 @@ int _xioopen_opt_socksport(
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WITH_SOCKS4 || WITH_SOCKS4A || WITH_SOCKS5 */
|
||||
#if WITH_SOCKS4 || WITH_SOCKS4A
|
||||
|
||||
int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen) {
|
||||
int _xioopen_socks4_init(
|
||||
const char *targetport,
|
||||
struct opt *opts,
|
||||
char **socksport,
|
||||
struct socks4 *sockhead,
|
||||
size_t *headlen)
|
||||
{
|
||||
char *userid;
|
||||
|
||||
/* generate socks header - points to final target */
|
||||
|
@ -280,14 +332,14 @@ int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **soc
|
|||
|
||||
|
||||
/* called within retry/fork loop, before connect() */
|
||||
int
|
||||
_xioopen_socks4_connect0(struct single *sfd,
|
||||
const char *hostname, /* socks target host */
|
||||
int socks4a,
|
||||
struct socks4 *sockhead,
|
||||
ssize_t *headlen, /* get available space,
|
||||
return used length*/
|
||||
int level) {
|
||||
int _xioopen_socks4_prepare(
|
||||
struct single *sfd,
|
||||
const char *hostname, /* socks target host */
|
||||
int socks4a,
|
||||
struct socks4 *sockhead,
|
||||
ssize_t *headlen, /* get available space, return used length*/
|
||||
int level)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (!socks4a) {
|
||||
|
@ -364,7 +416,7 @@ int _xioopen_socks4_connect(struct single *sfd,
|
|||
}
|
||||
}
|
||||
#endif /* WITH_MSGLEVEL <= E_DEBUG */
|
||||
if (writefull(sfd->fd, sockhead, headlen) < 0) {
|
||||
if (writefull(sfd->fd, sockhead, headlen, NULL) < 0) {
|
||||
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||
sfd->fd, sockhead, headlen, strerror(errno));
|
||||
if (Close(sfd->fd) < 0) {
|
||||
|
@ -429,16 +481,7 @@ int _xioopen_socks4_connect(struct single *sfd,
|
|||
switch (replyhead->action) {
|
||||
case SOCKS_CD_GRANTED:
|
||||
/* Notice("socks: connect request succeeded"); */
|
||||
#if 0
|
||||
if (Getsockname(sfd->fd, (struct sockaddr *)&us, &uslen) < 0) {
|
||||
Warn4("getsockname(%d, %p, {%d}): %s",
|
||||
sfd->fd, &us, uslen, strerror(errno));
|
||||
}
|
||||
Notice1("successfully connected from %s via socks4",
|
||||
sockaddr_info((struct sockaddr *)&us, infobuff, sizeof(infobuff)));
|
||||
#else
|
||||
Notice("successfully connected via socks4");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SOCKS_CD_FAILED:
|
||||
|
|
15
xio-socks.h
15
xio-socks.h
|
@ -10,9 +10,9 @@ struct socks4 {
|
|||
uint8_t action;
|
||||
uint16_t port;
|
||||
uint32_t dest;
|
||||
char userid[1]; /* just to have access via this struct */
|
||||
char userid[0]; /* just to have access via this struct */
|
||||
} ;
|
||||
#define SIZEOF_STRUCT_SOCKS4 8
|
||||
#define SIZEOF_STRUCT_SOCKS4 ((size_t)&((struct socks4 *)0)->userid)
|
||||
|
||||
extern const struct optdesc opt_socksport;
|
||||
extern const struct optdesc opt_socksuser;
|
||||
|
@ -21,15 +21,8 @@ extern const struct addrdesc xioaddr_socks4_connect;
|
|||
extern const struct addrdesc xioaddr_socks4a_connect;
|
||||
|
||||
extern int _xioopen_opt_socksport(struct opt *opts, char **socksport);
|
||||
extern int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen);
|
||||
extern int
|
||||
_xioopen_socks4_connect0(struct single *xfd,
|
||||
const char *hostname, /* socks target host */
|
||||
int socks4a,
|
||||
struct socks4 *sockhead,
|
||||
ssize_t *headlen, /* get available space,
|
||||
return used length*/
|
||||
int level);
|
||||
extern int _xioopen_socks4_init(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen);
|
||||
extern int _xioopen_socks4_prepare(struct single *xfd, const char *hostname, int socks4a, struct socks4 *sockhead, ssize_t *headlen, int level);
|
||||
extern int _xioopen_socks4_connect(struct single *xfd,
|
||||
struct socks4 *sockhead,
|
||||
size_t headlen,
|
||||
|
|
204
xio-socks5.c
204
xio-socks5.c
|
@ -53,7 +53,7 @@ static int xioopen_socks5(int argc, const char *argv[], struct opt *opts, int xi
|
|||
|
||||
const struct addrdesc xioaddr_socks5_connect = { "SOCKS5-CONNECT", 1+XIO_RDWR, xioopen_socks5, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS|GROUP_CHILD|GROUP_RETRY, SOCKS5_COMMAND_CONNECT, 0, 0 HELP(":<socks-server>[:<socks-port>]:<target-host>:<target-port>") };
|
||||
|
||||
const struct addrdesc xioaddr_socks5_listen = { "SOCKS5-LISTEN", 1+XIO_RDWR, xioopen_socks5, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCKS5_COMMAND_BIND, 0, 0 HELP(":<socks-server>[:<socks-port>]:<listen-host>:<listen-port>") };
|
||||
const struct addrdesc xioaddr_socks5_listen = { "SOCKS5-LISTEN", 1+XIO_RDWR, xioopen_socks5, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS|GROUP_CHILD|GROUP_RETRY, SOCKS5_COMMAND_BIND, 0, 0 HELP(":<socks-server>[:<socks-port>]:<listen-host>:<listen-port>") };
|
||||
|
||||
static const char * _xioopen_socks5_strerror(uint8_t r)
|
||||
{
|
||||
|
@ -136,7 +136,7 @@ static int _xioopen_socks5_handshake(struct single *sfd, int level)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (writefull(sfd->fd, client_hello, client_hello_size) < 0) {
|
||||
if (writefull(sfd->fd, client_hello, client_hello_size, NULL) < 0) {
|
||||
Msg4(level, "write(%d, %p, %d): %s",
|
||||
sfd->fd, client_hello, client_hello_size,
|
||||
strerror(errno));
|
||||
|
@ -188,6 +188,8 @@ static int _xioopen_socks5_handshake(struct single *sfd, int level)
|
|||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
Debug2("received SOCKS5 server hello %02x %02x",
|
||||
server_hello_ptr[0], server_hello_ptr[1]);
|
||||
Info2("received SOCKS5 server hello version=%d method=%d",
|
||||
server_hello.version,
|
||||
server_hello.method);
|
||||
|
@ -332,6 +334,12 @@ static int _xioopen_socks5_read_reply(
|
|||
}
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
Debug5("received SOCKS5 reply %02x %02x %02x %02x %02x",
|
||||
((unsigned char *)reply+bytes_read)[0],
|
||||
((unsigned char *)reply+bytes_read)[1],
|
||||
((unsigned char *)reply+bytes_read)[2],
|
||||
((unsigned char *)reply+bytes_read)[3],
|
||||
((unsigned char *)reply+bytes_read)[4]);
|
||||
bytes_read += result;
|
||||
|
||||
/* Once we've read 5 bytes, figure out total message length and
|
||||
|
@ -418,7 +426,7 @@ static int _xioopen_socks5_request(
|
|||
}
|
||||
#endif
|
||||
|
||||
if (writefull(sfd->fd, req, bytes) < 0) {
|
||||
if (writefull(sfd->fd, req, bytes, NULL) < 0) {
|
||||
Msg4(level, "write(%d, %p, %d): %s",
|
||||
sfd->fd, req, bytes, strerror(errno));
|
||||
if (Close(sfd->fd) < 0) {
|
||||
|
@ -504,6 +512,7 @@ static int xioopen_socks5(
|
|||
{
|
||||
int socks_command = addrdesc->arg1;
|
||||
bool dofork = false;
|
||||
int maxchildren = 0;
|
||||
int socktype = SOCK_STREAM;
|
||||
int pf = PF_UNSPEC;
|
||||
int ipproto = IPPROTO_TCP;
|
||||
|
@ -511,17 +520,12 @@ static int xioopen_socks5(
|
|||
struct opt *opts0 = NULL;
|
||||
struct single *sfd = &xxfd->stream;
|
||||
const char *socks_server, *target_name, *target_port, *socks_port;
|
||||
union sockaddr_union us_sa, *us = &us_sa;
|
||||
socklen_t uslen = sizeof(us_sa);
|
||||
struct addrinfo **themarr, *themp;
|
||||
struct addrinfo **bindarr = NULL;
|
||||
struct addrinfo **themarr = NULL;
|
||||
uint16_t bindport = 0;
|
||||
bool needbind = false;
|
||||
bool lowport = false;
|
||||
char infobuff[256];
|
||||
|
||||
if (!xioparms.experimental) {
|
||||
Error1("%s: use option --experimental to acknowledge unmature state", argv[0]);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
if (argc < 4 || argc > 5) {
|
||||
xio_syntax(argv[0], 4, argc-1, addrdesc->syntax);
|
||||
return STAT_NORETRY;
|
||||
|
@ -533,78 +537,120 @@ static int xioopen_socks5(
|
|||
target_name = argv[3];
|
||||
target_port = argv[4];
|
||||
} else {
|
||||
socks_port = NULL;
|
||||
target_name = argv[2];
|
||||
target_port = argv[3];
|
||||
}
|
||||
|
||||
if (sfd->howtoend == END_UNSPEC)
|
||||
sfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_bool(opts, OPT_FORK, &dofork);
|
||||
/* Apply and retrieve some options */
|
||||
result = _xioopen_ipapp_init(sfd, xioflags, opts,
|
||||
&dofork, &maxchildren,
|
||||
&pf, &socktype, &ipproto);
|
||||
if (result != STAT_OK)
|
||||
return result;
|
||||
|
||||
if (_xioopen_opt_socksport(opts, (char **)&socks_port) < 0) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
/*! possible memory leak */
|
||||
|
||||
result = _xioopen_ipapp_prepare(opts, &opts0, socks_server, socks_port,
|
||||
&pf, ipproto,
|
||||
sfd->para.socket.ip.ai_flags,
|
||||
&themarr, us, &uslen,
|
||||
&needbind, &lowport, socktype);
|
||||
opts0 = opts;
|
||||
opts = NULL;
|
||||
|
||||
Notice2("connecting to socks5 server %s:%s",
|
||||
socks_server, socks_port);
|
||||
Notice4("opening connection to %s:%s vis socks5 server %s:%s",
|
||||
target_name, target_port, socks_server, socks_port);
|
||||
|
||||
do {
|
||||
do { /* loop over retries (failed connect and socks-request attempts)
|
||||
and/or forks */
|
||||
int _errno;
|
||||
#if WITH_RETRY
|
||||
if (sfd->forever || sfd->retry) {
|
||||
level = E_INFO;
|
||||
} else {
|
||||
level = E_ERROR;
|
||||
}
|
||||
level = E_NOTICE;
|
||||
} else
|
||||
#endif
|
||||
level = E_WARN;
|
||||
|
||||
/* loop over themarr */
|
||||
themp = themarr[0];
|
||||
while (themp != NULL) {
|
||||
Notice1("opening connection to %s",
|
||||
sockaddr_info(themp->ai_addr, themp->ai_addrlen,
|
||||
infobuff, sizeof(infobuff)));
|
||||
result = _xioopen_connect(sfd, needbind?us:NULL, sizeof(*us),
|
||||
themp->ai_addr, themp->ai_addrlen,
|
||||
opts, pf?pf:themp->ai_family, socktype,
|
||||
IPPROTO_TCP, lowport, level);
|
||||
if (result == STAT_OK)
|
||||
break;
|
||||
themp = themp->ai_next;
|
||||
if (themp == NULL)
|
||||
result = STAT_RETRYLATER;
|
||||
opts = copyopts(opts0, GROUP_ALL);
|
||||
|
||||
switch(result){
|
||||
break;
|
||||
result =
|
||||
_xioopen_ipapp_prepare(&opts, opts0, socks_server, socks_port,
|
||||
pf, socktype, ipproto,
|
||||
sfd->para.socket.ip.ai_flags,
|
||||
&themarr, &bindarr, &bindport, &needbind,
|
||||
&lowport);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry-- ) {
|
||||
if (result == STAT_RETRYLATER) Nanosleep(&sfd->intervall, NULL);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER)
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
return result;
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
xiofreeaddrinfo(themarr);
|
||||
applyopts(sfd, -1, opts, PH_ALL);
|
||||
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||
#endif /* WITH_RETRY */
|
||||
/* FALLTHROUGH */
|
||||
case STAT_NORETRY:
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((result = _xioopen_socks5_handshake(sfd, level)) != STAT_OK) {
|
||||
Notice2("opening connection to socks5 server %s:%s",
|
||||
socks_server, socks_port);
|
||||
result =
|
||||
_xioopen_ipapp_connect(sfd, socks_server, opts, themarr,
|
||||
needbind, bindarr, bindport, lowport, level);
|
||||
_errno = errno;
|
||||
if (bindarr != NULL) xiofreeaddrinfo(bindarr);
|
||||
xiofreeaddrinfo(themarr);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER) {
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
Error4("%s:%s:%s:...: %s",
|
||||
argv[0], socks_server, socks_port,
|
||||
_errno?strerror(_errno):"(See above)");
|
||||
freeopts(opts0);
|
||||
freeopts(opts);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = _xioopen_socks5_handshake(sfd, level);
|
||||
switch (result) {
|
||||
case STAT_OK: break;
|
||||
#if WITH_RETRY
|
||||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if (sfd->forever || sfd->retry--) {
|
||||
if (result == STAT_RETRYLATER) {
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif /* WITH_RETRY */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
Error3("%s:%s:%s: Connection failed", argv[0], socks_server, socks_port);
|
||||
freeopts(opts0);
|
||||
freeopts(opts);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -616,11 +662,16 @@ static int xioopen_socks5(
|
|||
case STAT_RETRYLATER:
|
||||
case STAT_RETRYNOW:
|
||||
if ( sfd->forever || sfd->retry-- ) {
|
||||
if (result == STAT_RETRYLATER) Nanosleep(&sfd->intervall, NULL);
|
||||
if (result == STAT_RETRYLATER)
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#endif /* WITH_RETRY */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -636,12 +687,18 @@ static int xioopen_socks5(
|
|||
level = E_WARN;
|
||||
}
|
||||
while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
|
||||
if (sfd->forever || --sfd->retry) {
|
||||
if (sfd->forever || sfd->retry) {
|
||||
if (sfd->retry > 0)
|
||||
--sfd->retry;
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
freeopts(opts);
|
||||
continue;
|
||||
}
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
if ( pid == 0 ) {
|
||||
sfd->forever = false;
|
||||
sfd->retry = 0;
|
||||
|
@ -650,17 +707,26 @@ static int xioopen_socks5(
|
|||
|
||||
Close(sfd->fd);
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
dropopts(opts, PH_ALL);
|
||||
opts = copyopts(opts0, GROUP_ALL);
|
||||
while (maxchildren > 0 && num_child >= maxchildren) {
|
||||
Info1("all %d allowed children are active, waiting", maxchildren);
|
||||
Nanosleep(&sfd->intervall, NULL);
|
||||
}
|
||||
freeopts(opts);
|
||||
continue;
|
||||
} else
|
||||
#endif
|
||||
#endif /* WITH_RETRY */
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return 0;
|
||||
Notice4("successfully connected to %s:%s via socks5 server %s:%s",
|
||||
target_name, target_port, socks_server, socks_port);
|
||||
|
||||
result = _xio_openlate(sfd, opts);
|
||||
freeopts(opts);
|
||||
freeopts(opts0);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
#endif /* WITH_SOCKS5 */
|
||||
|
|
|
@ -17,7 +17,7 @@ static int xioopen_stdio(int argc, const char *argv[], struct opt *opts, int xio
|
|||
static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
|
||||
|
||||
|
||||
/* we specify all option groups that we can imagine for a FD, becasue the
|
||||
/* We specify all option groups that we can imagine for a FD, because the
|
||||
changed parsing mechanism does not allow us to check the type of FD before
|
||||
applying the options */
|
||||
const struct addrdesc xioaddr_stdio = { "STDIO", 3, xioopen_stdio, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(NULL) };
|
||||
|
|
|
@ -65,7 +65,7 @@ void dummy(void) {
|
|||
#else /* !defined(ENABLE_APPLYOPT) */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
#if WITH_STREAMS /* make this address configure dependend */
|
||||
#if WITH_STREAMS /* make this address configure dependent */
|
||||
#include "xioopen.h"
|
||||
|
||||
#include "xio-fd.h"
|
||||
|
|
|
@ -79,7 +79,7 @@ int xio_retropt_tcpwrap(
|
|||
}
|
||||
|
||||
|
||||
/* returns -1 if forbidden, 0 if no tcpwrap check, or 1 if explicitely allowed
|
||||
/* Returns -1 if forbidden, 0 if no tcpwrap check, or 1 if explicitly allowed
|
||||
*/
|
||||
int xio_tcpwrap_check(
|
||||
struct single *sfd,
|
||||
|
|
|
@ -501,7 +501,7 @@ int xiotermios_spec(int fd, int optcode) {
|
|||
#if HAVE_CFMAKERAW
|
||||
cfmakeraw(&_xiotermios_data.termarg);
|
||||
#else
|
||||
/* these setting follow the Linux documenation of cfmakeraw */
|
||||
/* These settings follow the Linux documentation of cfmakeraw */
|
||||
_xiotermios_data.termarg.c_iflag &=
|
||||
~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
|
||||
_xiotermios_data.termarg.c_oflag &= ~(OPOST);
|
||||
|
|
|
@ -120,7 +120,7 @@ static int xioopen_tun(
|
|||
if (retropt_bool(opts, OPT_IFF_NO_PI, &no_pi) == 0) {
|
||||
if (no_pi) {
|
||||
ifr.ifr_flags |= IFF_NO_PI;
|
||||
#if 0 /* not neccessary for now */
|
||||
#if 0 /* not necessary for now */
|
||||
} else {
|
||||
ifr.ifr_flags &= ~IFF_NO_PI;
|
||||
#endif
|
||||
|
@ -139,7 +139,7 @@ static int xioopen_tun(
|
|||
/* we seem to need a socket for manipulating the interface */
|
||||
if ((sockfd = Socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
Error1("socket(PF_INET, SOCK_DGRAM, 0): %s", strerror(errno));
|
||||
sockfd = sfd->fd; /* desparate fallback attempt */
|
||||
sockfd = sfd->fd; /* desperate fallback attempt */
|
||||
}
|
||||
|
||||
/*--------------------- setting interface address and netmask ------------*/
|
||||
|
|
33
xio-udp.c
33
xio-udp.c
|
@ -85,7 +85,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
|
|||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
#if WITH_IP4 /*|| WITH_IP6*/
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, pf, &sfd->para.socket.range,
|
||||
sfd->para.socket.ip.ai_flags)
|
||||
|
@ -277,8 +277,10 @@ int xioopen_ipdgram_listen(
|
|||
int pf = addrdesc->arg1;
|
||||
int ipproto = addrdesc->arg2;
|
||||
union sockaddr_union us;
|
||||
int bind_rc;
|
||||
int socktype = SOCK_DGRAM;
|
||||
socklen_t uslen;
|
||||
int result;
|
||||
|
||||
if (argc != 2) {
|
||||
xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
|
||||
|
@ -295,12 +297,31 @@ int xioopen_ipdgram_listen(
|
|||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
retropt_bind(opts, pf, socktype, ipproto,
|
||||
bind_rc = retropt_bind(opts, pf, socktype, ipproto,
|
||||
(struct sockaddr *)&us, &uslen, 1,
|
||||
xfd->stream.para.socket.ip.ai_flags);
|
||||
if (bind_rc == STAT_NORETRY)
|
||||
return STAT_NORETRY;
|
||||
if (pf == PF_UNSPEC && bind_rc == STAT_OK)
|
||||
pf = us.soa.sa_family;
|
||||
|
||||
if (false) {
|
||||
;
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
} else if (pf == PF_UNSPEC && bind_rc == STAT_NOACTION) {
|
||||
int ai_flags[2];
|
||||
ai_flags[0] = sfd->para.socket.ip.ai_flags[0];
|
||||
ai_flags[1] = sfd->para.socket.ip.ai_flags[1];
|
||||
if (!(ai_flags[1] & AI_PASSIVE))
|
||||
ai_flags[0] |= AI_PASSIVE;
|
||||
result =
|
||||
xioresolve(NULL, portname, pf, socktype, ipproto, &us, &uslen, ai_flags);
|
||||
if (result != STAT_OK) {
|
||||
Error("error resolving bind option");
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
pf = us.soa.sa_family;
|
||||
#endif /* WITH_IP4 || WITH_IP6*/
|
||||
#if WITH_IP4
|
||||
} else if (pf == PF_INET) {
|
||||
us.ip4.sin_port = parseport(portname, ipproto);
|
||||
|
@ -349,7 +370,7 @@ int xioopen_udp_sendto(
|
|||
applies and consumes the following option:
|
||||
PH_INIT, PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE
|
||||
OFUNC_OFFSET
|
||||
OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
|
||||
OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_O_CLOEXEC
|
||||
*/
|
||||
int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
||||
struct opt *opts,
|
||||
|
@ -529,7 +550,7 @@ int xioopen_udp_recvfrom(
|
|||
if (sfd->howtoend == END_UNSPEC)
|
||||
sfd->howtoend = END_NONE;
|
||||
|
||||
/* Set AI_PASSIVE, except when it is explicitely disabled */
|
||||
/* Set AI_PASSIVE, except when it is explicitly disabled */
|
||||
ai_flags2[0] = xfd->stream.para.socket.ip.ai_flags[0];
|
||||
ai_flags2[1] = xfd->stream.para.socket.ip.ai_flags[1];
|
||||
if (!(ai_flags2[1] & AI_PASSIVE))
|
||||
|
@ -605,7 +626,7 @@ int xioopen_udp_recv(
|
|||
xioinit_ip(&pf, xioparms.default_ip);
|
||||
retropt_socket_pf(opts, &pf);
|
||||
|
||||
/* Set AI_PASSIVE, except when it is explicitely disabled */
|
||||
/* Set AI_PASSIVE, except when it is explicitly disabled */
|
||||
ai_flags2[0] = xfd->stream.para.socket.ip.ai_flags[0];
|
||||
ai_flags2[1] = xfd->stream.para.socket.ip.ai_flags[1];
|
||||
if (!(ai_flags2[1] & AI_PASSIVE))
|
||||
|
@ -646,7 +667,7 @@ int xioopen_udp_recv(
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WITH_IP4 /*|| WITH_IP6*/
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
|
||||
if (xioparserange(rangename, pf, &xfd->stream.para.socket.range,
|
||||
xfd->stream.para.socket.ip.ai_flags)
|
||||
|
|
36
xio-unix.c
36
xio-unix.c
|
@ -15,7 +15,7 @@
|
|||
|
||||
#if WITH_UNIX
|
||||
|
||||
/* to avoid unneccessary runtime if () conditionals when no abstract support is
|
||||
/* To avoid unnecessary runtime if () conditionals when no abstract support is
|
||||
compiled in (or at least to give optimizing compilers a good chance) we need
|
||||
a constant that can be used in C expressions */
|
||||
#if WITH_ABSTRACT_UNIXSOCKET
|
||||
|
@ -33,7 +33,7 @@ static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, i
|
|||
|
||||
/* the first free parameter is 0 for "normal" unix domain sockets, or 1 for
|
||||
abstract unix sockets (Linux); the second and third free parameter are
|
||||
unsused */
|
||||
unused */
|
||||
const struct addrdesc xioaddr_unix_connect = { "UNIX-CONNECT", 1+XIO_RDWR, xioopen_unix_connect, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, 0, 0 HELP(":<filename>") };
|
||||
#if WITH_LISTEN
|
||||
const struct addrdesc xioaddr_unix_listen = { "UNIX-LISTEN", 1+XIO_RDWR, xioopen_unix_listen, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<filename>") };
|
||||
|
@ -123,6 +123,7 @@ static int xioopen_unix_listen(
|
|||
/* we expect the form: filename */
|
||||
const char *name;
|
||||
xiosingle_t *sfd = &xxfd->stream;
|
||||
char *bindstring = NULL;
|
||||
int pf = PF_UNIX;
|
||||
int socktype = SOCK_STREAM;
|
||||
int protocol = 0;
|
||||
|
@ -140,6 +141,12 @@ static int xioopen_unix_listen(
|
|||
}
|
||||
name = argv[1];
|
||||
|
||||
if (retropt_string(opts, OPT_BIND, &bindstring) == 0) {
|
||||
Error2("%s:%s: binds implicitly, bind option not allowed",
|
||||
addrdesc->defname, argv[1]);
|
||||
free(bindstring);
|
||||
}
|
||||
|
||||
sfd->para.socket.un.tight = UNIX_TIGHTSOCKLEN;
|
||||
retropt_socket_pf(opts, &pf);
|
||||
if (sfd->howtoend == END_UNSPEC)
|
||||
|
@ -257,7 +264,12 @@ static int xioopen_unix_connect(
|
|||
|
||||
if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
|
||||
(addrdesc->arg1/*abstract*/<<1)|sfd->para.socket.un.tight,
|
||||
sfd->para.socket.ip.ai_flags)
|
||||
#if WITH_TCP
|
||||
sfd->para.socket.ip.ai_flags
|
||||
#else
|
||||
0
|
||||
#endif /* WITH_TCP */
|
||||
)
|
||||
== STAT_OK) {
|
||||
needbind = true;
|
||||
}
|
||||
|
@ -426,7 +438,12 @@ static int xioopen_unix_sendto(
|
|||
|
||||
if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
|
||||
(addrdesc->arg1/*abstract*/<<1)| sfd->para.socket.un.tight,
|
||||
sfd->para.socket.ip.ai_flags)
|
||||
#if WITH_TCP
|
||||
sfd->para.socket.ip.ai_flags
|
||||
#else
|
||||
0
|
||||
#endif /* WITH_TCP */
|
||||
)
|
||||
== STAT_OK) {
|
||||
needbind = true;
|
||||
}
|
||||
|
@ -665,7 +682,7 @@ static int xioopen_unix_client(
|
|||
PH_CONNECTED, PH_LATE, ?PH_CONNECT
|
||||
OFUNC_OFFSET,
|
||||
OPT_PROTOCOL_FAMILY, OPT_UNIX_TIGHTSOCKLEN, OPT_UNLINK_CLOSE, OPT_BIND,
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_CLOEXEC, OPT_USER, OPT_GROUP, ?OPT_FORK,
|
||||
OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_O_CLOEXEC, OPT_USER, OPT_GROUP, ?OPT_FORK,
|
||||
*/
|
||||
int
|
||||
_xioopen_unix_client(
|
||||
|
@ -709,7 +726,12 @@ _xioopen_unix_client(
|
|||
|
||||
if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
|
||||
(abstract<<1)|sfd->para.socket.un.tight,
|
||||
sfd->para.socket.ip.ai_flags)
|
||||
#if WITH_TCP
|
||||
sfd->para.socket.ip.ai_flags
|
||||
#else
|
||||
0
|
||||
#endif /* WITH_TCP */
|
||||
)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
}
|
||||
|
@ -773,7 +795,7 @@ _xioopen_unix_client(
|
|||
opts, pf, SOCK_SEQPACKET, protocol,
|
||||
needtemp, E_INFO)) == 0)
|
||||
break;
|
||||
if (errno != EPROTOTYPE && errno != EPROTONOSUPPORT/*AIX*/
|
||||
if (errno != EPROTOTYPE && errno != EPROTONOSUPPORT/*AIX*/ && errno != ESOCKTNOSUPPORT/*Debian3*/
|
||||
#if WITH_ABSTRACT_UNIXSOCKET
|
||||
&& !(abstract && errno == ECONNREFUSED)
|
||||
#endif
|
||||
|
|
|
@ -98,7 +98,7 @@ static int xioopen_vsock_connect(
|
|||
|
||||
ret = retropt_bind(opts, pf, socktype, protocol,
|
||||
(struct sockaddr *)&sa_local, &sa_len, 3,
|
||||
sfd->para.socket.ip.ai_flags);
|
||||
NULL);
|
||||
if (ret == STAT_NORETRY)
|
||||
return ret;
|
||||
if (ret == STAT_OK)
|
||||
|
|
3
xio.h
3
xio.h
|
@ -120,12 +120,13 @@ typedef struct xioparms {
|
|||
const char *sniffleft_name; /* file name with -r */
|
||||
const char *sniffright_name; /* file name with -R */
|
||||
size_t bufsiz;
|
||||
struct timeval total_timeout;/* when nothing happens, die after seconds */
|
||||
} xioparms_t;
|
||||
|
||||
/* pack the description of a lock file */
|
||||
typedef struct {
|
||||
const char *lockfile; /* name of lockfile; NULL if no locking */
|
||||
bool waitlock; /* dont't exit when already locked */
|
||||
bool waitlock; /* don't exit when already locked */
|
||||
struct timespec intervall; /* polling intervall */
|
||||
} xiolock_t;
|
||||
|
||||
|
|
18
xioconfig.h
18
xioconfig.h
|
@ -16,7 +16,13 @@
|
|||
# define WITH_OPEN 1
|
||||
#endif
|
||||
|
||||
#if WITH_OPEN || WITH_PIPE || WITH_UNIX || WITH_PTY
|
||||
#if WITH_INTERFACE || WITH_TUN
|
||||
# define _WITH_INTERFACE 1
|
||||
#else
|
||||
# define _WITH_INTERFACE 0
|
||||
#endif
|
||||
|
||||
#if WITH_OPEN || WITH_PIPE || WITH_UNIX || WITH_PTY || _WITH_INTERFACE
|
||||
# define WITH_NAMED 1
|
||||
#endif
|
||||
|
||||
|
@ -34,7 +40,7 @@
|
|||
with IP6 */
|
||||
#endif
|
||||
|
||||
#if WITH_OPENSSL
|
||||
#if WITH_OPENSSL || WITH_SOCKS5
|
||||
# define WITH_TCP 1
|
||||
# define WITH_IP4 1
|
||||
#endif
|
||||
|
@ -57,7 +63,7 @@
|
|||
# define _WITH_UDP 1
|
||||
#endif
|
||||
|
||||
#if WITH_UNIX || WITH_IP4 || WITH_IP6 || WITH_SOCKS4 || WITH_RAWIP || WITH_GENERICSOCKET
|
||||
#if WITH_UNIX || WITH_IP4 || WITH_IP6 || WITH_SOCKS4 || WITH_SOCKS5 || WITH_RAWIP || WITH_GENERICSOCKET || WITH_SOCKETPAIR || WITH_VSOCK
|
||||
# define _WITH_SOCKET 1
|
||||
#else
|
||||
# undef _WITH_SOCKET
|
||||
|
@ -71,10 +77,8 @@
|
|||
# undef WITH_LIBWRAP
|
||||
#endif
|
||||
|
||||
#if WITH_INTERFACE || WITH_TUN
|
||||
# define _WITH_INTERFACE 1
|
||||
#else
|
||||
# define _WITH_INTERFACE 0
|
||||
#if WITH_SOCKETPAIR || WITH_EXEC || WITH_SYSTEM || WITH_SHELL
|
||||
# define _WITH_SOCKETPAIR 1
|
||||
#endif
|
||||
|
||||
#if WITH_GENERICSOCKET || _WITH_INTERFACE
|
||||
|
|
|
@ -53,7 +53,7 @@ static const char *addressgroupnames[] = {
|
|||
|
||||
/* keep consistent with xioopts.h:enum ephase ! */
|
||||
static char *optionphasenames[] = {
|
||||
"ALL", "INIT", "EARLY",
|
||||
"ALL", "OFFSET", "INIT", "EARLY",
|
||||
"PREOPEN", "OPEN", "PASTOPEN",
|
||||
"PRESOCKET", "SOCKET", "PASTSOCKET",
|
||||
"PREBIGEN", "BIGEN", "PASTBIGEN",
|
||||
|
@ -87,6 +87,8 @@ static int xiohelp_option(FILE *of, const struct optname *on, const char *name)
|
|||
groups = on->desc->group;
|
||||
occurred = false;
|
||||
chars = 7;
|
||||
if (groups == 0)
|
||||
fputs("(all)", of);
|
||||
for (j = 0; j < 8*sizeof(groups_t); ++j) {
|
||||
if (groups & 1) {
|
||||
if (occurred) {
|
||||
|
@ -150,8 +152,9 @@ int xioopenhelp(FILE *of,
|
|||
i = (40 - chars + 7) / 8;
|
||||
for (; i > 0; --i) { fputc('\t', of); }
|
||||
fputs("\tgroups=", of);
|
||||
groups = an->desc->groups; occurred = false;
|
||||
for (j = 0; j < 32; ++j) {
|
||||
groups = an->desc->groups;
|
||||
occurred = false;
|
||||
for (j = 0; j < sizeof(groups_t)*8; ++j) {
|
||||
if (groups & 1) {
|
||||
if (occurred) { fputc(',', of); }
|
||||
fprintf(of, "%s", addressgroupnames[j]);
|
||||
|
|
|
@ -175,8 +175,8 @@ static int xio_nokill(xiofile_t *sock) {
|
|||
return result;
|
||||
}
|
||||
|
||||
/* call this function immediately after fork() in child process */
|
||||
/* it performs some neccessary actions
|
||||
/* Call this function immediately after fork() in child process */
|
||||
/* It performs some necessary actions
|
||||
returns 0 on success or != 0 if an error occurred */
|
||||
int xio_forked_inchild(void) {
|
||||
int result = 0;
|
||||
|
|
|
@ -48,7 +48,8 @@ int xio_chdir(
|
|||
free(tmp_dir);
|
||||
return -1;
|
||||
}
|
||||
*orig_dir = Realloc(*orig_dir, strlen(*orig_dir)+1);
|
||||
/*0 *orig_dir = Realloc(*orig_dir, strlen(*orig_dir)+1); */
|
||||
*orig_dir = Realloc3(*orig_dir, strlen(*orig_dir)+1, PATH_MAX);
|
||||
|
||||
if (Chdir(tmp_dir) < 0) {
|
||||
Error2("chdir(\"%s\"): %s", tmp_dir, strerror(errno));
|
||||
|
|
|
@ -52,7 +52,7 @@ int xiogetlock(const char *lockfile) {
|
|||
|
||||
pid = Getpid();
|
||||
bytes = sprintf(pidbuf, F_pid"\n", pid);
|
||||
if (writefull(fd, pidbuf, bytes) < 0) {
|
||||
if (writefull(fd, pidbuf, bytes, NULL) < 0) {
|
||||
Error4("write(%d, %p, "F_Zu"): %s", fd, pidbuf, bytes, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
|
20
xioopen.c
20
xioopen.c
|
@ -177,11 +177,13 @@ const struct addrname addressnames[] = {
|
|||
{ "PIPE", &xioaddr_pipe },
|
||||
#endif
|
||||
#if WITH_POSIXMQ
|
||||
{ "POSIXMQ", &xioaddr_posixmq_bidir },
|
||||
{ "POSIXMQ-BIDIRECTIONAL", &xioaddr_posixmq_bidir },
|
||||
{ "POSIXMQ-READ", &xioaddr_posixmq_read },
|
||||
{ "POSIXMQ-RECEIVE", &xioaddr_posixmq_receive },
|
||||
{ "POSIXMQ-RECV", &xioaddr_posixmq_receive },
|
||||
{ "POSIXMQ-SEND", &xioaddr_posixmq_send },
|
||||
{ "POSIXMQ-WRITE", &xioaddr_posixmq_write },
|
||||
#endif
|
||||
#if WITH_PROXY
|
||||
{ "PROXY", &xioaddr_proxy_connect },
|
||||
|
@ -471,14 +473,14 @@ static xiofile_t *xioallocfd(void) {
|
|||
fd->stream.escape = -1;
|
||||
/* fd->stream.para.exec.pid = 0; */
|
||||
fd->stream.lineterm = LINETERM_RAW;
|
||||
#if WITH_RESOLVE
|
||||
#if ( _WITH_IP4 || _WITH_IP6 ) && WITH_RESOLVE
|
||||
#if HAVE_RES_RETRANS
|
||||
fd->stream.para.socket.ip.res.retrans = -1;
|
||||
#endif
|
||||
#if HAVE_RES_RETRY
|
||||
fd->stream.para.socket.ip.res.retry = -1;
|
||||
#endif
|
||||
#endif /* WITH_RESOLVE */
|
||||
#endif /* ( _WITH_IP4 || _WITH_IP6 ) && WITH_RESOLVE */
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
@ -701,10 +703,10 @@ int xioopen_single(xiofile_t *xfd, int xioflags) {
|
|||
mode_t orig_umask, tmp_umask;
|
||||
int result;
|
||||
/* Values to be saved until xioopen() is finished */
|
||||
#if WITH_RESOLVE && HAVE_RESOLV_H
|
||||
#if ( _WITH_IP4 || _WITH_IP6 ) && WITH_RESOLVE && HAVE_RESOLV_H
|
||||
int do_res;
|
||||
struct __res_state save_res;
|
||||
#endif /* WITH_RESOLVE && HAVE_RESOLV_H */
|
||||
#endif
|
||||
#if WITH_NAMESPACES
|
||||
int save_netfd = -1;
|
||||
#endif
|
||||
|
@ -730,15 +732,15 @@ int xioopen_single(xiofile_t *xfd, int xioflags) {
|
|||
if (applyopts_single(sfd, sfd->opts, PH_OFFSET) < 0)
|
||||
return -1;
|
||||
|
||||
#if WITH_NAMESPACES
|
||||
#if WITH_NAMESPACES /* netns */
|
||||
if ((save_netfd = xio_apply_namespace(sfd->opts)) < 0)
|
||||
return -1;
|
||||
#endif /* WITH_NAMESPACES */
|
||||
|
||||
#if WITH_RESOLVE && HAVE_RESOLV_H
|
||||
#if ( _WITH_IP4 || _WITH_IP6 ) && WITH_RESOLVE && HAVE_RESOLV_H
|
||||
if ((do_res = xio_res_init(sfd, &save_res)) < 0)
|
||||
return STAT_NORETRY;
|
||||
#endif /* WITH_RESOLVE && HAVE_RESOLV_H */
|
||||
#endif
|
||||
|
||||
if (xio_chdir(sfd->opts, &orig_dir) < 0)
|
||||
return STAT_NORETRY;
|
||||
|
@ -769,10 +771,10 @@ int xioopen_single(xiofile_t *xfd, int xioflags) {
|
|||
free(orig_dir);
|
||||
}
|
||||
|
||||
#if WITH_RESOLVE && HAVE_RESOLV_H
|
||||
#if ( _WITH_IP4 || _WITH_IP6 ) && WITH_RESOLVE && HAVE_RESOLV_H
|
||||
if (do_res)
|
||||
xio_res_restore(&save_res);
|
||||
#endif /* WITH_RESOLVE && HAVE_RESOLV_H */
|
||||
#endif
|
||||
|
||||
#if WITH_NAMESPACES
|
||||
if (save_netfd > 0) {
|
||||
|
|
121
xioopts.c
121
xioopts.c
|
@ -177,7 +177,7 @@ static int applyopt(struct single *sfd, int fd, struct opt *opt);
|
|||
binary search! */
|
||||
/* NULL terminated */
|
||||
const struct optname optionnames[] = {
|
||||
#if HAVE_RESOLV_H && WITH_RES_AAONLY
|
||||
#if (WITH_IP4 || WITH_IP6) && HAVE_RESOLV_H && WITH_RES_AAONLY
|
||||
IF_RESOLVE("aaonly", &opt_res_aaonly)
|
||||
#endif
|
||||
#ifdef TCP_ABORT_THRESHOLD /* HP_UX */
|
||||
|
@ -352,7 +352,7 @@ const struct optname optionnames[] = {
|
|||
#endif /* SO_CKSUMRECV */
|
||||
/*IF_NAMED ("cleanup", &opt_cleanup)*/
|
||||
IF_TERMIOS("clocal", &opt_clocal)
|
||||
IF_ANY ("cloexec", &opt_cloexec)
|
||||
IF_ANY ("cloexec", &opt_cloexec)
|
||||
IF_ANY ("close", &opt_end_close)
|
||||
IF_OPENSSL("cn", &opt_openssl_commonname)
|
||||
IF_OPENSSL("commonname", &opt_openssl_commonname)
|
||||
|
@ -390,8 +390,8 @@ const struct optname optionnames[] = {
|
|||
# endif
|
||||
#endif /* defined(CRDLY) */
|
||||
IF_TERMIOS("cread", &opt_cread)
|
||||
IF_OPEN ("creat", &opt_o_create)
|
||||
IF_OPEN ("create", &opt_o_create)
|
||||
IF_OPEN ("creat", &opt_o_creat)
|
||||
IF_OPEN ("create", &opt_o_creat)
|
||||
IF_ANY ("crlf", &opt_crnl)
|
||||
IF_ANY ("crnl", &opt_crnl)
|
||||
IF_TERMIOS("crterase", &opt_echoe)
|
||||
|
@ -421,7 +421,7 @@ const struct optname optionnames[] = {
|
|||
#ifdef TCP_DEFER_ACCEPT /* Linux 2.4.0 */
|
||||
IF_TCP ("defer-accept", &opt_tcp_defer_accept)
|
||||
#endif
|
||||
#if HAVE_RESOLV_H
|
||||
#if (WITH_IP4 || WITH_IP6) && HAVE_RESOLV_H
|
||||
IF_RESOLVE("defnames", &opt_res_defnames)
|
||||
#endif /* HAVE_RESOLV_H */
|
||||
#ifdef O_DELAY
|
||||
|
@ -454,10 +454,10 @@ const struct optname optionnames[] = {
|
|||
#ifdef VDISCARD
|
||||
IF_TERMIOS("discard", &opt_vdiscard)
|
||||
#endif
|
||||
#if WITH_RESOLVE && HAVE_RESOLV_H && HAVE_RES_NSADDR_LIST
|
||||
#if (WITH_IP4 || WITH_IP6) && WITH_RESOLVE && HAVE_RESOLV_H && HAVE_RES_NSADDR_LIST
|
||||
IF_IP ("dns", &opt_res_nsaddr)
|
||||
#endif
|
||||
#if HAVE_RESOLV_H
|
||||
#if (WITH_IP4 || WITH_IP6) && HAVE_RESOLV_H
|
||||
IF_RESOLVE("dnsrch", &opt_res_dnsrch)
|
||||
#endif /* HAVE_RESOLV_H */
|
||||
#ifdef SO_DONTLINGER
|
||||
|
@ -721,7 +721,7 @@ const struct optname optionnames[] = {
|
|||
IF_ANY ("ignoreeof", &opt_ignoreeof)
|
||||
IF_ANY ("ignoreof", &opt_ignoreeof)
|
||||
IF_TERMIOS("ignpar", &opt_ignpar)
|
||||
#if HAVE_RESOLV_H
|
||||
#if (WITH_IP4 || WITH_IP6) && HAVE_RESOLV_H
|
||||
IF_RESOLVE("igntc", &opt_res_igntc)
|
||||
#endif /* HAVE_RESOLV_H */
|
||||
IF_TERMIOS("imaxbel", &opt_imaxbel)
|
||||
|
@ -1032,7 +1032,10 @@ const struct optname optionnames[] = {
|
|||
#endif
|
||||
IF_ANY ("mode", &opt_perm)
|
||||
#if WITH_POSIXMQ
|
||||
IF_ANY ("mq-prio", &opt_posixmq_priority)
|
||||
IF_ANY ("mq-flush", &opt_posixmq_flush)
|
||||
IF_ANY ("mq-maxmsg", &opt_posixmq_maxmsg)
|
||||
IF_ANY ("mq-msgsize", &opt_posixmq_msgsize)
|
||||
IF_ANY ("mq-prio", &opt_posixmq_priority)
|
||||
#endif
|
||||
#ifdef TCP_MAXSEG
|
||||
IF_TCP ("mss", &opt_tcp_maxseg)
|
||||
|
@ -1050,7 +1053,7 @@ const struct optname optionnames[] = {
|
|||
IF_IP ("multicast-ttl", &opt_ip_multicast_ttl)
|
||||
IF_IP ("multicastloop", &opt_ip_multicast_loop)
|
||||
IF_IP ("multicastttl", &opt_ip_multicast_ttl)
|
||||
#if WITH_RESOLVE && HAVE_RESOLV_H && HAVE_RES_NSADDR_LIST
|
||||
#if (WITH_IP4 || WITH_IP6) && WITH_RESOLVE && HAVE_RESOLV_H && HAVE_RES_NSADDR_LIST
|
||||
IF_IP ("nameserver", &opt_res_nsaddr)
|
||||
#endif
|
||||
#if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
|
||||
|
@ -1118,7 +1121,7 @@ const struct optname optionnames[] = {
|
|||
IF_OPENSSL("nosni", &opt_openssl_no_sni)
|
||||
#endif
|
||||
IF_INTERFACE("notrailers", &opt_iff_notrailers)
|
||||
#if WITH_RESOLVE && HAVE_RESOLV_H && HAVE_RES_NSADDR_LIST
|
||||
#if (WITH_IP4 || WITH_IP6) && WITH_RESOLVE && HAVE_RESOLV_H && HAVE_RES_NSADDR_LIST
|
||||
IF_IP ("nsaddr", &opt_res_nsaddr)
|
||||
#endif
|
||||
#ifdef O_NSHARE
|
||||
|
@ -1132,8 +1135,8 @@ const struct optname optionnames[] = {
|
|||
#ifdef O_BINARY
|
||||
IF_OPEN ("o-binary", &opt_o_binary)
|
||||
#endif
|
||||
IF_OPEN ("o-creat", &opt_o_create)
|
||||
IF_OPEN ("o-create", &opt_o_create)
|
||||
IF_OPEN ("o-creat", &opt_o_creat)
|
||||
IF_OPEN ("o-create", &opt_o_creat)
|
||||
#ifdef O_DEFER
|
||||
IF_OPEN ("o-defer", &opt_o_defer)
|
||||
#endif
|
||||
|
@ -1191,7 +1194,8 @@ const struct optname optionnames[] = {
|
|||
#endif
|
||||
IF_OPEN ("o-trunc", &opt_o_trunc)
|
||||
IF_OPEN ("o-wronly", &opt_o_wronly)
|
||||
IF_OPEN ("o_create", &opt_o_create)
|
||||
IF_OPEN ("o_creat", &opt_o_creat)
|
||||
IF_OPEN ("o_create", &opt_o_creat)
|
||||
#ifdef O_DEFER
|
||||
IF_OPEN ("o_defer", &opt_o_defer)
|
||||
#endif
|
||||
|
@ -1348,9 +1352,12 @@ const struct optname optionnames[] = {
|
|||
IF_INTERFACE("portsel", &opt_iff_portsel)
|
||||
#endif
|
||||
#if WITH_POSIXMQ
|
||||
IF_ANY ("posixmq-flush", &opt_posixmq_flush)
|
||||
IF_ANY ("posixmq-maxmsg", &opt_posixmq_maxmsg)
|
||||
IF_ANY ("posixmq-msgsize", &opt_posixmq_msgsize)
|
||||
IF_ANY ("posixmq-priority", &opt_posixmq_priority)
|
||||
#endif
|
||||
#if HAVE_RESOLV_H && WITH_RES_PRIMARY
|
||||
#if (WITH_IP4 || WITH_IP6) && HAVE_RESOLV_H && WITH_RES_PRIMARY
|
||||
IF_RESOLVE("primary", &opt_res_primary)
|
||||
#endif
|
||||
#ifdef SO_PRIORITY
|
||||
|
@ -1411,7 +1418,7 @@ const struct optname optionnames[] = {
|
|||
IF_OPEN ("rdonly", &opt_o_rdonly)
|
||||
IF_OPEN ("rdwr", &opt_o_rdwr)
|
||||
IF_ANY ("readbytes", &opt_readbytes)
|
||||
#if HAVE_RESOLV_H
|
||||
#if (WITH_IP4 || WITH_IP6) && HAVE_RESOLV_H
|
||||
IF_RESOLVE("recurse", &opt_res_recurse)
|
||||
#endif /* HAVE_RESOLV_H */
|
||||
#ifdef IP_RECVDSTADDR
|
||||
|
@ -1451,7 +1458,7 @@ const struct optname optionnames[] = {
|
|||
#ifdef VREPRINT
|
||||
IF_TERMIOS("reprint", &opt_vreprint)
|
||||
#endif
|
||||
#if HAVE_RESOLV_H
|
||||
#if (WITH_IP4 || WITH_IP6) && HAVE_RESOLV_H
|
||||
# if WITH_AA_ONLY
|
||||
IF_RESOLVE("res-aaonly", &opt_res_aaonly)
|
||||
# endif
|
||||
|
@ -1480,15 +1487,15 @@ const struct optname optionnames[] = {
|
|||
# endif
|
||||
IF_RESOLVE("res-stayopen", &opt_res_stayopen)
|
||||
IF_RESOLVE("res-usevc", &opt_res_usevc)
|
||||
#endif /* HAVE_RESOLV_H */
|
||||
#endif /* (WITH_IP4 || WITH_IP6) && HAVE_RESOLV_H */
|
||||
IF_PROXY ("resolv", &opt_proxy_resolve)
|
||||
IF_PROXY ("resolve", &opt_proxy_resolve)
|
||||
#ifdef IP_RETOPTS
|
||||
IF_IP ("retopts", &opt_ip_retopts)
|
||||
#endif
|
||||
# if HAVE_RES_RETRANS
|
||||
#if (WITH_IP4 || WITH_IP6) && HAVE_RES_RETRANS
|
||||
IF_RESOLVE("retrans", &opt_res_retrans)
|
||||
# endif
|
||||
#endif
|
||||
#if WITH_INTERFACE && defined(PACKET_AUXDATA)
|
||||
IF_SOCKET ("retrieve-vlan", &opt_retrieve_vlan)
|
||||
#endif
|
||||
|
@ -1576,8 +1583,10 @@ const struct optname optionnames[] = {
|
|||
#endif
|
||||
IF_SOCKET ("setsockopt", &opt_setsockopt)
|
||||
IF_SOCKET ("setsockopt-bin", &opt_setsockopt_bin)
|
||||
IF_SOCKET ("setsockopt-connected", &opt_setsockopt_connected)
|
||||
IF_SOCKET ("setsockopt-int", &opt_setsockopt_int)
|
||||
IF_SOCKET ("setsockopt-listen", &opt_setsockopt_listen)
|
||||
IF_SOCKET ("setsockopt-socket", &opt_setsockopt_socket)
|
||||
IF_SOCKET ("setsockopt-string", &opt_setsockopt_string)
|
||||
IF_ANY ("setuid", &opt_setuid)
|
||||
IF_ANY ("setuid-early", &opt_setuid_early)
|
||||
|
@ -1712,8 +1721,10 @@ const struct optname optionnames[] = {
|
|||
#endif /* SO_USELOOPBACK */
|
||||
IF_SOCKET ("sockopt", &opt_setsockopt)
|
||||
IF_SOCKET ("sockopt-bin", &opt_setsockopt_bin)
|
||||
IF_SOCKET ("sockopt-conn", &opt_setsockopt_connected)
|
||||
IF_SOCKET ("sockopt-int", &opt_setsockopt_int)
|
||||
IF_SOCKET ("sockopt-listen", &opt_setsockopt_listen)
|
||||
IF_SOCKET ("sockopt-sock", &opt_setsockopt_socket)
|
||||
IF_SOCKET ("sockopt-string", &opt_setsockopt_string)
|
||||
IF_SOCKS4 ("socksport", &opt_socksport)
|
||||
IF_SOCKS4 ("socksuser", &opt_socksuser)
|
||||
|
@ -1724,7 +1735,7 @@ const struct optname optionnames[] = {
|
|||
IF_IPAPP ("sourceport", &opt_sourceport)
|
||||
IF_IPAPP ("sp", &opt_sourceport)
|
||||
IF_TERMIOS("start", &opt_vstart)
|
||||
#if HAVE_RESOLV_H
|
||||
#if (WITH_IP4 || WITH_IP6) && HAVE_RESOLV_H
|
||||
IF_RESOLVE("stayopen", &opt_res_stayopen)
|
||||
#endif /* HAVE_RESOLV_H */
|
||||
IF_EXEC ("stderr", &opt_stderr)
|
||||
|
@ -1930,7 +1941,7 @@ const struct optname optionnames[] = {
|
|||
IF_ANY ("user", &opt_user)
|
||||
IF_NAMED ("user-early", &opt_user_early)
|
||||
IF_ANY ("user-late", &opt_user_late)
|
||||
#if HAVE_RESOLV_H
|
||||
#if (WITH_IP4 || WITH_IP6) && HAVE_RESOLV_H
|
||||
IF_RESOLVE("usevc", &opt_res_usevc)
|
||||
#endif /* HAVE_RESOLV_H */
|
||||
#if defined(AI_V4MAPPED)
|
||||
|
@ -2654,13 +2665,13 @@ int parseopts_table(const char **a, groups_t groups, struct opt **opts,
|
|||
(*opts)[i].value3.u_string);
|
||||
break;
|
||||
|
||||
#if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
|
||||
#if (WITH_IP4 || WITH_IP6) && ( defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) )
|
||||
case TYPE_IP_MREQN:
|
||||
xiotype_ip_add_membership(token, ent, opt);
|
||||
break;
|
||||
#endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */
|
||||
#endif /* WITH_IP && defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) ) */
|
||||
|
||||
#if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP)
|
||||
#if _WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE)
|
||||
case TYPE_IP_MREQ_SOURCE:
|
||||
xiotype_ip_add_source_membership(token, ent, opt);
|
||||
break;
|
||||
|
@ -2768,7 +2779,8 @@ int parseopts_table(const char **a, groups_t groups, struct opt **opts,
|
|||
|
||||
++i;
|
||||
if ((i % 8) == 0) {
|
||||
*opts = Realloc(*opts, (i+8) * sizeof(struct opt));
|
||||
/*0 *opts = Realloc(*opts, (i+8) * sizeof(struct opt)); */
|
||||
*opts = Realloc3(*opts, (i+8) * sizeof(struct opt), i * sizeof(struct opt));
|
||||
if (*opts == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -2904,7 +2916,6 @@ int showleft(const struct opt *opts) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* determines the address group from mode_t */
|
||||
/* does not set GROUP_FD; cannot determine GROUP_TERMIOS ! */
|
||||
groups_t _groupbits(mode_t mode) {
|
||||
|
@ -3100,7 +3111,7 @@ int retropt_int(struct opt *opts, int optcode, int *result) {
|
|||
/* Looks for the first option of type <optcode>. If the option is found,
|
||||
this function stores its int value in *result, "consumes" the
|
||||
option, and returns 0.
|
||||
If the option is not found, *result is not modified, and -1 is returned. */
|
||||
If the option is not found, values are not modified, and -1 is returned. */
|
||||
int retropt_2integrals(struct opt *opts, int optcode,
|
||||
union integral *value1, union integral *value2)
|
||||
{
|
||||
|
@ -3250,7 +3261,8 @@ int retropt_bind(struct opt *opts,
|
|||
int ipproto,
|
||||
struct sockaddr *sa,
|
||||
socklen_t *salen,
|
||||
int feats, /* TCP etc: 1..address allowed,
|
||||
int feats, /* -1..generic addr spec
|
||||
TCP etc: 1..address allowed,
|
||||
3..address and port allowed
|
||||
UNIX (or'd): 1..tight
|
||||
2..abstract
|
||||
|
@ -3274,10 +3286,13 @@ int retropt_bind(struct opt *opts,
|
|||
}
|
||||
bindp = bindname;
|
||||
|
||||
switch (af) {
|
||||
#if WITH_IP4 && WITH_IP6
|
||||
/* Try to derive address family from string */
|
||||
if (af == AF_UNSPEC && bindname[0] == '[')
|
||||
af = AF_INET6;
|
||||
#endif /* WITH_IP4 && WITH_IP6 */
|
||||
|
||||
case AF_UNSPEC:
|
||||
{
|
||||
if (feats == -1) {
|
||||
size_t p = 0;
|
||||
dalan(bindname, (uint8_t *)sa->sa_data, &p, *salen-sizeof(sa->sa_family), 'i');
|
||||
*salen = p + sizeof(sa->sa_family);
|
||||
|
@ -3289,10 +3304,13 @@ int retropt_bind(struct opt *opts,
|
|||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
sa->sa_len = *salen;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
switch (af) {
|
||||
|
||||
#if WITH_IP4 || WITH_IP6 || WITH_VSOCK
|
||||
case AF_UNSPEC:
|
||||
#if WITH_VSOCK
|
||||
case AF_VSOCK:
|
||||
#endif
|
||||
|
@ -3323,11 +3341,12 @@ int retropt_bind(struct opt *opts,
|
|||
}
|
||||
}
|
||||
|
||||
/* Set AI_PASSIVE, except when it is explicitely disabled */
|
||||
# if WITH_IP4 || WITH_IP6
|
||||
/* Set AI_PASSIVE, except when it is explicitly disabled */
|
||||
ai_flags2[0] = ai_flags[0];
|
||||
ai_flags2[1] = ai_flags[1];
|
||||
if (!(ai_flags2[1] & AI_PASSIVE))
|
||||
ai_flags2[0] |= AI_PASSIVE;
|
||||
ai_flags2[0] |= AI_PASSIVE;
|
||||
|
||||
if ((result =
|
||||
xioresolve(hostname[0]!='\0'?hostname:NULL, portp,
|
||||
|
@ -3337,6 +3356,8 @@ int retropt_bind(struct opt *opts,
|
|||
Error("error resolving bind option");
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
/*# else */
|
||||
# endif /* WITH_IP4 || WITH_IP6 */
|
||||
break;
|
||||
#endif /* WITH_IP4 || WITH_IP6 || WITH_VSOCK */
|
||||
|
||||
|
@ -3567,6 +3588,8 @@ int applyopt_ioctl_generic(
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if _WITH_SOCKET
|
||||
|
||||
int applyopt_sockopt(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
|
@ -3695,7 +3718,7 @@ int applyopt_sockopt(
|
|||
}
|
||||
break;
|
||||
#endif /* HAVE_STRUCT_LINGER */
|
||||
#if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
|
||||
#if (WITH_IP4 || WITH_IP6) && ( defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) )
|
||||
case TYPE_IP_MREQN:
|
||||
/* handled in applyopts_single */
|
||||
break;
|
||||
|
@ -3815,6 +3838,9 @@ int applyopt_sockopt_generic(
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
#if HAVE_FLOCK
|
||||
int applyopt_flock(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
|
@ -3826,6 +3852,7 @@ int applyopt_flock(
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(HAVE_FLOCK) */
|
||||
|
||||
/* Applies an option that needs handling specific to its OPT_* setting.
|
||||
Does not overwrite the option instance with ODESC_DONE or ODESC_ERROR,
|
||||
|
@ -3921,8 +3948,12 @@ int applyopt_spec(
|
|||
{
|
||||
struct passwd *pwd;
|
||||
if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) {
|
||||
Error1("getpwuid("F_uid"): no such user",
|
||||
opt->value.u_uidt);
|
||||
if (errno != 0)
|
||||
Error2("getpwuid("F_uid"): %s",
|
||||
opt->value.u_uidt, strerror(errno));
|
||||
else
|
||||
Error1("getpwuid("F_uid"): no such user",
|
||||
opt->value.u_uidt);
|
||||
return -1;
|
||||
}
|
||||
if (Initgroups(pwd->pw_name, pwd->pw_gid) < 0) {
|
||||
|
@ -4216,7 +4247,7 @@ int applyopts_cloexec(int fd, struct opt *opts) {
|
|||
|
||||
if (!opts) return 0;
|
||||
|
||||
retropt_bool(opts, OPT_CLOEXEC, &docloexec);
|
||||
retropt_bool(opts, OPT_O_CLOEXEC, &docloexec);
|
||||
if (docloexec) {
|
||||
if (Fcntl_l(fd, F_SETFD, FD_CLOEXEC) < 0) {
|
||||
Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", fd, strerror(errno));
|
||||
|
@ -4272,6 +4303,7 @@ static int applyopt_offset(struct single *sfd, struct opt *opt) {
|
|||
case TYPE_CONST:
|
||||
*(int *)ptr = opt->desc->minor;
|
||||
break;
|
||||
#if WITH_IP4
|
||||
case TYPE_IP4NAME:
|
||||
memset(ptr, 0, sizeof(struct sockaddr_in));
|
||||
((struct sockaddr_in *)ptr)->sin_addr = opt->value.u_ip4addr;
|
||||
|
@ -4281,6 +4313,7 @@ static int applyopt_offset(struct single *sfd, struct opt *opt) {
|
|||
memset(ptr, 0, sizeof(struct sockaddr_in));
|
||||
*(struct sockaddr_in *)ptr = opt->value.u_ip4sock;
|
||||
break;
|
||||
#endif /* WITH_IP4 */
|
||||
default:
|
||||
Error2("applyopt_offset(opt:%s): type %s not implemented",
|
||||
opt->desc->defname, xiohelp_opttypename(opt->desc->type));
|
||||
|
@ -4664,3 +4697,11 @@ int dumpopts(struct opt *opts)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Better with type specific free function */
|
||||
void freeopts(
|
||||
struct opt *opts)
|
||||
{
|
||||
free(opts);
|
||||
return;
|
||||
}
|
||||
|
|
14
xioopts.h
14
xioopts.h
|
@ -72,7 +72,7 @@ enum e_types {
|
|||
#if HAVE_STRUCT_LINGER
|
||||
TYPE_LINGER, /* struct linger */
|
||||
#endif /* HAVE_STRUCT_LINGER */
|
||||
#if HAVE_STRUCT_IP_MREQ || HAVE_STRUCT_IP_MREQN
|
||||
#if (WITH_IP4 || WITH_IP6) && ( defined(HAVE_STRUCT_IP_MREQ) || defined(HAVE_STRUCT_IP_MREQN) )
|
||||
TYPE_IP_MREQN, /* for struct ip_mreq or struct ip_mreqn */
|
||||
#endif
|
||||
#if HAVE_STRUCT_IP_MREQ_SOURCE
|
||||
|
@ -150,7 +150,7 @@ enum e_func {
|
|||
#define GROUP_NONE 0x00000000
|
||||
#define GROUP_ADDR 0x00000000 /* options that apply to all addresses */
|
||||
|
||||
#define GROUP_FD 0x00000001 /* everything applyable to a fd */
|
||||
#define GROUP_FD 0x00000001 /* everything applicable to a fd */
|
||||
#define GROUP_FIFO 0x00000002
|
||||
#define GROUP_CHR 0x00000004 /* not yet used? */
|
||||
#define GROUP_BLK 0x00000008
|
||||
|
@ -272,7 +272,6 @@ enum e_optcode {
|
|||
OPT_CHROOT_EARLY, /* chroot() before file system access */
|
||||
/*OPT_CIBAUD,*/ /* termios.c_cflag */
|
||||
OPT_CLOCAL, /* termios.c_cflag */
|
||||
OPT_CLOEXEC,
|
||||
OPT_CONNECT_TIMEOUT, /* socket connect */
|
||||
OPT_COOL_WRITE,
|
||||
OPT_CR, /* customized */
|
||||
|
@ -482,6 +481,9 @@ enum e_optcode {
|
|||
OPT_LOWPORT,
|
||||
OPT_MAX_CHILDREN,
|
||||
#if WITH_POSIXMQ
|
||||
OPT_POSIXMQ_FLUSH,
|
||||
OPT_POSIXMQ_MAXMSG,
|
||||
OPT_POSIXMQ_MSGSIZE,
|
||||
OPT_POSIXMQ_PRIORITY,
|
||||
#endif
|
||||
#ifdef NLDLY
|
||||
|
@ -552,7 +554,8 @@ enum e_optcode {
|
|||
OPT_O_ASYNC,
|
||||
#endif
|
||||
OPT_O_BINARY, /* Cygwin */
|
||||
OPT_O_CREATE,
|
||||
OPT_O_CLOEXEC,
|
||||
OPT_O_CREAT,
|
||||
#ifdef O_DEFER
|
||||
OPT_O_DEFER,
|
||||
#endif
|
||||
|
@ -660,8 +663,10 @@ enum e_optcode {
|
|||
OPT_SETPGID,
|
||||
OPT_SETSID,
|
||||
OPT_SETSOCKOPT_BIN,
|
||||
OPT_SETSOCKOPT_CONNECTED,
|
||||
OPT_SETSOCKOPT_INT,
|
||||
OPT_SETSOCKOPT_LISTEN,
|
||||
OPT_SETSOCKOPT_SOCKET,
|
||||
OPT_SETSOCKOPT_STRING,
|
||||
OPT_SETUID,
|
||||
OPT_SETUID_EARLY,
|
||||
|
@ -1028,6 +1033,7 @@ extern groups_t _groupbits(mode_t mode);
|
|||
extern int dropopts(struct opt *opts, unsigned int phase);
|
||||
extern int dropopts2(struct opt *opts, unsigned int from, unsigned int to);
|
||||
extern int dumpopts(struct opt *opts);
|
||||
extern void freeopts(struct opt *opts);
|
||||
|
||||
#if HAVE_BASIC_UID_T==1
|
||||
# define retropt_uid(o,c,r) retropt_short(o,c,r)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "xio-openssl.h"
|
||||
|
||||
|
||||
static pid_t socat_kill_pid; /* here we pass the pid to be killed in sighandler */
|
||||
|
||||
static void signal_kill_pid(int dummy) {
|
||||
|
@ -51,6 +52,7 @@ int xioshutdown(xiofile_t *sock, int how) {
|
|||
sock->stream.fd, strerror(errno));
|
||||
}
|
||||
return 0;
|
||||
#if _WITH_SOCKET
|
||||
case XIOSHUT_DOWN:
|
||||
result = Shutdown(sock->stream.fd, how);
|
||||
if (result < 0) {
|
||||
|
@ -70,7 +72,6 @@ int xioshutdown(xiofile_t *sock, int how) {
|
|||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#if _WITH_SOCKET
|
||||
case XIOSHUT_NULL:
|
||||
writenull = '\0'; /* assign something to make gcc happy */
|
||||
/* send an empty packet; only useful on datagram sockets? */
|
||||
|
|
|
@ -50,7 +50,7 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
|||
switch (pipe->dtype & XIODATA_WRITEMASK) {
|
||||
|
||||
case XIOWRITE_STREAM:
|
||||
writt = writefull(pipe->fd, buff, bytes);
|
||||
writt = writefull(pipe->fd, buff, bytes, NULL);
|
||||
if (writt < 0) {
|
||||
_errno = errno;
|
||||
switch (_errno) {
|
||||
|
@ -116,8 +116,10 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
|||
case XIOWRITE_PIPE:
|
||||
if (pipe->para.bipipe.socktype == SOCK_STREAM) {
|
||||
writt = Write(pipe->para.bipipe.fdout, buff, bytes);
|
||||
#if _WITH_SOCKET
|
||||
} else {
|
||||
writt = Send(pipe->para.bipipe.fdout, buff, bytes, 0);
|
||||
#endif /* _WITH_SOCKET */
|
||||
}
|
||||
_errno = errno;
|
||||
if (writt < 0) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue