From 5df0e4a3d9f0ce62ddb28e1e5daa702305791548 Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Fri, 3 Apr 2009 17:17:10 +0200 Subject: [PATCH] version 2.0.0-b3 --- CHANGES | 51 +++++++- EXAMPLES | 2 +- README | 4 +- VERSION | 2 +- doc/socat-addresschain.html | 2 +- doc/socat-multicast.html | 37 +++--- doc/socat-tun.html | 10 +- doc/socat.yo | 105 +++++++++------- mail.sh | 6 +- socat.spec | 2 +- sysincludes.h | 4 +- test.sh | 238 +++++++++++++++++++++++++++--------- utils.c | 4 +- xio-fd.c | 9 +- xio-fd.h | 3 +- xio-listen.c | 19 +-- xio-process.c | 3 +- xio-process.h | 3 +- xio-progcall.c | 6 +- xio-pty.c | 6 +- xio-socket.c | 10 +- xio-socket.h | 3 +- xio-unix.c | 7 +- xio.h | 4 +- xiohelp.c | 2 +- xioopts.c | 6 + xioopts.h | 3 + xioread.c | 6 +- xioshutdown.c | 59 ++++++--- xiosocketpair.c | 4 +- 30 files changed, 435 insertions(+), 185 deletions(-) diff --git a/CHANGES b/CHANGES index 1b33dc8..d77f345 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,19 @@ +####################### V 2.0.0-b3: + +new features: + added inter addresses for execution of external programs or scripts: + EXEC2 and SYSTEM2 are bidirectional, EXEC1 and SYSTEM1 are + unidirectional + + option commtype replaces the now obsolete "socketpair" and "pipes" + options and selects the communication mechanism on the left side of + EXEC and SYSTEM addresses + + options leftfd, leftinfd, leftoutfd; and rightfd, rightinfd, + rightoutfd override the default file descriptor numbers provided to + exec'd programs + ####################### V 2.0.0-b2: new features: @@ -27,8 +42,42 @@ new features: new form of FD address with output/input fd numbers +####################### V 1.7.1.0: + +new features: + address options shut-none, shut-down, and shut-close allow to control + socat's half close behaviour + + with address option shut-null socat sends an empty packet to the peer + to indicate EOF + + option null-eof changes the behaviour of sockets that receive an empty + packet to see EOF instead of ignoring it + + introduced option names substuser-early and su-e, currently equivalent + to option substuser (thanks to Mike Perry for providing the patch) + corrections: - help displayed some option types wrong + fixed some typos and improved some comments + +####################### V 1.7.0.1: + +corrections: + fixed possible SIGSEGV in listening addresses when a new connection was + reset by peer before the socket addresses could be retrieved. Thanks to + Mike Perry for sending a patch. + + fixed a bug, introduced with version 1.7.0.0, that let client + connections with option connect-timeout fail when the connections + succeeded. Thanks to Bruno De Fraine for reporting this bug. + + option end-close "did not apply" to addresses PTY, SOCKET-CONNECT, + and most UNIX-* and ABSTRACT-* + + half close of EXEC and SYSTEM addresses did not work for pipes and + sometimes socketpair + + help displayed for some option a wrong type under some circumstances shutdown was called multiple times for the same fd diff --git a/EXAMPLES b/EXAMPLES index 0fd34c6..5e72e6e 100644 --- a/EXAMPLES +++ b/EXAMPLES @@ -230,7 +230,7 @@ $ socat -d -d tcp:localhost:25,crlf,nodelay exec:'/usr/sbin/chat -v -s "\"220 \" ////////////////////////////////////////////////////////////////////////////// // IP6 -# socat readline TCP6:::1:21 # if your inetd/ftp is listening on ip6 +# socat readline TCP6:[::1]:21 # if your inetd/ftp is listening on ip6 /////////////////////////////////////////////////////////////////////////////// diff --git a/README b/README index f92849d..ff1577e 100644 --- a/README +++ b/README @@ -50,7 +50,7 @@ following operating systems: Debian lenny/sid on x86, kernel 2.6.24 FreeBSD 6.1 on x86 -NetBSD4.0 on x86 +NetBSD 4.0 on x86 OpenBSD 4.3 on x86 OpenSolaris 10 on x86 with gcc Mac OS X 10.5.5 on iMac G5, with libreadline @@ -75,7 +75,7 @@ install Get the tarball and extract it: gtar xzf socat.tar.gz - cd socat-1.7.0.0 + cd socat-1.7.1.0 ./configure make su diff --git a/VERSION b/VERSION index b5f2dca..8d2ad59 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -"2+exec" +"2.0.0-b3" diff --git a/doc/socat-addresschain.html b/doc/socat-addresschain.html index 8f8b0d5..428daa3 100644 --- a/doc/socat-addresschain.html +++ b/doc/socat-addresschain.html @@ -164,7 +164,7 @@ socat -h |egrep 'openssl-server'

Dual inter addresses

In socat version 1 it was already possible to combine two unidirectional - addresses to one bidrectional address. This idea has been extended in version + addresses to one bidirectional address. This idea has been extended in version 2: Two unidirectional inter addresses can be combined to one bidirectional transfer unit.

diff --git a/doc/socat-multicast.html b/doc/socat-multicast.html index 829eba3..a4caedd 100644 --- a/doc/socat-multicast.html +++ b/doc/socat-multicast.html @@ -1,4 +1,4 @@ - + IP Multicasting with Socat @@ -41,8 +41,8 @@ requirements. All the following examples work bidirectionally except when otherwise noticed. For "clients" we just use STDIO, and for "servers" we use EXEC:hostname which ingores its input but shows us which host the reply comes from. Replace these -addresses with what is appropriate for you (e.g. shell script -invokations). Port 6666 can be replaced with any other port (but for ports < +socat addresses with what is appropriate for your needs (e.g. shell script +invocations). Port 6666 can be replaced with any other port (but for ports < 1024 root privilege might be required).

@@ -85,7 +85,7 @@ direction the first data is passed. A packet from the network is accepted by the IP stack for our socket if:

@@ -226,9 +226,10 @@ Set a multicast/broadcast route with the following command:

route add -net 224.0.0.0/3 gw 192.168.10.2 +

ALL-SYSTEMS multicast address

-224.0.0.1 is the all-systems multicast address: all +224.0.0.1 is the all-systems multicast address: all datagram sockets appear to be automatically member of this group on all interfaces. This membership cannot be dropped on Linux.

@@ -237,10 +238,14 @@ interfaces. This membership cannot be dropped on Linux.

(In)Security

When you use the above examples you should understand that all datagram -sockets without exception accept packets that are directly addressed to them; +sockets without exception accept all packets that are directly addressed to +them; the multi- and broadcast receiving features are just extensions to the normal -functionality. socat has no way to find out if an incoming packet is addressed -to a unicast, multicast, or broadcast address.

+functionality. socat currently has no means to handle incoming packets +differently when it is addressed to a unicast, multicast, or broadcast +address. However, for EXEC'd scripts socat can provide this info in environment +variables. +

Authentication or encryption are not available.

@@ -296,13 +301,13 @@ Please note that the new features could not be successfully tested on IPv6; these sections thus apply to IPv4 only.

-

This document was last modified in March 2007.

+

This document was last modified in April 2009.

More info about socat datagrams

Links regarding this tutorial

-address udp4-datagram
-address udp4-recvfrom
+address UDP4-DATAGRAM
+address UDP4-RECVFROM
option range
option broadcast
option ip-add-membership
@@ -310,11 +315,11 @@ these sections thus apply to IPv4 only. option bind

Other datagram addresses

-address udp4-recv: pure datagram receiver
-address udp4-sendto: communicate +address UDP4-RECV: pure datagram receiver
+address UDP4-SENDTO: communicate with one peer address
-address udp4-listen: pseudo stream server
-address udp4-connect: pseudo stream client
+address UDP4-LISTEN: pseudo stream server
+address UDP4-CONNECT: pseudo stream client

Related socat option groups

IP options
@@ -331,7 +336,7 @@ with one peer address
broadcasting on Wikipedia

-Copyright: Gerhard Rieger 2007
+Copyright: Gerhard Rieger 2007-2009
License: GNU Free Documentation License (FDL)

diff --git a/doc/socat-tun.html b/doc/socat-tun.html index 0df6bca..28c302b 100644 --- a/doc/socat-tun.html +++ b/doc/socat-tun.html @@ -1,4 +1,4 @@ - + Building TUN based virtual networks with socat @@ -16,7 +16,7 @@ these devices are called TUN or TAP.

socat provides an address type that creates a TUN device on Linux; the other -socat address can be any type; it transfer the "wire" data as desired. +socat address can be any type; it transfers the "wire" data as desired.

This document shows how a simple virtual network can be created between @@ -31,7 +31,7 @@ following commands with the requirements of your situation:

- +
hostaddressmask
physical "server" address1.2.3.4n/a
physical "client" address223.2.3.4n/a
physical "client" addressn/an/a
TUN on "server"192.168.255.1255.255.255.0
TUN on "client"192.168.255.2255.255.255.0
@@ -140,7 +140,7 @@ transfer.

Linux TUN/TAP support was added to socat in version 1.6.0.

-

This document was last modified in March 2007.

+

This document was last modified in April 2009.

More info about socat TUN/TAP support

@@ -157,7 +157,7 @@ Linux TUN/TAP support was added to socat in version 1.6.0.

TUN/TAP on Wikipedia

-Copyright: Gerhard Rieger 2007
+Copyright: Gerhard Rieger 2007-2009
License: GNU Free Documentation License (FDL)

diff --git a/doc/socat.yo b/doc/socat.yo index 9e2dc24..dc83081 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -389,13 +389,13 @@ label(ADDRESS_IP_SENDTO)dit(bf(tt(IP-SENDTO::))) Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6) nl() Useful options: link(pf)(OPTION_PROTOCOL_FAMILY), - link(ttl)(OPTION_TTL) + link(ttl)(OPTION_TTL) nl() See also: link(IP4-SENDTO)(ADDRESS_IP4_SENDTO), link(IP6-SENDTO)(ADDRESS_IP6_SENDTO), link(IP-RECVFROM)(ADDRESS_IP_RECVFROM), link(IP-RECV)(ADDRESS_IP_RECV), - link(UDP-SENDTO)(ADDRESS_UDP_SENDTO) + link(UDP-SENDTO)(ADDRESS_UDP_SENDTO), link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO) label(ADDRESS_INTERFACE)dit(bf(tt(INTERFACE:))) Communicates with a network connected on an interface using raw packets @@ -403,7 +403,7 @@ label(ADDRESS_INTERFACE)dit(bf(tt(INTERFACE:))) the network interface. Currently only available on Linux. Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET) nl() Useful options: - link(pf)(OPTION_PROTOCOL_FAMILY)nl() + link(pf)(OPTION_PROTOCOL_FAMILY), link(type)(OPTION_SO_TYPE)nl() See also: link(ip-recv)(ADDRESS_IP_RECV) label(ADDRESS_IP4_SENDTO)dit(bf(tt(IP4-SENDTO::))) @@ -417,7 +417,7 @@ label(ADDRESS_IP_DATAGRAM)dit(bf(tt(IP-DATAGRAM:
:))) Sends outgoing data to the specified address which may in particular be a broadcast or multicast address. Packets arriving on the local socket are checked if their source addresses match - eventual link(RANGE)(OPTION_RANGE) or link(TCPWRAP)(OPTION_TCPWRAPPERS) + link(RANGE)(OPTION_RANGE) or link(TCPWRAP)(OPTION_TCPWRAPPERS) options. This address type can for example be used for implementing symmetric or asymmetric broadcast or multicast communications.nl() Option groups: link(FD)(GROUP_FD), link(SOCKET)(GROUP_SOCKET), @@ -444,19 +444,21 @@ label(ADDRESS_IP_DATAGRAM)dit(bf(tt(IP-DATAGRAM:
:))) label(ADDRESS_IP4_DATAGRAM)dit(bf(tt(IP4-DATAGRAM::))) Like link(IP-DATAGRAM)(ADDRESS_IP_DATAGRAM), but always uses IPv4. (link(example)(EXAMPLE_ADDRESS_IP4_BROADCAST_CLIENT))nl() - Option groups: link(FD)(GROUP_FD), link(SOCKET)(GROUP_SOCKET), - link(IP4)(GROUP_IP4), link(RANGE)(GROUP_RANGE) nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(RANGE)(GROUP_RANGE) nl() label(ADDRESS_IP6_DATAGRAM)dit(bf(tt(IP6-DATAGRAM::))) Like link(IP-DATAGRAM)(ADDRESS_IP_DATAGRAM), but always uses IPv6. Please note that IPv6 does not know broadcasts.nl() - Option groups: link(FD)(GROUP_FD), link(SOCKET)(GROUP_SOCKET), - link(IP6)(GROUP_IP6), link(RANGE)(GROUP_RANGE) nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6),link(RANGE)(GROUP_RANGE) nl() label(ADDRESS_IP_RECVFROM)dit(bf(tt(IP-RECVFROM:))) Opens a raw IP socket of link()(TYPE_PROTOCOL). Depending on option link(pf)(OPTION_PROTOCOL_FAMILY), IP procotol version 4 or 6 is used. It receives one packet from an unspecified peer and may send one or more answer packets to that peer. This mode is particularly useful with fork option where each arriving packet - from arbitrary peers - is handled by its own sub process. - This allows a behaviour similar to typical UDP based servers like ntpd or named. + This allows a behaviour similar to typical UDP based servers like ntpd or + named.nl() + Please note that the reply packets might be fetched as incoming traffic when + sender and receiver IP address are identical because there is no port number + to distinguish the sockets.nl() This address works well with IP-SENDTO address peers (see above). Protocol 255 uses the raw socket with the IP header being part of the data.nl() @@ -544,6 +546,7 @@ label(ADDRESS_OPENSSL_CONNECT)dit(bf(tt(OPENSSL::))) link(cafile)(OPTION_OPENSSL_CAFILE), link(capath)(OPTION_OPENSSL_CAPATH), link(certificate)(OPTION_OPENSSL_CERTIFICATE), + link(key)(OPTION_OPENSSL_KEY), link(bind)(OPTION_BIND), link(pf)(OPTION_PROTOCOL_FAMILY), link(connect-timeout)(OPTION_CONNECT_TIMEOUT), @@ -570,6 +573,7 @@ label(ADDRESS_OPENSSL_LISTEN)dit(bf(tt(OPENSSL-LISTEN:))) link(cafile)(OPTION_OPENSSL_CAFILE), link(capath)(OPTION_OPENSSL_CAPATH), link(certificate)(OPTION_OPENSSL_CERTIFICATE), + link(key)(OPTION_OPENSSL_KEY), link(fork)(OPTION_FORK), link(bind)(OPTION_BIND), link(range)(OPTION_RANGE), @@ -1059,7 +1063,7 @@ label(ADDRESS_UDP_DATAGRAM)dit(bf(tt(UDP-DATAGRAM:
:))) Sends outgoing data to the specified address which may in particular be a broadcast or multicast address. Packets arriving on the local socket are checked for the correct remote port and if their source addresses match - eventual link(RANGE)(OPTION_RANGE) or link(TCPWRAP)(OPTION_TCPWRAPPERS) + link(RANGE)(OPTION_RANGE) or link(TCPWRAP)(OPTION_TCPWRAPPERS) options. This address type can for example be used for implementing symmetric or asymmetric broadcast or multicast communications.nl() Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(RANGE)(GROUP_RANGE) nl() @@ -1089,13 +1093,11 @@ label(ADDRESS_UDP4_DATAGRAM)dit(bf(tt(UDP4-DATAGRAM:
:))) Like link(UDP-DATAGRAM)(ADDRESS_UDP_DATAGRAM), but only supports IPv4 protocol (link(example1)(EXAMPLE_ADDRESS_UDP4_BROADCAST_CLIENT), link(example2)(EXAMPLE_ADDRESS_UDP4_MULTICAST)).nl() - Option groups: link(FD)(GROUP_FD), link(SOCKET)(GROUP_SOCKET), - link(IP4)(GROUP_IP4), link(RANGE)(GROUP_RANGE) + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4), link(RANGE)(GROUP_RANGE) label(ADDRESS_UDP6_DATAGRAM)dit(bf(tt(UDP6-DATAGRAM:
:))) Like link(UDP-DATAGRAM)(ADDRESS_UDP_DATAGRAM), but only supports IPv6 protocol.nl() - Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET), - link(IP6)(GROUP_IP6),link(RANGE)(GROUP_RANGE) + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6),link(RANGE)(GROUP_RANGE) label(ADDRESS_UDP_LISTEN)dit(bf(tt(UDP-LISTEN:))) Waits for a UDP/IP packet arriving on [link(UDP service)(TYPE_UDP_SERVICE)] and `connects' back to sender. @@ -1167,7 +1169,7 @@ label(ADDRESS_UDP_RECVFROM)dit(bf(tt(UDP-RECVFROM:))) option where each arriving packet - from arbitrary peers - is handled by its own sub process. This allows a behaviour similar to typical UDP based servers like ntpd - or named. This address works well with socat() SENDTO address peers.nl() + or named. This address works well with socat() UDP-SENDTO address peers.nl() Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE) nl() Useful options: link(fork)(OPTION_FORK), @@ -1228,9 +1230,7 @@ label(ADDRESS_UNIX_CONNECT)dit(bf(tt(UNIX-CONNECT:))) if is not a unixdomain() socket, this is an error; if is a unixdomain() socket, but no process is listening, this is an error.nl() - Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET), - link(NAMED)(GROUP_NAMED),link(RETRY)(GROUP_RETRY), - link(UNIX)(GROUP_SOCK_UNIX) nl()) + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(NAMED)(GROUP_NAMED),link(RETRY)(GROUP_RETRY),link(UNIX)(GROUP_SOCK_UNIX) nl()) Useful options: link(bind)(OPTION_BIND)nl() See also: @@ -1247,10 +1247,7 @@ label(ADDRESS_UNIX_LISTEN)dit(bf(tt(UNIX-LISTEN:))) Note that opening this address usually blocks until a client connects. Beginning with socat() version 1.4.3, the file system entry is removed when this address is closed (but see option link(unlink-close)(OPTION_UNLINK_CLOSE)) (link(example)(EXAMPLE_ADDRESS_UNIX_LISTEN)).nl() - Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET), - link(NAMED)(GROUP_NAMED),link(LISTEN)(GROUP_LISTEN), - link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY), - link(UNIX)(GROUP_SOCK_UNIX) nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(NAMED)(GROUP_NAMED),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY),link(UNIX)(GROUP_SOCK_UNIX) nl() Useful options: link(fork)(OPTION_FORK), link(umask)(OPTION_UMASK), @@ -1267,7 +1264,11 @@ label(ADDRESS_UNIX_LISTEN)dit(bf(tt(UNIX-LISTEN:))) label(ADDRESS_UNIX_SENDTO)dit(bf(tt(UNIX-SENDTO:))) Communicates with the specified peer socket, defined by [link()(TYPE_FILENAME)] assuming it is a unixdomain() datagram socket. It sends packets to and receives packets from that peer socket only. - It works well with socat() UNIX-RECVFROM and UNIX-RECV address peers.nl() + Please note that it might be neccessary to link(bind)(OPTION_BIND) the + local socket to an address (e.g. tt(/tmp/sock1), which must not exist + before). + This address type works well with socat() UNIX-RECVFROM and UNIX-RECV address + peers.nl() Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET), link(NAMED)(GROUP_NAMED),link(UNIX)(GROUP_SOCK_UNIX)nl() Useful options: @@ -1301,8 +1302,7 @@ label(ADDRESS_UNIX_RECV)dit(bf(tt(UNIX-RECV:))) Receives packets from multiple unspecified peers and merges the data. No replies are possible. It can be, e.g., addressed by socat() UNIX-SENDTO address peers. It behaves similar to a syslog server. - Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET), - link(NAMED)(GROUP_NAMED),link(UNIX)(GROUP_SOCK_UNIX) nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(NAMED)(GROUP_NAMED),link(UNIX)(GROUP_SOCK_UNIX) nl() See also: link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO), link(UNIX-RECVFROM)(ADDRESS_UNIX_RECVFROM), @@ -1315,8 +1315,7 @@ label(ADDRESS_UNIX_CLIENT)dit(bf(tt(UNIX-CLIENT:))) [link()(TYPE_FILENAME)] assuming it is a unixdomain() socket. It first tries to connect and, if that fails, assumes it is a datagram socket, thus supporting both types.nl() - Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET), - link(NAMED)(GROUP_NAMED),link(UNIX)(GROUP_SOCK_UNIX) nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(NAMED)(GROUP_NAMED),link(UNIX)(GROUP_SOCK_UNIX) nl() Useful options: link(bind)(OPTION_BIND)nl() See also: @@ -1544,6 +1543,25 @@ label(OPTION_END_CLOSE)dit(bf(tt(end-close))) Similarly, when an address of type EXEC or SYSTEM is ended, socat() usually will explicitely kill the sub process. With this option, it will just close the file descriptors. +label(OPTION_SHUT_NONE)dit(bf(tt(shut-none))) + Changes the (address dependent) method of shutting down the write part of a + connection to not do anything. +label(OPTION_SHUT_DOWN)dit(bf(tt(shut-down))) + Changes the (address dependent) method of shutting down the write part of a + connection to tt(shutdown\(fd, SHUT_WR)). Is only useful with sockets. +label(OPTION_SHUT_CLOSE)dit(bf(tt(shut-close))) + Changes the (address dependent) method of shutting down the write part of a + connection to tt(close\(fd)). +label(OPTION_SHUT_NULL)dit(bf(tt(shut-null))) + When one address indicates EOF, socat() will send a zero sized packet to the + write channel of the other address to transfer the EOF condition. This is + useful with UDP and other datagram protocols. Has been tested against + netcat and socat with option link(null-eof)(OPTION_NULL_EOF). +label(OPTION_NULL_EOF)dit(bf(tt(null-eof))) + Normally socat() will ignore empty (zero size payload) packets arriving on + datagram sockets, so it survives port scans. With this option socat() + interprets empty datagram packets as EOF indicator (see + link(shut-null)(OPTION_SHUT_NULL). label(OPTION_IOCTL_VOID)dit(bf(tt(ioctl-void=))) Calls tt(ioctl()) with the request value as second argument and NULL as third argument. This option allows to utilize ioctls that are not @@ -1673,21 +1691,24 @@ startdit() label(OPTION_SEEK)dit(bf(tt(seek=))) Applies the code(lseek(fd, , SEEK_SET)) (or code(lseek64)) system call, thus positioning the file pointer absolutely to - [link(off_t)(TYPE_OFF) or link(off64_t)(TYPE_OFF64)]. + [link(off_t)(TYPE_OFF) or link(off64_t)(TYPE_OFF64)]. Please note that a + missing value defaults to 1, not 0. label(OPTION_SEEK_CUR)dit(bf(tt(seek-cur=))) Applies the code(lseek(fd, , SEEK_CUR)) (or code(lseek64)) system call, thus positioning the file pointer [link(off_t)(TYPE_OFF) or link(off64_t)(TYPE_OFF64)] bytes relatively to its current position (which - is usually 0). + is usually 0). Please note that a missing value defaults to 1, not 0. label(OPTION_SEEK_END)dit(bf(tt(seek-end=))) Applies the code(lseek(fd, , SEEK_END)) (or code(lseek64)) system call, thus positioning the file pointer [link(off_t)(TYPE_OFF) or - link(off64_t)(TYPE_OFF64)] bytes relatively to the files current end. + link(off64_t)(TYPE_OFF64)] bytes relatively to the files current end. Please + note that a missing value defaults to 1, not 0. label(OPTION_FTRUNCATE)dit(bf(tt(ftruncate=))) Applies the code(ftruncate(fd, )) (or code(ftruncate64) if available) system call, thus truncating the file at the position [link(off_t)(TYPE_OFF) or - link(off64_t)(TYPE_OFF64)]. + link(off64_t)(TYPE_OFF64)]. Please note that a missing value defaults to 1, + not 0. label(OPTION_EXT2_SECRM_FL)dit(bf(tt(secrm=))) label(OPTION_EXT2_UNRM)dit(bf(tt(unrm=))) @@ -1726,16 +1747,18 @@ label(OPTION_CHROOT_EARLY)dit(bf(tt(chroot-early=))) before opening the address. This call might require root privilege. label(OPTION_SETGID)dit(bf(tt(setgid=))) Changes the primary link()(TYPE_GROUP) of the process after - processing the address. This call might require root privilege. + 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=))) - Changes the primary link()(TYPE_GROUP) of the process before opening - the address. This call might require root privilege. + Like link(setgit)(OPTION_SETGID) but is performed before opening the address. label(OPTION_SETUID)dit(bf(tt(setuid=))) Changes the link()(TYPE_USER) (owner) of the process after processing - the address. This call might require root privilege. + the address. This call might require root privilege. Please note that this + option does not drop group related privileges. Check if option + link(su)(OPTION_SUBSTUSER) better fits your needs. label(OPTION_SETUID_EARLY)dit(bf(tt(setuid-early=))) - Changes the link()(TYPE_USER) (owner) of the process before opening - the address. This call might require root privilege. + Like link(setuid)(OPTION_SETUID) but is performed before opening the + address. label(OPTION_SUBSTUSER)dit(bf(tt(su=))) Changes the link()(TYPE_USER) (owner) and groups of the process after processing the address (link(example)(EXAMPLE_OPTION_SUBSTUSER)). This call might require root privilege. @@ -1831,11 +1854,11 @@ label(OPTION_BIND)dit(bf(tt(bind=))) Binds the socket to the given socket address using the code(bind()) system call. The form of is socket domain dependent: IP4 and IP6 allow the form [hostname|hostaddress][:(service|port)] (link(example)(EXAMPLE_OPTION_BIND_TCP4)), - unixdomain() sockets require link()(TYPE_FILENAME). + unixdomain() sockets require link()(TYPE_FILENAME). label(OPTION_CONNECT_TIMEOUT)dit(bf(tt(connect-timeout=))) Abort the connection attempt after [link(timeval)(TYPE_TIMEVAL)] with error status. -label(OPTION_INTERFACE)dit(bf(tt(interface=))) +label(OPTION_SO_BINDTODEV)dit(bf(tt(so-bindtodev=))) Binds the socket to the given link()(TYPE_INTERFACE). This option might require root privilege. label(OPTION_SO_BROADCAST)dit(bf(tt(broadcast))) @@ -2420,7 +2443,7 @@ label(OPTION_FDOUT)dit(bf(tt(fdout=))) instead of stdout (1). The program started from the subprocess has to use this fd for writing data to socat() (link(example)(EXAMPLE_OPTION_FDOUT)). label(OPTION_SIGHUP)label(OPTION_SIGINT)label(OPTION_SIGQUIT)dit(bf(tt(sighup)), bf(tt(sigint)), bf(tt(sigquit))) - Has socat() pass an eventual signal of this type to the sub process. + Has socat() pass signals of this type to the sub process. If no address has this option, socat() terminates on these signals. enddit() @@ -3327,7 +3350,7 @@ servers), and the original client request. label(EXAMPLE_ANCILLARY) dit(bf(tt(socat -d -d -%UDP4-RECVFROM:9999,so-broadcast,so-timestamp,ip-pktinfo,ip-recverr,ip-recvopts,ip-recvtos,ip-recvttl SYSTEM:'export; sleep 1' |grep SOCAT))) -waits for incoming UDP packets on port 9999 and prints the environment +waits for an incoming UDP packet on port 9999 and prints the environment variables provided by socat. On BSD based systems you have to replace link(tt(ip-pktinfo))(OPTION_IP_PKTINFO) with link(tt(ip-recvdstaddr))(OPTION_IP_RECVDSTADDR),link(tt(ip-recvif))(OPTION_IP_RECVIF). Especially interesting is SOCAT_IP_DSTADDR: it contains the target address of the packet which may be a diff --git a/mail.sh b/mail.sh index 115b1eb..7bc2c5e 100755 --- a/mail.sh +++ b/mail.sh @@ -1,6 +1,6 @@ #! /bin/sh # source: mail.sh -# Copyright Gerhard Rieger 2001-2005 +# Copyright Gerhard Rieger 2001-2009 # Published under the GNU General Public License V.2, see file COPYING #set -vx @@ -8,7 +8,9 @@ # This is an example for a shell script that can be fed to socat with exec. # Its clue is that it does not use stdin/stdout for communication with socat, # so you may feed the mail message via stdin to the script. The message should -# contain appropriate mail headers. +# contain appropriate mail headers without continuation lines. +# socat establishes the connection to the SMTP server; the script performs the +# SMTP dialog and afterwards transfers the message body to the server. # Lines with only a dot are not permitted - use two dots as escape. # This script supports multiline answers from server, but not much more yet. diff --git a/socat.spec b/socat.spec index 370c246..ec7c0ae 100644 --- a/socat.spec +++ b/socat.spec @@ -1,6 +1,6 @@ %define majorver 1.7 -%define minorver 0.0 +%define minorver 1.0 Summary: socat - multipurpose relay Name: socat diff --git a/sysincludes.h b/sysincludes.h index 6806049..ee25556 100644 --- a/sysincludes.h +++ b/sysincludes.h @@ -1,5 +1,5 @@ /* source: sysincludes.h */ -/* Copyright Gerhard Rieger 2001-2008 */ +/* Copyright Gerhard Rieger 2001-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __sysincludes_h_included @@ -36,7 +36,7 @@ #if HAVE_GRP_H #include /* getgrnam() */ #endif -#if HAVE_PTY_H && _WITH_TERMIOS +#if HAVE_PTY_H && (_WITH_TERMIOS || HAVE_OPENPTY) #include #endif #if HAVE_SYS_PARAM_H diff --git a/test.sh b/test.sh index 4e11aa0..d1fbb83 100755 --- a/test.sh +++ b/test.sh @@ -2108,7 +2108,7 @@ waitfile () { # generate a test certificate and key gentestcert () { local name="$1" - if [ -f $name.key -a -f $name.crt -a -f $name.pem ]; then return; fi + if [ -s $name.key -a -s $name.crt -a -s $name.pem ]; then return; fi openssl genrsa $OPENSSL_RAND -out $name.key 768 >/dev/null 2>&1 openssl req -new -config testcert.conf -key $name.key -x509 -days 3653 -out $name.crt >/dev/null 2>&1 cat $name.key $name.crt >$name.pem @@ -2118,9 +2118,7 @@ gentestcert () { gentestdsacert () { #set -vx local name="$1" - if [ -f $name.key -a -f $name.crt -a -f $name.pem ]; then - return; - fi + if [ -s $name.key -a -s $name.crt -a -s $name.pem ]; then return; fi openssl dsaparam -out $name-dsa.pem 512 >/dev/null 2>&1 openssl dhparam -dsaparam -out $name-dh.pem 512 >/dev/null 2>&1 openssl req -newkey dsa:$name-dsa.pem -keyout $name.key -nodes -x509 -days 3653 -config testcert.conf -out $name.crt >/dev/null 2>&1 @@ -2299,14 +2297,13 @@ esac N=$((N+1)) -## LATER: -#NAME=SYSTEMPIPESFLUSH -#case "$TESTS" in -#*%functions%*|*%system%*|*%$NAME%*) -#TEST="$NAME: call to od via system() with pipes" -#testod "$N" "$TEST" "" "system:$OD_C,pipes" "$opts" -#esac -#N=$((N+1)) +NAME=SYSTEMPIPESFLUSH +case "$TESTS" in +*%functions%*|*%system%*|*%$NAME%*) +TEST="$NAME: call to od via system() with pipes" +testod "$N" "$TEST" "" "system:$OD_C,pipes" "$opts" "$val_t" +esac +N=$((N+1)) ## LATER: @@ -2339,24 +2336,22 @@ N=$((N+1)) #N=$((N+1)) -## LATER: -#NAME=SYSTEMPIPESFDSFLUSH -#case "$TESTS" in -#*%functions%*|*%system%*|*%$NAME%*) -#TEST="$NAME: call to od via system() with pipes, non stdio" -#testod "$N" "$TEST" "" "system:$OD_C>&9 <&8,pipes,fdin=8,fdout=9" "$opts" -#esac -#N=$((N+1)) +NAME=SYSTEMPIPESFDSFLUSH +case "$TESTS" in +*%functions%*|*%system%*|*%$NAME%*) +TEST="$NAME: call to od via system() with pipes, non stdio" +testod "$N" "$TEST" "" "system:$OD_C>&9 <&8,pipes,fdin=8,fdout=9" "$opts" "$val_t" +esac +N=$((N+1)) -## LATER: -#NAME=DUALSYSTEMFDSFLUSH -#case "$TESTS" in -#*%functions%*|*%system%*|*%$NAME%*) -#TEST="$NAME: call to od via dual system()" -#testecho "$N" "$TEST" "system:$CAT<&7,fdin=7%system:$OD_C>&6,fdout=6" "" "$opts" -#esac -#N=$((N+1)) +NAME=DUALSYSTEMFDSFLUSH +case "$TESTS" in +*%functions%*|*%system%*|*%$NAME%*) +TEST="$NAME: call to od via dual system()" +testod "$N" "$TEST" "system:$CAT<&7,fdin=7%system:$OD_C>&6,fdout=6" "pipe" "$opts" "$val_t" +esac +N=$((N+1)) case "$UNAME" in @@ -4717,7 +4712,7 @@ case "$TESTS" in TEST="$NAME: readline with password and sigint" if ! eval $NUMCOND; then :; elif ! feat=$(testaddrs readline pty); then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else SAVETERM="$TERM"; TERM= # 'cause konsole might print controls even in raw @@ -4861,7 +4856,7 @@ case "$TESTS" in TEST="$NAME: gender changer via SSL through HTTP proxy, oneshot" if ! eval $NUMCOND; then :; elif ! feat=$(testaddrs openssl proxy); then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat |tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat" |tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else gentestcert testsrv @@ -4948,7 +4943,7 @@ case "$TESTS" in TEST="$NAME: gender changer via SSL through HTTP proxy, daemons" if ! eval $NUMCOND; then :; elif ! feat=$(testaddrs openssl proxy); then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else gentestcert testsrv @@ -5823,10 +5818,10 @@ case "$TESTS" in TEST="$NAME: test if master pty ($PTYTYPE) waits for slave connection" if ! eval $NUMCOND; then :; else if ! feat=$(testaddrs pty); then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testoptions "$PTYTYPE" pty-wait-slave); then - $PRINTF "test $F_n $TEST... ${YELLOW}option $(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}option $(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testptywaitslave "$N" "$TEST" "$PTYTYPE" "$opts" @@ -5842,10 +5837,10 @@ case "$TESTS" in TEST="$NAME: test if master pty ($PTYTYPE) waits for slave connection" if ! eval $NUMCOND; then :; elif ! feat=$(testaddrs pty); then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testoptions "$PTYTYPE" pty-wait-slave); then - $PRINTF "test $F_n $TEST... ${YELLOW}option $(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}option $(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else testptywaitslave "$N" "$TEST" "$PTYTYPE" "$opts" @@ -5856,14 +5851,14 @@ N=$((N+1)) NAME=CONNECTTIMEOUT case "$TESTS" in -*%functions%*|*%$NAME%*) +*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%timeout%*|*%$NAME%*) TEST="$NAME: test the connect-timeout option" if ! eval $NUMCOND; then :; elif ! feat=$(testaddrs tcp); then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) elif ! feat=$(testoptions connect-timeout); then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else # we need a hanging connection attempt, guess an address for this @@ -5907,6 +5902,53 @@ esac N=$((N+1)) +# version 1.7.0.0 had a bug with the connect-timeout option: while it correctly +# terminated a hanging connect attempt, it prevented a successful connection +# establishment from being recognized by socat, instead the timeout occurred +NAME=CONNECTTIMEOUT_CONN +if ! eval $NUMCOND; then :; else +case "$TESTS" in +*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%timeout%*|*%$NAME%*) +TEST="$NAME: TCP4 connect-timeout option when server replies" +# just try a connection that is expected to succeed with the usual data +# transfer; with the bug it will fail +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +tsl=$PORT +ts="127.0.0.1:$tsl" +da="test$N $(date) $RANDOM" +CMD1="$SOCAT $opts TCP4-LISTEN:$tsl,reuseaddr PIPE" +CMD2="$SOCAT $opts STDIO TCP4:$ts,connect-timeout=1" +printf "test $F_n $TEST... " $N +$CMD1 >"$tf" 2>"${te}1" & +pid1=$! +waittcp4port $tsl 1 +echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" +if [ $? -ne 0 ]; then + $PRINTF "$FAILED: $SOCAT:\n" + echo "$CMD1 &" + cat "${te}1" + echo "$CMD2" + cat "${te}2" + numFAIL=$((numFAIL+1)) +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + cat "$tdiff" + numFAIL=$((numFAIL+1)) +else + $PRINTF "$OK\n" + if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi + numOK=$((numOK+1)) +fi +kill $pid1 2>/dev/null +wait ;; +esac +PORT=$((PORT+1)) +fi # NUMCOND +N=$((N+1)) + + NAME=OPENSSLLISTENDSA case "$TESTS" in *%functions%*|*%chain%*|*%openssl%*|*%tcp%*|*%$NAME%*) @@ -5957,7 +5999,7 @@ N=$((N+1)) signum () { if [ ! "$BASH_VERSION" -o -o posix ]; then # we expect: - for i in $(POSIXLY_CORRECT=1 kill -l); do echo $i; done |grep -n -i "^$1$" |cut -d: -f1 + for i in $(POSIXLY_CORRECT=1 kill -l); do echo "$i"; done |grep -n -i "^$1$" |cut -d: -f1 else # expect: # " 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL" @@ -5977,7 +6019,7 @@ case "$TESTS" in TEST="$NAME: exit status when dying on SIG$signam" if ! eval $NUMCOND; then :; elif ! feat=$(testaddrs pty); then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat |tr a-z A-Z) not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat" |tr a-z A-Z) not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else SIG="$(signum $signam)" @@ -6021,7 +6063,7 @@ case "$TESTS" in TEST="$NAME: restrict reading from file with bytes option" if ! eval $NUMCOND; then :; elif false; then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else tr="$td/test$N.ref" @@ -7672,6 +7714,89 @@ esac N=$((N+1)) +# up to 1.7.0.0 option end-close led to an error with some address types due to +# bad internal handling. here we check it for address PTY +NAME=PTYENDCLOSE +case "$TESTS" in +*%functions%*|*%bugs%*|*%pty%*|*%$NAME%*) +TEST="$NAME: PTY handles option end-close" +# with the bug, socat exits with error. we invoke socat in a no-op mode and +# check its return status. +if ! eval $NUMCOND; then :; + else +tf="$td/test$N.stout" +te="$td/test$N.stderr" +CMD="$SOCAT $opts /dev/null pty,end-close" +printf "test $F_n $TEST... " $N +$CMD 2>"${te}" +rc=$? +if [ "$rc" = 0 ]; then + $PRINTF "$OK\n" + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + echo "$CMD" + cat "${te}" + numFAIL=$((numFAIL+1)) +fi +fi # NUMCOND + ;; +esac +N=$((N+1)) + + +# test the shut-null and null-eof options +NAME=SHUTNULLEOF +case "$TESTS" in +*%functions%*|*%socket%*|*%$NAME%*) +TEST="$NAME: options shut-null and null-eof" +# run a receiving background process with option null-eof. +# start a sending process with option shut-null that sends a test record to the +# receiving process and then terminates. +# send another test record. +# whe the receiving process just got the first test record the test succeeded +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts -u UDP-RECV:$PORT,null-eof CREAT:$tf" +CMD1="$SOCAT $opts -u - UDP-SENDTO:127.0.0.1:$PORT,shut-null" +printf "test $F_n $TEST... " $N +$CMD0 >/dev/null 2>"${te}0" & +pid0=$! +waitudp4port $PORT 1 +echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" +rc1=$? +echo "xyz" |$CMD1 >"${tf}2" 2>"${te}2" +rc2=$? +kill $pid0 2>/dev/null; wait +if [ $rc1 != 0 -o $rc2 != 0 ]; then + $PRINTF "$FAILED\n" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" + cat "${te}1" + cat "${te}2" + numFAIL=$((numFAIL+1)) +elif echo "$da" |diff - "${tf}" >"$tdiff"; then + $PRINTF "$OK\n" + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" + cat "${te}1" + cat "${tdiff}" + numFAIL=$((numFAIL+1)) +fi +fi # NUMCOND + ;; +esac +N=$((N+1)) + + NAME=UDP6LISTENBIND # this tests for a bug in (up to) 1.5.0.0: # with udp*-listen, the bind option supported only IPv4 @@ -8016,7 +8141,8 @@ waitip4proto $ts1p 1 usleep $((10*MICROS)) echo "$da" |$CMD2 2>>"${te}2" rc2="$?" -usleep $((10*MICROS)) +#usleep $MICROS +sleep 1 kill "$pid1" 2>/dev/null; wait; if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $SOCAT:\n" @@ -8467,7 +8593,7 @@ TEST="$NAME: socat handles data buffered by openssl" # transferred, the test has failed. if ! eval $NUMCOND; then :; elif ! feat=$(testaddrs openssl) >/dev/null; then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else tf="$td/test$N.out" @@ -8519,7 +8645,7 @@ TEST="$NAME: trigger EOF after that many bytes, even when socket idle" # the process did not terminate and the bug is still there. if ! eval $NUMCOND; then :; elif false; then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else tr="$td/test$N.ref" @@ -9106,8 +9232,8 @@ while read PF KEYW ADDR IPPORT SCM_ENABLE SCM_RECV SCM_TYPE SCM_NAME ROOT SCM_VA do if [ -z "$PF" ] || [[ "$PF" == \#* ]]; then continue; fi # -pf="$(echo $PF |tr A-Z a-z)" -proto="$(echo $KEYW |tr A-Z a-z)" +pf="$(echo "$PF" |tr A-Z a-z)" +proto="$(echo "$KEYW" |tr A-Z a-z)" NAME=${KEYW}SCM_$SCM_TYPE case "$TESTS" in *%functions%*|*%$pf%*|*%dgram%*|*%udp%*|*%$proto%*|*%recv%*|*%ancillary%*|*%$ROOT%*|*%$NAME%*) @@ -9227,7 +9353,7 @@ IP6 IP6 [::1] PROTO ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS while read KEYW FEAT TEST_SOCKADDR TEST_PEERADDR TEST_SOCKPORT TEST_PEERPORT; do if [ -z "$KEYW" ] || [[ "$KEYW" == \#* ]]; then continue; fi # -test_proto="$(echo $KEYW |tr A-Z a-z)" +test_proto="$(echo "$KEYW" |tr A-Z a-z)" NAME=${KEYW}LISTENENV case "$TESTS" in *%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$test_proto%*|*%envvar%*|*%$NAME%*) @@ -9238,12 +9364,12 @@ TEST="$NAME: $KEYW-LISTEN fills environment variables with socket addresses" # describing the peer and local sockets. if ! eval $NUMCOND; then :; elif ! feat=$(testaddrs $FEAT); then - $PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat |tr a-z A-Z) not available${NORMAL}\n" $N + $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat" |tr a-z A-Z) not available${NORMAL}\n" $N numCANT=$((numCANT+1)) else tf="$td/test$N.stdout" te="$td/test$N.stderr" -TEST_SOCKADDR="$(echo $TEST_SOCKADDR |sed "s/\$N/$N/g")" # actual vars +TEST_SOCKADDR="$(echo "$TEST_SOCKADDR" |sed "s/\$N/$N/g")" # actual vars tsa="$TEST_SOCKADDR" # test server address tsp="$TEST_SOCKPORT" # test server port if [ "$tsp" != ',' ]; then @@ -9251,7 +9377,7 @@ if [ "$tsp" != ',' ]; then else tsa1="$tsa"; tsa2= # tsa1 used for addr parameter fi -TEST_PEERADDR="$(echo $TEST_PEERADDR |sed "s/\$N/$N/g")" # actual vars +TEST_PEERADDR="$(echo "$TEST_PEERADDR" |sed "s/\$N/$N/g")" # actual vars tca="$TEST_PEERADDR" # test client address tcp="$TEST_PEERPORT" # test client port if [ "$tcp" != ',' ]; then @@ -9297,11 +9423,11 @@ else cat "${te}1" numFAIL=$((numFAIL+1)) fi -set +xv fi # NUMCOND, feats ;; esac N=$((N+1)) +set +xv # done <<<" TCP4 TCP $LOCALHOST $SECONDADDR $PORT $((PORT+1)) @@ -9320,8 +9446,8 @@ while read PF KEYW ADDR IPPORT SCM_ENABLE SCM_RECV SCM_ENVNAME ROOT SCM_VALUE do if [ -z "$PF" ] || [[ "$PF" == \#* ]]; then continue; fi # -pf="$(echo $PF |tr A-Z a-z)" -proto="$(echo $KEYW |tr A-Z a-z)" +pf="$(echo "$PF" |tr A-Z a-z)" +proto="$(echo "$KEYW" |tr A-Z a-z)" NAME=${KEYW}ENV_$SCM_ENVNAME case "$TESTS" in *%functions%*|*%$pf%*|*%dgram%*|*%udp%*|*%$proto%*|*%recv%*|*%ancillary%*|*%envvar%*|*%$ROOT%*|*%$NAME%*) @@ -10032,7 +10158,7 @@ printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1=$! waitsctp4port $tsl 1 -# SCTP does not seem to support half close, so we let it 1s to finish +# SCTP does not seem to support half close, so we give it 1s to finish (echo "$da"; sleep 1) |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $SOCAT:\n" @@ -10421,12 +10547,12 @@ case "$TESTS" in TEST="$NAME: give a one line description of test" # describe how the test is performed, and what's the success criteria if ! eval $NUMCOND; then :; else -tf="$td/test$N.stout" +tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$SOCAT $opts server-address PIPE" -CMD1="$SOCAT - client-address" +CMD1="$SOCAT $opts - client-address" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! diff --git a/utils.c b/utils.c index 57904d9..6f578e2 100644 --- a/utils.c +++ b/utils.c @@ -1,5 +1,5 @@ /* source: utils.c */ -/* Copyright Gerhard Rieger 2001-2008 */ +/* Copyright Gerhard Rieger 2001-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* useful additions to C library */ @@ -75,7 +75,7 @@ int setenv(const char *name, const char *value, int overwrite) { if (!overwrite) { if (getenv(name)) return 0; /* already exists */ } - if ((env = Malloc(strlen(name)+strlen(value)+2)) != NULL) { + if ((env = Malloc(strlen(name)+strlen(value)+2)) == NULL) { return -1; } sprintf(env, "%s=%s", name, value); diff --git a/xio-fd.c b/xio-fd.c index 7006d11..8d8babe 100644 --- a/xio-fd.c +++ b/xio-fd.c @@ -74,10 +74,11 @@ const struct optdesc opt_flock_ex_nb = { "flock-ex-nb", "flock-nb", OPT_FLOCK_E const struct optdesc opt_cool_write = { "cool-write", "coolwrite", OPT_COOL_WRITE, GROUP_FD, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.cool_write }; /* control closing of connections */ -const struct optdesc opt_end_close = { "end-close", "close", OPT_END_CLOSE, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoclose, XIOCLOSE_CLOSE }; -const struct optdesc opt_shut_none = { "shut-none", NULL, OPT_SHUT_NONE, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_NONE }; -const struct optdesc opt_shut_down = { "shut-down", NULL, OPT_SHUT_DOWN, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_DOWN }; -const struct optdesc opt_shut_close= { "shut-close", NULL, OPT_SHUT_CLOSE, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_CLOSE }; +const struct optdesc opt_end_close = { "end-close", "close", OPT_END_CLOSE, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoclose, XIOCLOSE_CLOSE }; +const struct optdesc opt_shut_none = { "shut-none", NULL, OPT_SHUT_NONE, GROUP_FD, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_NONE }; +const struct optdesc opt_shut_down = { "shut-down", NULL, OPT_SHUT_DOWN, GROUP_FD, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_DOWN }; +const struct optdesc opt_shut_close= { "shut-close", NULL, OPT_SHUT_CLOSE, GROUP_FD, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_CLOSE }; +const struct optdesc opt_shut_null = { "shut-null", NULL, OPT_SHUT_NULL, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_NULL }; /****** generic ioctl() options ******/ const struct optdesc opt_ioctl_void = { "ioctl-void", "ioctl", OPT_IOCTL_VOID, GROUP_FD, PH_FD, TYPE_INT, OFUNC_IOCTL_GENERIC, 0, 0, 0 }; diff --git a/xio-fd.h b/xio-fd.h index f1460bd..4b74b55 100644 --- a/xio-fd.h +++ b/xio-fd.h @@ -1,5 +1,5 @@ /* source: xio-fd.h */ -/* Copyright Gerhard Rieger 2001-2008 */ +/* Copyright Gerhard Rieger 2001-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_fd_h_included @@ -45,6 +45,7 @@ extern const struct optdesc opt_end_close; extern const struct optdesc opt_shut_none; extern const struct optdesc opt_shut_down; extern const struct optdesc opt_shut_close; +extern const struct optdesc opt_shut_null; extern const struct optdesc opt_streams_i_push; #endif /* !defined(__xio_fd_h_included) */ diff --git a/xio-listen.c b/xio-listen.c index 12dfd57..2358d78 100644 --- a/xio-listen.c +++ b/xio-listen.c @@ -1,5 +1,5 @@ /* source: xio-listen.c */ -/* Copyright Gerhard Rieger 2001-2008 */ +/* Copyright Gerhard Rieger 2001-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for listen socket options */ @@ -261,8 +261,10 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl la = NULL; } Notice2("accepting connection from %s on %s", - sockaddr_info(pa?&pa->soa:NULL, pas, peername, sizeof(peername)), - sockaddr_info(pa?&la->soa:NULL, las, sockname, sizeof(sockname))); + pa? + sockaddr_info(&pa->soa, pas, peername, sizeof(peername)):"NULL", + la? + sockaddr_info(&la->soa, las, sockname, sizeof(sockname)):"NULL"); if (pa != NULL && la != NULL && xiocheckpeer(xfd, pa, la) < 0) { if (Shutdown(ps, 2) < 0) { @@ -271,9 +273,10 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl continue; } - Info1("permitting connection from %s", - sockaddr_info((struct sockaddr *)pa, pas, - infobuff, sizeof(infobuff))); + if (pa != NULL) + Info1("permitting connection from %s", + sockaddr_info((struct sockaddr *)pa, pas, + infobuff, sizeof(infobuff))); applyopts(xfd->rfd, opts, PH_FD); applyopts(xfd->rfd, opts, PH_CONNECTED); @@ -331,8 +334,8 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl return result; /* set the env vars describing the local and remote sockets */ - xiosetsockaddrenv("SOCK", la, las, proto); - xiosetsockaddrenv("PEER", pa, pas, proto); + if (la != NULL) xiosetsockaddrenv("SOCK", la, las, proto); + if (pa != NULL) xiosetsockaddrenv("PEER", pa, pas, proto); return 0; } diff --git a/xio-process.c b/xio-process.c index 246c47a..5ee3506 100644 --- a/xio-process.c +++ b/xio-process.c @@ -1,5 +1,5 @@ /* source: xio-process.c */ -/* Copyright Gerhard Rieger 2001-2003 */ +/* Copyright Gerhard Rieger 2001-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file handles process related addresses options */ @@ -14,6 +14,7 @@ const struct optdesc opt_setgid_early= { "setgid-early",NULL, OPT_SETGID_EARLY, const struct optdesc opt_setgid = { "setgid", NULL, OPT_SETGID, GROUP_PROCESS, PH_LATE2, TYPE_GIDT, OFUNC_SPEC }; const struct optdesc opt_setuid_early= { "setuid-early",NULL, OPT_SETUID_EARLY,GROUP_PROCESS, PH_EARLY, TYPE_UIDT, OFUNC_SPEC }; const struct optdesc opt_setuid = { "setuid", NULL, OPT_SETUID, GROUP_PROCESS, PH_LATE2, TYPE_UIDT, OFUNC_SPEC }; +const struct optdesc opt_substuser_early = { "substuser-early", "su-e", OPT_SUBSTUSER_EARLY, GROUP_PROCESS, PH_EARLY, TYPE_UIDT, OFUNC_SPEC }; const struct optdesc opt_substuser = { "substuser", "su", OPT_SUBSTUSER, GROUP_PROCESS, PH_LATE2, TYPE_UIDT, OFUNC_SPEC }; const struct optdesc opt_substuser_delayed = { "substuser-delayed", "su-d", OPT_SUBSTUSER_DELAYED, GROUP_PROCESS, PH_INIT, TYPE_UIDT, OFUNC_SPEC }; const struct optdesc opt_chroot_early = { "chroot-early", NULL, OPT_CHROOT_EARLY, GROUP_PROCESS, PH_EARLY, TYPE_STRING, OFUNC_SPEC }; diff --git a/xio-process.h b/xio-process.h index 4a80928..09ddc8c 100644 --- a/xio-process.h +++ b/xio-process.h @@ -1,5 +1,5 @@ /* source: xio-process.h */ -/* Copyright Gerhard Rieger 2001, 2002 */ +/* Copyright Gerhard Rieger 2001-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_process_h_included @@ -9,6 +9,7 @@ extern const struct optdesc opt_setgid_early; extern const struct optdesc opt_setgid; extern const struct optdesc opt_setuid_early; extern const struct optdesc opt_setuid; +extern const struct optdesc opt_substuser_early; extern const struct optdesc opt_substuser; extern const struct optdesc opt_substuser_delayed; extern const struct optdesc opt_chroot_early; diff --git a/xio-progcall.c b/xio-progcall.c index 09e613b..2cffb01 100644 --- a/xio-progcall.c +++ b/xio-progcall.c @@ -40,7 +40,7 @@ const struct optdesc opt_pipes = { "pipes", NULL, OPT_PIPES, GROUP_F #if HAVE_PTY const struct optdesc opt_pty = { "pty", NULL, OPT_PTY, GROUP_FORK, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC }; #endif -const struct optdesc opt_commtype= { "commtype", "c", OPT_COMMTYPE, GROUP_FORK, PH_BIGEN, TYPE_STRING, OFUNC_SPEC }; +const struct optdesc opt_commtype= { "commtype", NULL, OPT_COMMTYPE, GROUP_FORK, PH_BIGEN, TYPE_STRING, OFUNC_SPEC }; const struct optdesc opt_stderr = { "stderr", NULL, OPT_STDERR, GROUP_FORK, PH_PASTFORK, TYPE_BOOL, OFUNC_SPEC }; const struct optdesc opt_nofork = { "nofork", NULL, OPT_NOFORK, GROUP_FORK, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC }; const struct optdesc opt_sighup = { "sighup", NULL, OPT_SIGHUP, GROUP_PARENT, PH_LATE, TYPE_CONST, OFUNC_SIGNAL, SIGHUP }; @@ -87,7 +87,7 @@ int _xioopen_progcall(int xioflags, /* XIO_RDONLY etc. */ struct opt *popts; /* parent process options */ int numleft; int sv[2], rdpip[2], wrpip[2]; - int saverfd, savewfd; /* with inter addr, save assigned right fds */ + int saverfd = -1, savewfd = -1; /* with inter addr, save assigned right fds */ int rw = (xioflags & XIO_ACCMODE); char *commname; int commtype = XIOCOMM_SOCKETPAIRS; @@ -213,6 +213,7 @@ int _xioopen_progcall(int xioflags, /* XIO_RDONLY etc. */ case XIOCOMM_TCP4: typename = "TCP4 socket pair"; break; case XIOCOMM_TCP4_LISTEN: typename = "TCP4 listen socket pair"; break; #endif + default: typename = NULL; break; } Notice2("forking off child, using %s for %s", typename, ddirection[rw]); @@ -758,6 +759,7 @@ Warn1("xio-progcall.c: fd->howtoshut == %d", fd->howtoshut); } if (fdi != sv[1] && fdo != sv[1]) { applyopts_cloexec(sv[1], *copts); + Close(sv[1]); } applyopts(fdi, *copts, PH_LATE); diff --git a/xio-pty.c b/xio-pty.c index b7984f1..dbbc1ba 100644 --- a/xio-pty.c +++ b/xio-pty.c @@ -1,5 +1,5 @@ /* source: xio-pty.c */ -/* Copyright Gerhard Rieger 2002-2008 */ +/* Copyright Gerhard Rieger 2002-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for creating pty addresses */ @@ -66,8 +66,8 @@ static int xioopen_pty(const char *linkname, struct opt *opts, int xioflags, xio compatibility we choose "no" as default */ struct timespec pollintv = { PTY_INTERVALL }; - applyopts(-1, opts, PH_INIT); if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; + applyopts(-1, opts, PH_INIT); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); @@ -99,8 +99,8 @@ static int xioopen_pty(const char *linkname, struct opt *opts, int xioflags, xio retropt_timespec(opts, OPT_PTY_INTERVALL, &pollintv); #endif /* HAVE_POLL */ - applyopts2(-1, opts, PH_INIT, PH_EARLY); if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; + applyopts2(-1, opts, PH_INIT, PH_EARLY); applyopts(-1, opts, PH_PREBIGEN); diff --git a/xio-socket.c b/xio-socket.c index eb0bc79..6958aed 100644 --- a/xio-socket.c +++ b/xio-socket.c @@ -226,6 +226,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_PASTSOCKET,TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 }; const struct optdesc opt_setsockopt_string = { "setsockopt-string", "sockopt-string", OPT_SETSOCKOPT_STRING, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_STRING, OFUNC_SOCKOPT_GENERIC, 0, 0 }; +const struct optdesc opt_null_eof = { "null-eof", NULL, OPT_NULL_EOF, GROUP_SOCKET, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.para.socket.null_eof }; + #if WITH_GENERICSOCKET @@ -267,8 +269,8 @@ int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts, retropt_int(opts, OPT_SO_TYPE, &socktype); /*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/ - applyopts(-1, opts, PH_INIT); if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + applyopts(-1, opts, PH_INIT); applyopts(-1, opts, PH_EARLY); themlen = 0; @@ -891,10 +893,10 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, themlen, strerror(errno)); timeout = xfd->para.socket.connect_timeout; writefd.fd = xfd->rfd; - writefd.events = (POLLIN|POLLHUP|POLLERR); + writefd.events = (POLLOUT|POLLERR); result = xiopoll(&writefd, 1, &timeout); if (result < 0) { - Msg4(level, "xiopoll({%d,POLLIN|POLLHUP|POLLER},,{"F_tv_sec"."F_tv_usec"): %s", + Msg4(level, "xiopoll({%d,POLLOUT|POLLER},,{"F_tv_sec"."F_tv_usec"): %s", xfd->rfd, timeout.tv_sec, timeout.tv_usec, strerror(errno)); return STAT_RETRYLATER; } @@ -904,7 +906,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen, strerror(ETIMEDOUT)); return STAT_RETRYLATER; } - if (writefd.revents & POLLOUT) { + if (writefd.revents & POLLERR) { #if 0 unsigned char dummy[1]; Read(xfd->rfd, &dummy, 1); /* get error message */ diff --git a/xio-socket.h b/xio-socket.h index a35f3d2..d2744b8 100644 --- a/xio-socket.h +++ b/xio-socket.h @@ -1,5 +1,5 @@ /* source: xio-socket.h */ -/* Copyright Gerhard Rieger 2001-2008 */ +/* Copyright Gerhard Rieger 2001-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xio_socket_h_included @@ -67,6 +67,7 @@ extern const struct optdesc opt_protocol_family; extern const struct optdesc opt_setsockopt_int; extern const struct optdesc opt_setsockopt_bin; extern const struct optdesc opt_setsockopt_string; +extern const struct optdesc opt_null_eof; extern diff --git a/xio-unix.c b/xio-unix.c index 9877b4f..2b71de3 100644 --- a/xio-unix.c +++ b/xio-unix.c @@ -169,6 +169,7 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i } } + if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; applyopts(-1, opts, PH_INIT); applyopts(-1, opts, PH_EARLY); @@ -242,8 +243,8 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, xfd->opt_unlink_close = true; } - applyopts(-1, opts, PH_INIT); if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + applyopts(-1, opts, PH_INIT); applyopts(-1, opts, PH_EARLY); if ((result = @@ -315,8 +316,8 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i xfd->opt_unlink_close = true; } - applyopts(-1, opts, PH_INIT); if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + applyopts(-1, opts, PH_INIT); if ((result = _xioopen_dgram_sendto(needbind?&us:NULL, uslen, @@ -497,8 +498,8 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups, struct opt *opts0; int result; - applyopts(-1, opts, PH_INIT); if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + applyopts(-1, opts, PH_INIT); retropt_socket_pf(opts, &pf); diff --git a/xio.h b/xio.h index 6d13a10..88a1f19 100644 --- a/xio.h +++ b/xio.h @@ -123,11 +123,13 @@ struct opt; #define XIOSHUTRD_SIGTERM 0x0050 /* kill sub process with SIGTERM */ #define XIOSHUTWR_SIGTERM 0x0005 /* kill sub process with SIGTERM */ #define XIOSHUTWR_SIGKILL 0x0006 /* kill sub process with SIGKILL */ +#define XIOSHUTWR_NULL 0x0007 /* send empty packet (dgram socket) */ #define XIOSHUT_UNSPEC (XIOSHUTRD_UNSPEC|XIOSHUTWR_UNSPEC) #define XIOSHUT_NONE (XIOSHUTRD_NONE|XIOSHUTWR_NONE) #define XIOSHUT_CLOSE (XIOSHUTRD_CLOSE|XIOSHUTWR_CLOSE) #define XIOSHUT_DOWN (XIOSHUTRD_DOWN|XIOSHUTWR_DOWN) #define XIOSHUT_KILL (XIOSHUTRD_KILL|XIOSHUTWR_KILL) +#define XIOSHUT_NULL (XIOSHUTRD_DOWN|XIOSHUTWR_NULL) #define XIOSHUT_PTYEOF 0x0100 /* change pty to icanon and write VEOF */ #define XIOSHUT_OPENSSL 0x0101 /* specific action on openssl */ /*!!!*/ @@ -374,7 +376,7 @@ typedef struct single { struct { struct timeval connect_timeout; /* how long to hang in connect() */ union sockaddr_union la; /* local socket address */ - bool emptyiseof; /* with dgram: empty packet means EOF */ + bool null_eof; /* with dgram: empty packet means EOF */ bool dorange; struct xiorange range; /* restrictions for peer address */ #if _WITH_IP4 || _WITH_IP6 diff --git a/xiohelp.c b/xiohelp.c index a135a83..aed4110 100644 --- a/xiohelp.c +++ b/xiohelp.c @@ -1,5 +1,5 @@ /* source: xiohelp.c */ -/* Copyright Gerhard Rieger 2001-2008 */ +/* Copyright Gerhard Rieger 2001-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for the help function */ diff --git a/xioopts.c b/xioopts.c index 2cff2f4..6bda52a 100644 --- a/xioopts.c +++ b/xioopts.c @@ -937,6 +937,8 @@ const struct optname optionnames[] = { #ifdef O_NSHARE IF_OPEN ("nshare", &opt_o_nshare) #endif + IF_SOCKET ("null-eof", &opt_null_eof) + IF_ANY ("o-append", &opt_append) #ifdef O_ASYNC IF_ANY ("o-async", &opt_async) #endif @@ -1286,6 +1288,7 @@ const struct optname optionnames[] = { IF_ANY ("shut-close", &opt_shut_close) IF_ANY ("shut-down", &opt_shut_down) IF_ANY ("shut-none", &opt_shut_none) + IF_ANY ("shut-null", &opt_shut_null) #if WITH_EXEC || WITH_SYSTEM IF_ANY ("sid", &opt_setsid) #endif @@ -1428,8 +1431,10 @@ const struct optname optionnames[] = { #endif IF_ANY ("su", &opt_substuser) IF_ANY ("su-d", &opt_substuser_delayed) + IF_ANY ("su-e", &opt_substuser_early) IF_ANY ("substuser", &opt_substuser) IF_ANY ("substuser-delayed", &opt_substuser_delayed) + IF_ANY ("substuser-early", &opt_substuser_early) IF_TERMIOS("susp", &opt_vsusp) #ifdef VSWTC IF_TERMIOS("swtc", &opt_vswtc) @@ -3256,6 +3261,7 @@ int applyopts(int fd, struct opt *opts, enum e_phase phase) { opt->desc = ODESC_ERROR; ++opt; continue; } break; + case OPT_SUBSTUSER_EARLY: case OPT_SUBSTUSER: { struct passwd *pwd; diff --git a/xioopts.h b/xioopts.h index 248e685..2bbe729 100644 --- a/xioopts.h +++ b/xioopts.h @@ -448,6 +448,7 @@ enum e_optcode { OPT_NOFLSH, /* termios.c_lflag */ OPT_NOFORK, /* exec, system */ OPT_NOPROMPT, /* readline */ + OPT_NULL_EOF, /* receiving empty packet triggers EOF */ #ifdef OCRNL OPT_OCRNL, /* termios.c_oflag */ #endif @@ -600,6 +601,7 @@ enum e_optcode { OPT_SHUT_CLOSE, OPT_SHUT_DOWN, OPT_SHUT_NONE, + OPT_SHUT_NULL, /* send 0 bytes on shutdown */ OPT_SIGHUP, OPT_SIGINT, OPT_SIGQUIT, @@ -707,6 +709,7 @@ enum e_optcode { # define ENABLE_OPTCODE # include "xio-streams.h" # undef ENABLE_OPTCODE + OPT_SUBSTUSER_EARLY, OPT_SUBSTUSER, OPT_SUBSTUSER_DELAYED, OPT_SYMBOLIC_LINK, /* with pty */ diff --git a/xioread.c b/xioread.c index 476070f..08f7d82 100644 --- a/xioread.c +++ b/xioread.c @@ -1,5 +1,5 @@ /* source: xioread.c */ -/* Copyright Gerhard Rieger 2001-2008 */ +/* Copyright Gerhard Rieger 2001-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this is the source of the extended read function */ @@ -189,7 +189,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) { bytes, sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff))); if (bytes == 0) { - if (!pipe->para.socket.emptyiseof) { + if (!pipe->para.socket.null_eof) { errno = EAGAIN; return -1; } return bytes; @@ -380,7 +380,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) { bytes, sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff))); if (bytes == 0) { - if (!pipe->para.socket.emptyiseof) { + if (!pipe->para.socket.null_eof) { errno = EAGAIN; return -1; } return bytes; diff --git a/xioshutdown.c b/xioshutdown.c index 282de50..b203ed1 100644 --- a/xioshutdown.c +++ b/xioshutdown.c @@ -1,5 +1,5 @@ /* source: xioshutdown.c */ -/* Copyright Gerhard Rieger 2001-2008 */ +/* Copyright Gerhard Rieger 2001-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this is the source of the extended shutdown function */ @@ -20,6 +20,7 @@ static void signal_kill_pid(int dummy) { /* how: SHUT_RD, SHUT_WR, or SHUT_RDWR */ int xioshutdown(xiofile_t *sock, int how) { + int fd; int result = 0; Debug2("xioshutdown(%p, %d)", sock, how); @@ -43,6 +44,8 @@ int xioshutdown(xiofile_t *sock, int how) { return result; } + fd = XIO_GETWRFD(sock); + /* let us bring how nearer to the resulting action */ if ((sock->stream.flags&XIO_ACCMODE) == XIO_WRONLY) { how = ((how+1) & ~(SHUT_RD+1)) - 1; @@ -50,7 +53,6 @@ int xioshutdown(xiofile_t *sock, int how) { how = ((how+1) & ~(SHUT_WR+1)) - 1; } - /* here handle special shutdown functions */ switch (sock->stream.howtoshut) { #if WITH_PTY case XIOSHUT_PTYEOF: @@ -92,6 +94,31 @@ int xioshutdown(xiofile_t *sock, int how) { /*! what about half/full close? */ return 0; #endif /* WITH_OPENSSL */ + default: + break; + } + + /* here handle special shutdown functions */ + switch (sock->stream.howtoshut & XIOSHUTWR_MASK) { + char writenull; + case XIOSHUTWR_NONE: + return 0; + case XIOSHUTWR_CLOSE: + if (Close(fd) < 0) { + Info2("close(%d): %s", fd, strerror(errno)); + } + return 0; + case XIOSHUTWR_DOWN: + if ((result = Shutdown(fd, how)) < 0) { + Info3("shutdown(%d, %d): %s", fd, how, strerror(errno)); + } + return 0; +#if _WITH_SOCKET + case XIOSHUTWR_NULL: + /* send an empty packet; only useful on datagram sockets? */ + xiowrite(sock, &writenull, 0); + return 0; +#endif /* _WITH_SOCKET */ default: break; } @@ -103,25 +130,23 @@ int xioshutdown(xiofile_t *sock, int how) { switch (sock->stream.howtoshut) { #if _WITH_SOCKET case XIOSHUT_DOWN: - if ((result = Shutdown(sock->stream.fd1, how)) < 0) { - Info3("shutdown(%d, %d): %s", - sock->stream.fd1, how, strerror(errno)); + if ((result = Shutdown(fd, how)) < 0) { + Info3("shutdown(%d, %d): %s", fd, how, strerror(errno)); } break; case XIOSHUT_KILL: - if ((result = Shutdown(sock->stream.fd1, how)) < 0) { - Info3("shutdown(%d, %d): %s", - sock->stream.fd1, how, strerror(errno)); + if ((result = Shutdown(fd, how)) < 0) { + Info3("shutdown(%d, %d): %s", fd, how, strerror(errno)); } break; #endif /* _WITH_SOCKET */ case XIOSHUT_CLOSE: - Close(sock->stream.fd1); + Close(fd); #if WITH_TERMIOS if (sock->stream.ttyvalid) { - if (Tcsetattr(sock->stream.fd1, 0, &sock->stream.savetty) < 0) { + if (Tcsetattr(fd, 0, &sock->stream.savetty) < 0) { Warn2("cannot restore terminal settings on fd %d: %s", - sock->stream.fd1, strerror(errno)); + fd, strerror(errno)); } } #endif /* WITH_TERMIOS */ @@ -136,9 +161,9 @@ int xioshutdown(xiofile_t *sock, int how) { #if 0 && _WITH_SOCKET case XIODATA_RECVFROM: if (how >= 1) { - if (Close(sock->stream.fd1) < 0) { + if (Close(fd) < 0) { Info2("close(%d): %s", - sock->stream.fd1, strerror(errno)); + fd, strerror(errno)); } sock->stream.eof = 2; sock->stream.fd1 = -1; @@ -154,9 +179,8 @@ int xioshutdown(xiofile_t *sock, int how) { case XIOREAD_STREAM: case XIODATA_2PIPE: - if (Close(sock->stream.rfd) < 0) { - Info2("close(%d): %s", - sock->stream.rfd, strerror(errno)); + if (Close(fd) < 0) { + Info2("close(%d): %s", fd, strerror(errno)); } break; } @@ -164,9 +188,6 @@ int xioshutdown(xiofile_t *sock, int how) { if ((how+1) & 2) { /* contains SHUT_WR */ /* shutdown write channel */ - int fd; - - fd = sock->stream.wfd; switch (sock->stream.howtoshut & XIOSHUTWR_MASK) { diff --git a/xiosocketpair.c b/xiosocketpair.c index c12fcf3..ef74235 100644 --- a/xiosocketpair.c +++ b/xiosocketpair.c @@ -247,8 +247,8 @@ int xiosocketpair2(int pf, int socktype, int protocol, int sv[2]) { int xiocommpair(int commtype, bool lefttoright, bool righttoleft, int dual, xiofd_t *left, xiofd_t *right, ...) { va_list ap; - int domain, socktype, protocol; - int useptmx; + int domain = -1, socktype = -1, protocol = -1; + int useptmx = 0; /* arrays can be used with pipe(2) and socketpair(2): */ int svlr[2] = {-1, -1}; /* left to right: rfd, wfd */ int svrl[2] = {-1, -1}; /* right to left: rfd, wfd */