merged feature sctp streams

This commit is contained in:
Gerhard Rieger 2008-09-22 23:21:26 +02:00
parent d78b080ef0
commit 91057b0b68
17 changed files with 388 additions and 17 deletions

View file

@ -1,5 +1,9 @@
new features: new features:
new address types SCTP-CONNECT and SCTP-LISTEN implement SCTP stream
mode for IPv4 and IPv6; new address options sctp-maxseg and
sctp-nodelay
added generic socket addresses: SOCKET-CONNECT, SOCKET-LISTEN, added generic socket addresses: SOCKET-CONNECT, SOCKET-LISTEN,
SOCKET-SENDTO, SOCKET-RECVFROM, SOCKET-RECV, SOCKET-DATAGRAM allow SOCKET-SENDTO, SOCKET-RECVFROM, SOCKET-RECV, SOCKET-DATAGRAM allow
protocol independent socket handling; all parameters are explicitely protocol independent socket handling; all parameters are explicitely

View file

@ -46,7 +46,7 @@ XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \
xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \ xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \
xio-gopen.c xio-creat.c xio-file.c xio-named.c \ xio-gopen.c xio-creat.c xio-file.c xio-named.c \
xio-socket.c xio-listen.c xio-unix.c xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c xio-socks.c xio-proxy.c xio-udp.c \ xio-socket.c xio-listen.c xio-unix.c xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c xio-socks.c xio-proxy.c xio-udp.c \
xio-rawip.c \ xio-sctp.c xio-rawip.c \
xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \ xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
xio-pty.c xio-openssl.c \ xio-pty.c xio-openssl.c \
xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c
@ -63,6 +63,7 @@ HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.
xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h xio-socket.h \ xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h xio-socket.h \
xio-listen.h xio-unix.h xio-rawip.h xio-ip.h xio-ip4.h xio-ip6.h \ xio-listen.h xio-unix.h xio-rawip.h xio-ip.h xio-ip4.h xio-ip6.h \
xio-ipapp.h xio-tcp.h xio-udp.h xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ xio-ipapp.h xio-tcp.h xio-udp.h xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \
xio-sctp.h \
xio-system.h xio-termios.h xio-readline.h \ xio-system.h xio-termios.h xio-readline.h \
xio-pty.h xio-openssl.h \ xio-pty.h xio-openssl.h \
xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h

View file

@ -1 +1 @@
"1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+escape+timestamp+ancillary+envvar+protocol+ioctl+setsockopt+genericsocket" "1.6.0.1+ip4bind+recvfromfork+x64+execstderr+execspaces+cosmetics+poll+udplistencont+ignoreeofunblock+escape+timestamp+ancillary+envvar+protocol+ioctl+setsockopt+genericsocket+sctp"

View file

@ -1,5 +1,5 @@
/* source: config.h.in */ /* source: config.h.in */
/* Copyright Gerhard Rieger 2001-2007 */ /* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */ /* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __config_h_included #ifndef __config_h_included
@ -471,6 +471,7 @@
#undef WITH_GENERICSOCKET #undef WITH_GENERICSOCKET
#undef WITH_TCP #undef WITH_TCP
#undef WITH_UDP #undef WITH_UDP
#undef WITH_SCTP
#undef WITH_LISTEN #undef WITH_LISTEN
#undef WITH_SOCKS4 #undef WITH_SOCKS4
#undef WITH_SOCKS4A #undef WITH_SOCKS4A

View file

@ -237,6 +237,14 @@ AC_ARG_ENABLE(udp, [ --disable-udp disable UDP support],
esac], esac],
[AC_DEFINE(WITH_UDP) AC_MSG_RESULT(yes)]) [AC_DEFINE(WITH_UDP) AC_MSG_RESULT(yes)])
AC_MSG_CHECKING(whether to include SCTP support)
AC_ARG_ENABLE(tcp, [ --disable-sctp disable SCTP support],
[case "$enableval" in
no) AC_MSG_RESULT(no);;
*) AC_DEFINE(WITH_SCTP) AC_MSG_RESULT(yes);;
esac],
[AC_DEFINE(WITH_SCTP) AC_MSG_RESULT(yes)])
AC_MSG_CHECKING(whether to include listen support) AC_MSG_CHECKING(whether to include listen support)
AC_ARG_ENABLE(listen, [ --disable-listen disable listen support], AC_ARG_ENABLE(listen, [ --disable-listen disable listen support],
[case "$enableval" in [case "$enableval" in

View file

@ -600,6 +600,69 @@ label(ADDRESS_READLINE)dit(bf(tt(READLINE)))
link(noecho)(OPTION_NOECHO)nl() link(noecho)(OPTION_NOECHO)nl()
See also: See also:
link(STDIO)(ADDRESS_STDIO) link(STDIO)(ADDRESS_STDIO)
label(ADDRESS_SCTP_CONNECT)dit(bf(tt(SCTP-CONNECT:<host>:<port>)))
Establishes an SCTP stream connection to the specified <host> [link(IP
address)(TYPE_IP_ADDRESS)] and <port> [link(TCP service)(TYPE_TCP_SERVICE)]
using TCP/IP version 4 or 6 depending on address specification, name
resolution, or option link(pf)(OPTION_PROTOCOL_FAMILY).nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(SCTP)(GROUP_SCTP),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY) nl()
Useful options:
link(bind)(OPTION_BIND),
link(pf)(OPTION_PROTOCOL_FAMILY),
link(connect-timeout)(OPTION_CONNECT_TIMEOUT),
link(tos)(OPTION_TOS),
link(mtudiscover)(OPTION_MTUDISCOVER),
link(mss)(OPTION_MSS),
link(nodelay)(OPTION_NODELAY),
link(nonblock)(OPTION_NONBLOCK),
link(sourceport)(OPTION_SOURCEPORT),
link(retry)(OPTION_RETRY),
link(readbytes)(OPTION_READBYTES)nl()
See also:
link(SCTP4-CONNECT)(ADDRESS_SCTP4_CONNECT),
link(SCTP6-CONNECT)(ADDRESS_SCTP6_CONNECT),
link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN),
link(TCP-CONNECT)(ADDRESS_TCP_CONNECT)
label(ADDRESS_SCTP4_CONNECT)dit(bf(tt(SCTP4-CONNECT:<host>:<port>)))
Like link(SCTP-CONNECT)(ADDRESS_SCTP_CONNECT), but only supports IPv4 protocol.nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(SCTP)(GROUP_SCTP),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY) nl()
label(ADDRESS_SCTP6_CONNECT)dit(bf(tt(SCTP6-CONNECT:<host>:<port>)))
Like link(SCTP-CONNECT)(ADDRESS_SCTP_CONNECT), but only supports IPv6 protocol.nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6),link(SCTP)(GROUP_SCTP),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY) nl()
label(ADDRESS_SCTP_LISTEN)dit(bf(tt(SCTP-LISTEN:<port>)))
Listens on <port> [link(TCP service)(TYPE_TCP_SERVICE)] and accepts a
TCP/IP connection. The IP version is 4 or the one specified with
address option link(pf)(OPTION_PROTOCOL_FAMILY), socat option
(link(-4)(option_4), link(-6)(option_6)), or environment variable link(SOCAT_DEFAULT_LISTEN_IP)(ENV_SOCAT_DEFAULT_LISTEN_IP).
Note that opening
this address usually blocks until a client connects.nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(SCTP)(GROUP_SCTP),link(RETRY)(GROUP_RETRY) nl()
Useful options:
link(crnl)(OPTION_CRNL),
link(fork)(OPTION_FORK),
link(bind)(OPTION_BIND),
link(range)(OPTION_RANGE),
link(tcpwrap)(OPTION_TCPWRAPPERS),
link(pf)(OPTION_PROTOCOL_FAMILY),
link(backlog)(OPTION_BACKLOG),
link(mss)(OPTION_MSS),
link(su)(OPTION_SUBSTUSER),
link(reuseaddr)(OPTION_REUSEADDR),
link(retry)(OPTION_RETRY),
link(cool-write)(OPTION_COOL_WRITE)nl()
See also:
link(SCTP4-LISTEN)(ADDRESS_SCTP4_LISTEN),
link(SCTP6-LISTEN)(ADDRESS_SCTP6_LISTEN),
link(TCP-LISTEN)(ADDRESS_TCP_LISTEN),
link(SCTP-CONNECT)(ADDRESS_SCTP_CONNECT)
label(ADDRESS_SCTP4_LISTEN)dit(bf(tt(SCTP4-LISTEN:<port>)))
Like link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN), but only supports IPv4
protocol.nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP4)(GROUP_IP4),link(SCTP)(GROUP_SCTP),link(RETRY)(GROUP_RETRY) nl()
label(ADDRESS_SCTP6_LISTEN)dit(bf(tt(SCTP6-LISTEN:<port>)))
Like link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN), but only supports IPv6
protocol.nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP6)(GROUP_IP6),link(SCTP)(GROUP_SCTP),link(RETRY)(GROUP_RETRY) nl()
label(ADDRESS_SOCKET_CONNECT)dit(bf(tt(SOCKET-CONNECT:<domain>:<protocol>:<remote-address>))) label(ADDRESS_SOCKET_CONNECT)dit(bf(tt(SOCKET-CONNECT:<domain>:<protocol>:<remote-address>)))
Creates a stream socket using the first and second given socket parameters Creates a stream socket using the first and second given socket parameters
and tt(SOCK_STREAM) (see man socket(2)) and connects to the remote-address. and tt(SOCK_STREAM) (see man socket(2)) and connects to the remote-address.
@ -829,6 +892,7 @@ label(ADDRESS_TCP_CONNECT)dit(bf(tt(TCP:<host>:<port>)))
link(TCP6)(ADDRESS_TCP6_CONNECT), link(TCP6)(ADDRESS_TCP6_CONNECT),
link(TCP-LISTEN)(ADDRESS_TCP_LISTEN), link(TCP-LISTEN)(ADDRESS_TCP_LISTEN),
link(UDP)(ADDRESS_UDP_CONNECT), link(UDP)(ADDRESS_UDP_CONNECT),
link(SCTP-CONNECT)(ADDRESS_SCTP_CONNECT),
link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT) link(UNIX-CONNECT)(ADDRESS_UNIX_CONNECT)
label(ADDRESS_TCP4_CONNECT)dit(bf(tt(TCP4:<host>:<port>))) label(ADDRESS_TCP4_CONNECT)dit(bf(tt(TCP4:<host>:<port>)))
Like link(TCP)(ADDRESS_TCP_CONNECT), but only supports IPv4 protocol (link(example)(EXAMPLE_ADDRESS_TCP4_CONNECT)).nl() Like link(TCP)(ADDRESS_TCP_CONNECT), but only supports IPv4 protocol (link(example)(EXAMPLE_ADDRESS_TCP4_CONNECT)).nl()
@ -839,7 +903,8 @@ label(ADDRESS_TCP6_CONNECT)dit(bf(tt(TCP6:<host>:<port>)))
label(ADDRESS_TCP_LISTEN)dit(bf(tt(TCP-LISTEN:<port>))) label(ADDRESS_TCP_LISTEN)dit(bf(tt(TCP-LISTEN:<port>)))
Listens on <port> [link(TCP service)(TYPE_TCP_SERVICE)] and accepts a Listens on <port> [link(TCP service)(TYPE_TCP_SERVICE)] and accepts a
TCP/IP connection. The IP version is 4 or the one specified with TCP/IP connection. The IP version is 4 or the one specified with
link(pf)(OPTION_PROTOCOL_FAMILY). address option link(pf)(OPTION_PROTOCOL_FAMILY), socat option
(link(-4)(option_4), link(-6)(option_6)), or environment variable link(SOCAT_DEFAULT_LISTEN_IP)(ENV_SOCAT_DEFAULT_LISTEN_IP).
Note that opening Note that opening
this address usually blocks until a client connects.nl() this address usually blocks until a client connects.nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(RETRY)(GROUP_RETRY) nl() Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(RETRY)(GROUP_RETRY) nl()
@ -855,13 +920,15 @@ label(ADDRESS_TCP_LISTEN)dit(bf(tt(TCP-LISTEN:<port>)))
link(su)(OPTION_SUBSTUSER), link(su)(OPTION_SUBSTUSER),
link(reuseaddr)(OPTION_REUSEADDR), link(reuseaddr)(OPTION_REUSEADDR),
link(retry)(OPTION_RETRY), link(retry)(OPTION_RETRY),
link(retry)(OPTION_COOL_WRITE)nl() link(cool-write)(OPTION_COOL_WRITE)nl()
See also: See also:
link(TCP4-LISTEN)(ADDRESS_TCP4_CONNECT), link(TCP4-LISTEN)(ADDRESS_TCP4_LISTEN),
link(TCP6-LISTEN)(ADDRESS_TCP6_LISTEN), link(TCP6-LISTEN)(ADDRESS_TCP6_LISTEN),
link(UDP-LISTEN)(ADDRESS_UDP_LISTEN), link(UDP-LISTEN)(ADDRESS_UDP_LISTEN),
link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN),
link(UNIX-LISTEN)(ADDRESS_UNIX_LISTEN), link(UNIX-LISTEN)(ADDRESS_UNIX_LISTEN),
link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN) link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN),
link(TCP-CONNECT)(ADDRESS_TCP_CONNECT)
label(ADDRESS_TCP4_LISTEN)dit(bf(tt(TCP4-LISTEN:<port>))) label(ADDRESS_TCP4_LISTEN)dit(bf(tt(TCP4-LISTEN:<port>)))
Like link(TCP-LISTEN)(ADDRESS_TCP_LISTEN), but only supports IPv4 Like link(TCP-LISTEN)(ADDRESS_TCP_LISTEN), but only supports IPv4
protocol (link(example)(EXAMPLE_ADDRESS_TCP4_LISTEN)).nl() protocol (link(example)(EXAMPLE_ADDRESS_TCP4_LISTEN)).nl()
@ -2058,10 +2125,24 @@ enddit()
startdit()enddit()nl() startdit()enddit()nl()
em(bf(UDP and TCP option groups)) label(GROUP_SCTP)em(bf(SCTP option group))
These options may be applied to SCTP stream sockets.
startdit()
label(OPTION_SCTP_NODELAY)dit(bf(tt(sctp-nodelay)))
Sets the SCTP_NODELAY socket option that disables the Nagle algorithm.
label(OPTION_SCTP_MAXSEG)dit(bf(tt(sctp-maxseg=<bytes>)))
Sets the SCTP_MAXSEG socket option to <bytes> [link(int)(TYPE_INT)]. This
value is then proposed to the peer with the SYN or SYN/ACK packet.
enddit()
startdit()enddit()nl()
em(bf(UDP, TCP, and SCTP option groups))
Here we find options that are related to the network port mechanism and that Here we find options that are related to the network port mechanism and that
thus can be used with UDP and TCP, client and server addresses. thus can be used with UDP, TCP, and SCTP client and server addresses.
startdit() startdit()
label(OPTION_SOURCEPORT)dit(bf(tt(sourceport=<port>))) label(OPTION_SOURCEPORT)dit(bf(tt(sourceport=<port>)))
For outgoing (client) TCP and UDP connections, it sets the source For outgoing (client) TCP and UDP connections, it sets the source
@ -3163,11 +3244,11 @@ by the upper case name of the executable or the value of option
link(-lp)(option_lp). link(-lp)(option_lp).
startdit() startdit()
label(ENV_SOCAT_DEFAULT_LISTEN_IP)
dit(bf(SOCAT_DEFAULT_LISTEN_IP) (input)) (Values 4 or 6) Sets the IP version to dit(bf(SOCAT_DEFAULT_LISTEN_IP) (input)) (Values 4 or 6) Sets the IP version to
be used be used for listen, recv, and recvfrom addresses if no
for listen, recv, and recvfrom addresses if no link(pf)(OPTION_PROTOCOL_FAMILY) link(pf)(OPTION_PROTOCOL_FAMILY) (protocol-family) option is given. Is
(protocol-family) option is given. Is overridden by socat options overridden by socat options link(-4)(option_4) or link(-6)(option_6).
link(-4)(option_4) or link(-6)(option_6).
dit(bf(SOCAT_PREFERRED_RESOLVE_IP) (input)) (Values 0, 4, or 6) Sets the IP dit(bf(SOCAT_PREFERRED_RESOLVE_IP) (input)) (Values 0, 4, or 6) Sets the IP
version to version to

View file

@ -438,6 +438,11 @@ void socat_version(FILE *fd) {
#else #else
fputs(" #undef WITH_UDP\n", fd); fputs(" #undef WITH_UDP\n", fd);
#endif #endif
#ifdef WITH_SCTP
fprintf(fd, " #define WITH_SCTP %d\n", WITH_SCTP);
#else
fputs(" #undef WITH_SCTP\n", fd);
#endif
#ifdef WITH_LISTEN #ifdef WITH_LISTEN
fprintf(fd, " #define WITH_LISTEN %d\n", WITH_LISTEN); fprintf(fd, " #define WITH_LISTEN %d\n", WITH_LISTEN);
#else #else

View file

@ -423,7 +423,9 @@ int xiopoll(struct pollfd fds[], nfds_t nfds, int timeout) {
#if WITH_TCP || WITH_UDP #if WITH_TCP || WITH_UDP
/* returns port in network byte order */ /* returns port in network byte order;
ipproto==IPPROTO_UDP resolves as UDP service, every other value resolves as
TCP */
int parseport(const char *portname, int ipproto) { int parseport(const char *portname, int ipproto) {
struct servent *se; struct servent *se;
char *extra; char *extra;
@ -438,7 +440,7 @@ int parseport(const char *portname, int ipproto) {
return result; return result;
} }
if ((se = getservbyname(portname, ipproto==IPPROTO_TCP?"tcp":"udp")) == NULL) { if ((se = getservbyname(portname, ipproto==IPPROTO_UDP?"udp":"tcp")) == NULL) {
Error2("cannot resolve service \"%s/%d\"", portname, ipproto); Error2("cannot resolve service \"%s/%d\"", portname, ipproto);
return 0; return 0;
} }

162
test.sh
View file

@ -1866,6 +1866,40 @@ waitudp4port () {
return 1 return 1
} }
# wait until an SCTP4 listen port is ready
waitsctp4port () {
local port="$1"
local logic="$2" # 0..wait until free; 1..wait until listening
local timeout="$3"
local l
[ "$logic" ] || logic=1
[ "$timeout" ] || timeout=5
while [ $timeout -gt 0 ]; do
case "$UNAME" in
Linux) l=$(netstat -n -a |grep '^sctp .* .*[0-9*]:'$port' .* LISTEN') ;;
# FreeBSD) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;;
# NetBSD) l=$(netstat -an |grep '^tcp .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]* LISTEN.*') ;;
# Darwin) case "$(uname -r)" in
# [1-5]*) l=$(netstat -an |grep '^tcp.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;;
# *) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;;
# esac ;;
# AIX) l=$(netstat -an |grep '^tcp[^6] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;;
# SunOS) l=$(netstat -an -f inet -P tcp |grep '.*[1-9*]\.'$port' .*\* 0 .* LISTEN') ;;
# HP-UX) l=$(netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' .* LISTEN$') ;;
# OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') ;;
# CYGWIN*) l=$(netstat -an -p TCP |grep '^ TCP [0-9.]*:'$port' .* LISTENING') ;;
*) l=$(netstat -an |grep -i 'sctp .*[0-9*][:.]'$port' .* listen') ;;
esac
[ \( \( $logic -ne 0 \) -a -n "$l" \) -o \
\( \( $logic -eq 0 \) -a -z "$l" \) ] && return 0
sleep 1
timeout=$((timeout-1))
done
$ECHO "!port $port timed out! \c" >&2
return 1
}
# wait until a tcp6 listen port is ready # wait until a tcp6 listen port is ready
waittcp6port () { waittcp6port () {
local port="$1" local port="$1"
@ -1926,6 +1960,36 @@ waitudp6port () {
return 1 return 1
} }
# wait until a sctp6 listen port is ready
# not all (Linux) variants show this in netstat
waitsctp6port () {
local port="$1"
local logic="$2" # 0..wait until free; 1..wait until listening
local timeout="$3"
local l
[ "$logic" ] || logic=1
[ "$timeout" ] || timeout=5
while [ $timeout -gt 0 ]; do
case "$UNAME" in
Linux) l=$(netstat -an |grep '^sctp[6 ] .* [0-9a-f:]*:'$port' .* LISTEN') ;;
# FreeBSD) l=$(netstat -an |grep -i 'tcp[46][6 ] .*[0-9*][:.]'$port' .* listen') ;;
# NetBSD) l=$(netstat -an |grep '^tcp6 .*[0-9*]\.'$port' [ ]* \*\.\*') ;;
# OpenBSD) l=$(netstat -an |grep -i 'tcp6 .*[0-9*][:.]'$port' .* listen') ;;
# AIX) l=$(netstat -an |grep '^tcp[6 ] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;;
# SunOS) l=$(netstat -an -f inet6 -P tcp |grep '.*[1-9*]\.'$port' .*\* [ ]* 0 .* LISTEN') ;;
# #OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp6 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') /*?*/;;
*) l=$(netstat -an |grep -i 'stcp6 .*:'$port' .* listen') ;;
esac
[ \( \( $logic -ne 0 \) -a -n "$l" \) -o \
\( \( $logic -eq 0 \) -a -z "$l" \) ] && return 0
sleep 1
timeout=$((timeout-1))
done
$ECHO "!port $port timed out! \c" >&2
return 1
}
# we need this misleading function name for canonical reasons # we need this misleading function name for canonical reasons
waitunixport () { waitunixport () {
waitfile "$1" "$2" "$3" waitfile "$1" "$2" "$3"
@ -9174,6 +9238,7 @@ esac
PORT=$((PORT+1)) PORT=$((PORT+1))
N=$((N+1)) N=$((N+1))
# test the SOCKET-RECV address (with UDP4-SENDTO) # test the SOCKET-RECV address (with UDP4-SENDTO)
NAME=SOCKET_RECV NAME=SOCKET_RECV
case "$TESTS" in case "$TESTS" in
@ -9427,6 +9492,103 @@ PORT=$((PORT+1))
N=$((N+1)) N=$((N+1))
NAME=SCTP4STREAM
case "$TESTS" in
*%functions%*|*%ip4%*|*%ipapp%*|*%sctp%*|*%$NAME%*)
TEST="$NAME: echo via connection to SCTP V4 socket"
if ! testaddrs sctp ip4 >/dev/null || ! runsip4 >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}SCTP4 not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
elif [ "$UNAME" = Linux ] && ! grep ^sctp /proc/modules >/dev/null; then
# RHEL5 based systems became unusable when an sctp socket was created but
# module sctp not loaded
$PRINTF "test $F_n $TEST...${YELLOW}load sctp module!${NORMAL}\n" $N
numCANT=$((numCANT+1))
else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
tsl=$PORT
ts="127.0.0.1:$tsl"
da=$(date)
CMD1="$SOCAT $opts SCTP4-LISTEN:$tsl,reuseaddr PIPE"
CMD2="$SOCAT $opts stdin!!stdout SCTP4:$ts"
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
(echo "$da"; sleep 1) |$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
fi ;; # sctp
esac
PORT=$((PORT+1))
N=$((N+1))
NAME=SCTP6STREAM
case "$TESTS" in
*%functions%*|*%ip6%*|*%ipapp%*|*%sctp%*|*%$NAME%*)
TEST="$NAME: echo via connection to SCTP V6 socket"
if ! testaddrs sctp ip6 >/dev/null || ! runsip6 >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}SCTP6 not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
elif [ "$UNAME" = Linux ] && ! grep ^sctp /proc/modules >/dev/null; then
$PRINTF "test $F_n $TEST...${YELLOW}load sctp module!${NORMAL}\n" $N
numCANT=$((numCANT+1))
else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
tsl=$PORT
ts="[::1]:$tsl"
da=$(date)
CMD1="$SOCAT $opts SCTP6-listen:$tsl,reuseaddr PIPE"
CMD2="$SOCAT $opts stdin!!stdout SCTP6:$ts"
printf "test $F_n $TEST... " $N
$CMD1 >"$tf" 2>"${te}1" &
pid=$! # background process id
waitsctp6port $tsl 1
# SCTP does not seem to support half close, so we let it 1s to finish
(echo "$da"; sleep 1) |$CMD2 >>"$tf" 2>>"${te}2"
if [ $? -ne 0 ]; then
$PRINTF "$FAILED: $SOCAT:\n"
echo "$CMD1 &"
echo "$CMD2"
cat "$te"
numFAIL=$((numFAIL+1))
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED: diff:\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 $pid 2>/dev/null
fi ;; # sctp
esac
PORT=$((PORT+1))
N=$((N+1))
echo "summary: $((N-1)) tests; $numOK ok, $numFAIL failed, $numCANT could not be performed" echo "summary: $((N-1)) tests; $numOK ok, $numFAIL failed, $numCANT could not be performed"
if [ "$numFAIL" -gt 0 ]; then if [ "$numFAIL" -gt 0 ]; then

50
xio-sctp.c Normal file
View file

@ -0,0 +1,50 @@
/* source: xio-sctp.c */
/* Copyright Gerhard Rieger 2008 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for SCTP related functions and options */
#include "xiosysincludes.h"
#if WITH_SCTP
#include "xioopen.h"
#include "xio-listen.h"
#include "xio-ip4.h"
#include "xio-ipapp.h"
#include "xio-sctp.h"
/****** SCTP addresses ******/
#if WITH_IP4 || WITH_IP6
const struct addrdesc addr_sctp_connect = { "sctp-connect", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_SCTP|GROUP_CHILD|GROUP_RETRY, SOCK_STREAM, IPPROTO_SCTP, PF_UNSPEC HELP(":<host>:<port>") };
#if WITH_LISTEN
const struct addrdesc addr_sctp_listen = { "sctp-listen", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_SCTP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_STREAM, IPPROTO_SCTP, PF_UNSPEC HELP(":<port>") };
#endif
#endif
#if WITH_IP4
const struct addrdesc addr_sctp4_connect = { "sctp4-connect", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_SCTP|GROUP_CHILD|GROUP_RETRY, SOCK_STREAM, IPPROTO_SCTP, PF_INET HELP(":<host>:<port>") };
#if WITH_LISTEN
const struct addrdesc addr_sctp4_listen = { "sctp4-listen", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_SCTP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_STREAM, IPPROTO_SCTP, PF_INET HELP(":<port>") };
#endif
#endif /* WITH_IP4 */
#if WITH_IP6
const struct addrdesc addr_sctp6_connect = { "sctp6-connect", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_SCTP|GROUP_CHILD|GROUP_RETRY, SOCK_STREAM, IPPROTO_SCTP, PF_INET6 HELP(":<host>:<port>") };
#if WITH_LISTEN
const struct addrdesc addr_sctp6_listen = { "sctp6-listen", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_SCTP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_STREAM, IPPROTO_SCTP, PF_INET6 HELP(":<port>") };
#endif
#endif /* WITH_IP6 */
/****** SCTP address options ******/
#ifdef SCTP_NODELAY
const struct optdesc opt_sctp_nodelay = { "sctp-nodelay", "nodelay", OPT_SCTP_NODELAY, GROUP_IP_SCTP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SCTP, SCTP_NODELAY };
#endif
#ifdef SCTP_MAXSEG
const struct optdesc opt_sctp_maxseg = { "sctp-maxseg", "mss", OPT_SCTP_MAXSEG, GROUP_IP_SCTP, PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SCTP, SCTP_MAXSEG };
const struct optdesc opt_sctp_maxseg_late={"sctp-maxseg-late","mss-late",OPT_SCTP_MAXSEG_LATE,GROUP_IP_SCTP,PH_CONNECTED,TYPE_INT,OFUNC_SOCKOPT, SOL_SCTP, SCTP_MAXSEG};
#endif
#endif /* WITH_SCTP */

19
xio-sctp.h Normal file
View file

@ -0,0 +1,19 @@
/* source: xio-sctp.h */
/* Copyright Gerhard Rieger 2008 */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_sctp_h_included
#define __xio_sctp_h_included 1
extern const struct addrdesc addr_sctp_connect;
extern const struct addrdesc addr_sctp_listen;
extern const struct addrdesc addr_sctp4_connect;
extern const struct addrdesc addr_sctp4_listen;
extern const struct addrdesc addr_sctp6_connect;
extern const struct addrdesc addr_sctp6_listen;
extern const struct optdesc opt_sctp_nodelay;
extern const struct optdesc opt_sctp_maxseg;
extern const struct optdesc opt_sctp_maxseg_late;
#endif /* !defined(__xio_sctp_h_included) */

View file

@ -43,7 +43,7 @@ static const char *addressgroupnames[] = {
"TERMIOS", "RANGE", "PTY", "PARENT", "TERMIOS", "RANGE", "PTY", "PARENT",
"UNIX", "IP4", "IP6", "INTERFACE", "UNIX", "IP4", "IP6", "INTERFACE",
"UDP", "TCP", "SOCKS4", "OPENSSL", "UDP", "TCP", "SOCKS4", "OPENSSL",
"PROCESS", "APPL", "HTTP", "undef" "PROCESS", "APPL", "HTTP", "SCTP"
} ; } ;

View file

@ -28,6 +28,7 @@
#include "xio-ipapp.h" #include "xio-ipapp.h"
#include "xio-tcp.h" #include "xio-tcp.h"
#include "xio-udp.h" #include "xio-udp.h"
#include "xio-sctp.h"
#include "xio-socks.h" #include "xio-socks.h"
#include "xio-proxy.h" #include "xio-proxy.h"
#endif /* _WITH_SOCKET */ #endif /* _WITH_SOCKET */

View file

@ -135,6 +135,26 @@ const struct addrname addressnames[] = {
#if WITH_READLINE #if WITH_READLINE
{ "readline", &addr_readline }, { "readline", &addr_readline },
#endif #endif
#if (WITH_IP4 || WITH_IP6) && WITH_SCTP
{ "sctp", &addr_sctp_connect },
{ "sctp-connect", &addr_sctp_connect },
#if WITH_LISTEN
{ "sctp-l", &addr_sctp_listen },
{ "sctp-listen", &addr_sctp_listen },
#endif
{ "sctp4", &addr_sctp4_connect },
{ "sctp4-connect", &addr_sctp4_connect },
#if WITH_LISTEN
{ "sctp4-l", &addr_sctp4_listen },
{ "sctp4-listen", &addr_sctp4_listen },
#endif
{ "sctp6", &addr_sctp6_connect },
{ "sctp6-connect", &addr_sctp6_connect },
#if WITH_LISTEN
{ "sctp6-l", &addr_sctp6_listen },
{ "sctp6-listen", &addr_sctp6_listen },
#endif
#endif /* (WITH_IP4 || WITH_IP6) && WITH_SCTP */
#if WITH_GENERICSOCKET #if WITH_GENERICSOCKET
{ "sendto", &xioaddr_socket_sendto }, { "sendto", &xioaddr_socket_sendto },
#endif #endif

View file

@ -1,5 +1,5 @@
/* source: xioopen.h */ /* source: xioopen.h */
/* Copyright Gerhard Rieger 2001-2006 */ /* Copyright Gerhard Rieger 2001-2008 */
/* Published under the GNU General Public License V.2, see file COPYING */ /* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xioopen_h_included #ifndef __xioopen_h_included

View file

@ -82,6 +82,12 @@ bool xioopts_ignoregroups;
# define IF_TCP(a,b) # define IF_TCP(a,b)
#endif #endif
#if WITH_SCTP
# define IF_SCTP(a,b) {a,b},
#else
# define IF_SCTP(a,b)
#endif
#if WITH_SOCKS4 #if WITH_SOCKS4
# define IF_SOCKS4(a,b) {a,b}, # define IF_SOCKS4(a,b) {a,b},
#else #else
@ -1208,6 +1214,13 @@ const struct optname optionnames[] = {
IF_TCP ("sackena", &opt_tcp_sackena) IF_TCP ("sackena", &opt_tcp_sackena)
#endif #endif
IF_TERMIOS("sane", &opt_sane) IF_TERMIOS("sane", &opt_sane)
#ifdef SCTP_MAXSEG
IF_SCTP ("sctp-maxseg", &opt_sctp_maxseg)
IF_SCTP ("sctp-maxseg-late", &opt_sctp_maxseg_late)
#endif
#ifdef SCTP_NODELAY
IF_SCTP ("sctp-nodelay", &opt_sctp_nodelay)
#endif
#if WITH_EXT2 && defined(EXT2_SECRM_FL) #if WITH_EXT2 && defined(EXT2_SECRM_FL)
IF_ANY ("secrm", &opt_ext2_secrm) IF_ANY ("secrm", &opt_ext2_secrm)
#endif #endif

View file

@ -166,6 +166,7 @@ enum e_func {
#define GROUP_PROCESS 0x10000000 /* a process related option */ #define GROUP_PROCESS 0x10000000 /* a process related option */
#define GROUP_APPL 0x20000000 /* option handled by data loop */ #define GROUP_APPL 0x20000000 /* option handled by data loop */
#define GROUP_HTTP 0x40000000 /* any HTTP client */ #define GROUP_HTTP 0x40000000 /* any HTTP client */
#define GROUP_IP_SCTP 0x80000000
#define GROUP_ANY (GROUP_PROCESS|GROUP_APPL) #define GROUP_ANY (GROUP_PROCESS|GROUP_APPL)
#define GROUP_ALL 0xffffffff #define GROUP_ALL 0xffffffff
@ -568,6 +569,9 @@ enum e_optcode {
OPT_RES_USEVC, /* resolver(3) */ OPT_RES_USEVC, /* resolver(3) */
OPT_RETRY, OPT_RETRY,
OPT_SANE, /* termios */ OPT_SANE, /* termios */
OPT_SCTP_MAXSEG,
OPT_SCTP_MAXSEG_LATE,
OPT_SCTP_NODELAY,
OPT_SEEK32_CUR, OPT_SEEK32_CUR,
OPT_SEEK32_END, OPT_SEEK32_END,
OPT_SEEK32_SET, OPT_SEEK32_SET,