UDP-Lite (UDPlite) support

This commit is contained in:
Gerhard Rieger 2023-11-11 17:18:06 +01:00
parent a846b94e6c
commit 2cfc39e9e5
21 changed files with 833 additions and 71 deletions

10
CHANGES
View file

@ -179,6 +179,16 @@ Features:
DCCP6-LISTEN (DCCP6-L) DCCP6-LISTEN (DCCP6-L)
New option: dccp-set-ccid (ccid) New option: dccp-set-ccid (ccid)
Support for UDP-Lite protocol, new addresses:
UDPLITE-CONNECT
UDPLITE-LISTEN
UDPLITE-DATAGRAM
UDPLITE-RECV
UDPLITE-RECVFROM
UDPLITE-SENDTO
All these are also available in UDPLITE4-* and UDPLITE6-* form;
options udplite-recv-cscov and udplite-send-cscov.
Corrections: Corrections:
When a sub process (EXEC, SYSTEM) terminated with exit code other than When a sub process (EXEC, SYSTEM) terminated with exit code other than
0, its last sent data might have been lost depending on timing of read/ 0, its last sent data might have been lost depending on timing of read/

View file

@ -50,7 +50,7 @@ XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \
xio-socket.c xio-interface.c xio-listen.c xio-unix.c xio-vsock.c \ xio-socket.c xio-interface.c xio-listen.c xio-unix.c xio-vsock.c \
xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \ xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \
xio-sctp.c xio-dccp.c xio-rawip.c xio-posixmq.c \ xio-sctp.c xio-dccp.c xio-rawip.c xio-posixmq.c \
xio-socks.c xio-socks5.c xio-proxy.c xio-udp.c \ xio-socks.c xio-socks5.c xio-proxy.c xio-udp.c xio-udplite.c \
xio-progcall.c xio-exec.c xio-system.c xio-shell.c \ xio-progcall.c xio-exec.c xio-system.c xio-shell.c \
xio-termios.c xio-readline.c \ xio-termios.c xio-readline.c \
xio-pty.c xio-openssl.c xio-streams.c xio-namespaces.c \ xio-pty.c xio-openssl.c xio-streams.c xio-namespaces.c \
@ -68,7 +68,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-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h \
xio-socketpair.h xio-socket.h xio-interface.h xio-listen.h xio-unix.h xio-vsock.h \ xio-socketpair.h xio-socket.h xio-interface.h xio-listen.h xio-unix.h xio-vsock.h \
xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h xio-posixmq.h \ xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h xio-posixmq.h \
xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h xio-dccp.h \ xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h xio-dccp.h xio-udplite.h \
xio-socks.h xio-socks5.h xio-proxy.h xio-progcall.h xio-exec.h \ xio-socks.h xio-socks5.h xio-proxy.h xio-progcall.h xio-exec.h \
xio-system.h xio-shell.h xio-termios.h xio-readline.h \ xio-system.h xio-shell.h xio-termios.h xio-readline.h \
xio-pty.h xio-openssl.h xio-streams.h xio-namespaces.h \ xio-pty.h xio-openssl.h xio-streams.h xio-namespaces.h \

View file

@ -712,6 +712,7 @@
#undef WITH_INTERFACE #undef WITH_INTERFACE
#undef WITH_TCP #undef WITH_TCP
#undef WITH_UDP #undef WITH_UDP
#undef WITH_UDPLITE
#undef WITH_SCTP #undef WITH_SCTP
#undef WITH_DCCP #undef WITH_DCCP
#undef WITH_LISTEN #undef WITH_LISTEN

View file

@ -345,6 +345,25 @@ 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 UDP-Lite support)
AC_ARG_ENABLE(udplite, [ --disable-udplite disable UDP-Lite support],
[case "$enableval" in
no) AC_MSG_RESULT(no); WITH_UDPLITE= ;;
*) AC_MSG_RESULT(yes); WITH_UDPLITE=1 ;;
esac],
[AC_MSG_RESULT(yes); WITH_UDPLITE=1 ])
if test -n "$WITH_UDPLITE"; then
AC_MSG_CHECKING(for IPPROTO_UDPLITE)
AC_TRY_COMPILE([#include <sys/types.h>
#include <netinet/in.h>],
[IPPROTO_UDPLITE;],
[ AC_MSG_RESULT(yes); WITH_UDPLITE=1],
[ AC_MSG_RESULT(no); WITH_UDPLITE=])
if test "$WITH_UDPLITE"; then
AC_DEFINE(WITH_UDPLITE)
fi
fi
AC_MSG_CHECKING(whether to include SCTP support) AC_MSG_CHECKING(whether to include SCTP support)
AC_ARG_ENABLE(sctp, [ --disable-sctp disable SCTP support], AC_ARG_ENABLE(sctp, [ --disable-sctp disable SCTP support],
[case "$enableval" in [case "$enableval" in

View file

@ -927,6 +927,7 @@ label(ADDRESS_SCTP6_LISTEN)dit(bf(tt(SCTP6-LISTEN:<port>)))
Like link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN), but only supports IPv6 Like link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN), but only supports IPv6
protocol.nl() 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() 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 NOEXPAND(socket(2))) and connects to the remote-address. and tt(SOCK_STREAM) (see man NOEXPAND(socket(2))) and connects to the remote-address.
@ -1301,6 +1302,8 @@ label(ADDRESS_TUN)dit(bf(tt(TUN[:<if-addr>/<bits>])))
link(netns)(OPTION_NETNS)nl() link(netns)(OPTION_NETNS)nl()
See also: See also:
link(ip-recv)(ADDRESS_IP_RECV) link(ip-recv)(ADDRESS_IP_RECV)
label(ADDRESSES_UDP)
label(ADDRESS_UDP_CONNECT)dit(bf(tt(UDP:<host>:<port>))) label(ADDRESS_UDP_CONNECT)dit(bf(tt(UDP:<host>:<port>)))
Connects to <port> [link(UDP service)(TYPE_UDP_SERVICE)] on Connects to <port> [link(UDP service)(TYPE_UDP_SERVICE)] on
<host> [link(IP address)(TYPE_IP_ADDRESS)] using UDP/IP version 4 or 6 <host> [link(IP address)(TYPE_IP_ADDRESS)] using UDP/IP version 4 or 6
@ -1504,6 +1507,28 @@ label(ADDRESS_UDP6_RECV)dit(bf(tt(UDP6-RECV:<port>)))
Like link(UDP-RECV)(ADDRESS_UDP_RECV), but only supports IPv6 protocol.nl() Like link(UDP-RECV)(ADDRESS_UDP_RECV), 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)
dit(bf(tt(UDPLITE-CONNECT:<host>:<port>)))
dit(bf(tt(UDPLITE4-CONNECT:<host>:<port>)))
dit(bf(tt(UDPLITE6-CONNECT:<host>:<port>)))
dit(bf(tt(UDPLITE-DATAGRAM:<address>:<port>)))
dit(bf(tt(UDPLITE4-DATAGRAM:<address>:<port>)))
dit(bf(tt(UDPLITE6-DATAGRAM:<address>:<port>)))
dit(bf(tt(UDPLITE-LISTEN:<port>)))
dit(bf(tt(UDPLITE4-LISTEN:<port>)))
dit(bf(tt(UDPLITE6-LISTEN:<port>)))
dit(bf(tt(UDPLITE-SENDTO:<host>:<port>)))
dit(bf(tt(UDPLITE4-SENDTO:<host>:<port>)))
dit(bf(tt(UDPLITE6-SENDTO:<host>:<port>)))
dit(bf(tt(UDPLITE-RECVFROM:<port>)))
dit(bf(tt(UDPLITE4-RECVFROM:<port>)))
dit(bf(tt(UDPLITE6-RECVFROM:<port>)))
dit(bf(tt(UDPLITE-RECV:<port>)))
dit(bf(tt(UDPLITE4-RECV:<port>)))
dit(bf(tt(UDPLITE6-RECV:<port>)))
The UDPLITE addresses are almost identical to the related link(UDP addresses)(ADDRESSES_UDP)
but they use UDP-Lite protocol and have the additional link(UDPLITE option
group)(GROUP_UDPLITE).nl()
label(ADDRESS_UNIX_CONNECT)dit(bf(tt(UNIX-CONNECT:<filename>))) label(ADDRESS_UNIX_CONNECT)dit(bf(tt(UNIX-CONNECT:<filename>)))
Connects to link(<filename>)(TYPE_FILENAME) assuming it is a unixdomain() Connects to link(<filename>)(TYPE_FILENAME) assuming it is a unixdomain()
socket. socket.
@ -2700,6 +2725,21 @@ enddit()
startdit()enddit()nl() startdit()enddit()nl()
label(GROUP_UDPLITE)em(bf(UDPLITE option group))
These options may be applied to UDPLITE addresses:
startdit()
label(OPTION_UDPLITE_SEND_CSCOV)dit(bf(tt(udplite-send-cscov)))
Sets the number of bytes for which the checksum is calculated and sent
("checksum coverage").
label(OPTION_UDPLITE_RECV_CSCOV)dit(bf(tt(udplite-recv-cscov)))
Sets the number of bytes for which the checksum is checked ("checksum
coverage").
enddit()
startdit()enddit()nl()
label(GROUP_SCTP)em(bf(SCTP option group)) label(GROUP_SCTP)em(bf(SCTP option group))
These options may be applied to SCTP stream sockets. These options may be applied to SCTP stream sockets.
@ -2726,13 +2766,14 @@ enddit()
startdit()enddit()nl() startdit()enddit()nl()
em(bf(UDP, TCP, SCTP, and DCCP option group)) label(GROUP_IPAPP)em(bf(UDP, TCP, SCTP, DCCP, and UDPLITE option group))
Here we find options that are related to the network port mechanism and thus Here we find options that are related to the network port mechanism and thus
can be used with UDP, TCP, SCTP, and DCCP client and server addresses. can be used with UDP, TCP, SCTP, DCCP, and UDP-Lite 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) connections, it sets the source
link(<port>)(TYPE_PORT) using an extra code(bind()) call. link(<port>)(TYPE_PORT) using an extra code(bind()) call.
With TCP or UDP listen addresses, socat immediately shuts down the With TCP or UDP listen addresses, socat immediately shuts down the
connection if the client does not use this sourceport. UDP-RECV, connection if the client does not use this sourceport. UDP-RECV,
@ -2740,7 +2781,7 @@ label(OPTION_SOURCEPORT)dit(bf(tt(sourceport=<port>)))
it does not match. it does not match.
(link(example)(EXAMPLE_OPTION_SOURCEPORT)). (link(example)(EXAMPLE_OPTION_SOURCEPORT)).
label(OPTION_LOWPORT)dit(bf(tt(lowport))) label(OPTION_LOWPORT)dit(bf(tt(lowport)))
Outgoing (client) TCP and UDP connections with this option use Outgoing (client) connections with this option use
an unused random source port between 640 and 1023 incl. On UNIX class operating an unused random source port between 640 and 1023 incl. On UNIX class operating
systems, this requires root privilege, and thus indicates that the systems, this requires root privilege, and thus indicates that the
client process is authorized by local root. client process is authorized by local root.

View file

@ -126,11 +126,14 @@ int procan_cdefs(FILE *outfile) {
#ifdef IPPROTO_UDP #ifdef IPPROTO_UDP
fprintf(outfile, "#define IPPROTO_UDP %d\n", IPPROTO_UDP); fprintf(outfile, "#define IPPROTO_UDP %d\n", IPPROTO_UDP);
#endif #endif
#ifdef IPPROTO_DCCP
fprintf(outfile, "#define IPPROTO_DCCP %d\n", IPPROTO_DCCP);
#endif
#ifdef IPPROTO_SCTP #ifdef IPPROTO_SCTP
fprintf(outfile, "#define IPPROTO_SCTP %d\n", IPPROTO_SCTP); fprintf(outfile, "#define IPPROTO_SCTP %d\n", IPPROTO_SCTP);
#endif #endif
#ifdef IPPROTO_DCCP #ifdef IPPROTO_UDPLITE
fprintf(outfile, "#define IPPROTO_DCCP %d\n", IPPROTO_DCCP); fprintf(outfile, "#define IPPROTO_UDPLITE %d\n", IPPROTO_UDPLITE);
#endif #endif
#ifdef SOL_SOCKET #ifdef SOL_SOCKET
fprintf(outfile, "#define SOL_SOCKET 0x%x\n", SOL_SOCKET); fprintf(outfile, "#define SOL_SOCKET 0x%x\n", SOL_SOCKET);

View file

@ -604,6 +604,11 @@ void socat_version(FILE *fd) {
#else #else
fputs(" #undef WITH_DCCP\n", fd); fputs(" #undef WITH_DCCP\n", fd);
#endif #endif
#ifdef WITH_UDPLITE
fprintf(fd, " #define WITH_UDPLITE %d\n", WITH_UDPLITE);
#else
fputs(" #undef WITH_UDPLITE\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

570
test.sh
View file

@ -607,6 +607,10 @@ case "$TESTS" in
$ECHO "testing if address array is sorted...\c" $ECHO "testing if address array is sorted...\c"
TF="$TD/socat-q" TF="$TD/socat-q"
IFS="$($ECHO ' \n\t')" IFS="$($ECHO ' \n\t')"
if ! $SOCAT -hhh >/dev/null; then
echo "Failed: $SOCAT -hhh" >&2
exit -1
fi
$SOCAT -hhh |sed -n '/^ address-head:/,/^ opts:/ p' |grep -v -e "^ address-head:" -e "^ opts:" |sed -e 's/^[[:space:]]*//' -e 's/[: ].*//' |grep -v '^<' >"$TF" $SOCAT -hhh |sed -n '/^ address-head:/,/^ opts:/ p' |grep -v -e "^ address-head:" -e "^ opts:" |sed -e 's/^[[:space:]]*//' -e 's/[: ].*//' |grep -v '^<' >"$TF"
$SOCAT -hhh |sed -n '/^ address-head:/,/^ opts:/ p' |grep -v -e "^ address-head:" -e "^ opts:" |sed -e 's/^[[:space:]]*//' -e 's/[: ].*//' |grep -v '^<' |LC_ALL=C sort |diff "$TF" - >"$TF-diff" $SOCAT -hhh |sed -n '/^ address-head:/,/^ opts:/ p' |grep -v -e "^ address-head:" -e "^ opts:" |sed -e 's/^[[:space:]]*//' -e 's/[: ].*//' |grep -v '^<' |LC_ALL=C sort |diff "$TF" - >"$TF-diff"
if [ -s "$TF-diff" ]; then if [ -s "$TF-diff" ]; then
@ -994,6 +998,20 @@ runsdccp6 () {
return 0; return 0;
} }
# check if UDPLITE on IPv4 is available on host
runsudplite4 () {
runsip4 >/dev/null || { echo UDPLITE4; return 1; }
$SOCAT -u -T 0.001 /dev/null UDPLITE4-SENDTO:$LOCALHOST4:0 2>/dev/null || return 1;
return 0;
}
# check if UDPLITE on IPv6 is available on host
runsudplite6 () {
runsip6 >/dev/null || { echo UDPLITE6; return 1; }
$SOCAT -u -T 0.001 /dev/null UDPLITE6-SENDTO:$LOCALHOST6:0 2>/dev/null || return 1;
return 0;
}
# check if UNIX domain sockets work # check if UNIX domain sockets work
runsunix () { runsunix () {
# for now... # for now...
@ -1415,6 +1433,51 @@ waitsctp4port () {
return 1 return 1
} }
# wait until a UDPLITE4 port is ready
waitudplite4port () {
local port="$1"
local logic="$2" # 0..wait until free; 1..wait until listening
local timeout="$3"
local l
local vx=+; case $- in *vx*) set +vx; vx=-; esac # no tracing here
[ "$logic" ] || logic=1
[ "$timeout" ] || timeout=5
while [ $timeout -gt 0 ]; do
case "$UNAME" in
Linux) #if [ "$SS" ]; then
#l=$($SS -4 -l -n -u |grep "^UNCONN .*:$port\>")
#else
l=$(netstat -a -n -U -l |grep '^udpl .* .*[0-9*]:'$port' [ ]*0\.0\.0\.0:\*')
#fi
;;
FreeBSD) l=$(netstat -an |egrep '^udpl46? .*[0-9*]\.'$port' .* \*\.\*') ;;
NetBSD) l=$(netstat -an |grep '^udpl .*[0-9*]\.'$port' [ ]* \*\.\*') ;;
OpenBSD) l=$(netstat -an |grep '^udpl .*[0-9*]\.'$port' [ ]* \*\.\*') ;;
#Darwin) case "$(uname -r)" in
# [1-5]*) l=$(netstat -an |grep '^udp.* .*[0-9*]\.'$port' .* \*\.\*') ;;
# *) l=$(netstat -an |grep '^udp4.* .*[0-9*]\.'$port' .* \*\.\* .*') ;;
# esac ;;
#AIX) l=$(netstat -an |grep '^udp[4 ] 0 0 .*[*0-9]\.'$port' .* \*\.\*[ ]*$') ;;
#SunOS) l=$(netstat -an -f inet -P udp |grep '.*[1-9*]\.'$port' [ ]*Idle') ;;
#HP-UX) l=$(netstat -an |grep '^udp 0 0 .*[0-9*]\.'$port' .* \*\.\* ') ;;
#OSF1) l=$(/usr/sbin/netstat -an |grep '^udp 0 0 .*[0-9*]\.'$port' [ ]*\*\.\*') ;;
#DragonFly) l=$(netstat -an |grep '^udp4 .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]*') ;;
*) l=$(netstat -an |grep -i 'udp .*[0-9*][:.]'$port' ') ;;
esac
if [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \
\( \( $logic -eq 0 \) -a -z "$l" \) ]; then
set ${vx}vx
return 0
fi
sleep 1
timeout=$((timeout-1))
done
$ECHO "!port $port timed out! \c" >&2
set ${vx}vx
return 1
}
# check if a TCP6 port is in use # check if a TCP6 port is in use
# exits with 0 when it is not used # exits with 0 when it is not used
checktcp6port () { checktcp6port () {
@ -1557,6 +1620,48 @@ waitsctp6port () {
return 1 return 1
} }
# wait until a UDPLITE6 port is ready
waitudplite6port () {
local port="$1"
local logic="$2" # 0..wait until free; 1..wait until listening
local timeout="$3"
local l
local vx=+; case $- in *vx*) set +vx; vx=-; esac # no tracing here
[ "$logic" ] || logic=1
[ "$timeout" ] || timeout=5
while [ $timeout -gt 0 ]; do
case "$UNAME" in
Linux) #if [ "$SS" ]; then
#l=$($SS -6 -u -l -n |grep "^UNCONN .*:$port\>")
#else
l=$(netstat -an |grep -E '^udpl6? .* .*[0-9*:%]:'$port' [ ]*:::\*')
#fi
;;
FreeBSD) l=$(netstat -an |egrep '^udpl(6|46) .*[0-9*]\.'$port' .* \*\.\*') ;;
NetBSD) l=$(netstat -an |grep '^udpl6 .* \*\.'$port' [ ]* \*\.\*') ;;
OpenBSD) l=$(netstat -an |grep '^udpl6 .*[0-9*]\.'$port' [ ]* \*\.\*') ;;
Darwin) l=$(netstat -an |egrep '^udpl4?6 +[0-9]+ +[0-9]+ +[0-9a-z:%*]+\.'$port' +[0-9a-z:%*.]+') ;;
#AIX) l=$(netstat -an |grep '^udp[6 ] 0 0 .*[*0-9]\.'$port' .* \*\.\*[ ]*$') ;;
#SunOS) l=$(netstat -an -f inet6 -P udp |grep '.*[1-9*]\.'$port' [ ]*Idle') ;;
#HP-UX) l=$(netstat -an |grep '^udp 0 0 .*[0-9*]\.'$port' ') ;;
#OSF1) l=$(/usr/sbin/netstat -an |grep '^udp6 0 0 .*[0-9*]\.'$port' [ ]*\*\.\*') ;;
#DragonFly) l=$(netstat -ant |grep '^udp6 .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]*') ;;
*) l=$(netstat -an |grep -i 'udp .*[0-9*][:.]'$port' ') ;;
esac
if [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \
\( \( $logic -eq 0 \) -a -z "$l" \) ]; then
set ${vx}vx
return 0
fi
sleep 1
timeout=$((timeout-1))
done
$ECHO "!port $port timed out! \c" >&2
set ${vx}vx
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"
@ -9897,14 +10002,14 @@ IP6 IP6 [::1] PROTO ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS
# test: setting of environment variables that describe a stream socket # test: setting of environment variables that describe a stream socket
# connection: SOCAT_SOCKADDR, SOCAT_PEERADDR; and SOCAT_SOCKPORT, # connection: SOCAT_SOCKADDR, SOCAT_PEERADDR; and SOCAT_SOCKPORT,
# SOCAT_PEERPORT when applicable # SOCAT_PEERPORT when applicable
while read KEYW FEAT TEST_SOCKADDR TEST_PEERADDR PORTMETHOD; do while read KEYW FEAT SEL TEST_SOCKADDR TEST_PEERADDR PORTMETHOD; do
if [ -z "$KEYW" ] || [[ "$KEYW" == \#* ]]; then continue; fi if [ -z "$KEYW" ] || [[ "$KEYW" == \#* ]]; then continue; fi
# #
protov="$(echo "$KEYW" |tr A-Z a-z)" protov="$(echo "$KEYW" |tr A-Z a-z)"
proto="${protov%%[0-9]}" proto="${protov%%[0-9]}"
NAME=${KEYW}LISTENENV NAME=${KEYW}LISTENENV
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$proto%*|*%$protov%*|*%envvar%*|*%listen%*|*%$NAME%*) *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%$SEL%*|*%$proto%*|*%$protov%*|*%envvar%*|*%listen%*|*%$NAME%*)
TEST="$NAME: $KEYW-LISTEN sets environment variables with socket addresses" TEST="$NAME: $KEYW-LISTEN sets environment variables with socket addresses"
# have a server accepting a connection and invoking some shell code. The shell # have a server accepting a connection and invoking some shell code. The shell
# code extracts and prints the SOCAT related environment vars. # code extracts and prints the SOCAT related environment vars.
@ -9993,19 +10098,19 @@ N=$((N+1))
#set +xv #set +xv
# #
done <<<" done <<<"
TCP4 TCP 127.0.0.1 $SECONDADDR PORT TCP4 TCP tcp 127.0.0.1 $SECONDADDR PORT
TCP6 IP6 [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] PORT TCP6 IP6 tcp [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] PORT
UDP6 IP6 [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] PORT UDP6 IP6 udp [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] PORT
SCTP4 SCTP 127.0.0.1 $SECONDADDR PORT SCTP4 SCTP sctp 127.0.0.1 $SECONDADDR PORT
SCTP6 SCTP [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] PORT SCTP6 SCTP sctp [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] PORT
UNIX UNIX $td/test\$N.server $td/test\$N.client , UNIX UNIX unix $td/test\$N.server $td/test\$N.client ,
" "
# this one fails due to weakness in socats UDP4-LISTEN implementation: # this one fails due to weakness in socats UDP4-LISTEN implementation:
#UDP4 $LOCALHOST $SECONDADDR $((PORT+4)) $((PORT+5)) #UDP4 $LOCALHOST $SECONDADDR $((PORT+4)) $((PORT+5))
# test: environment variables from ancillary message # test: environment variables from ancillary message
while read PF KEYW ADDR IPPORT SCM_ENABLE SCM_RECV SCM_ENVNAME ROOT SCM_VALUE while read PF KEYW SEL ADDR IPPORT SCM_ENABLE SCM_RECV SCM_ENVNAME ROOT SCM_VALUE
do do
if [ -z "$PF" ] || [[ "$PF" == \#* ]]; then continue; fi if [ -z "$PF" ] || [[ "$PF" == \#* ]]; then continue; fi
# #
@ -10013,7 +10118,7 @@ pf="$(echo "$PF" |tr A-Z a-z)"
proto="$(echo "$KEYW" |tr A-Z a-z)" proto="$(echo "$KEYW" |tr A-Z a-z)"
NAME=${KEYW}ENV_$SCM_ENVNAME NAME=${KEYW}ENV_$SCM_ENVNAME
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%socket%*|*%$pf%*|*%dgram%*|*%udp%*|*%$proto%*|*%recv%*|*%ancillary%*|*%envvar%*|*%$ROOT%*|*%$NAME%*) *%$N%*|*%functions%*|*%socket%*|*%$pf%*|*%dgram%*|*%$SEL%*|*%$proto%*|*%recv%*|*%ancillary%*|*%envvar%*|*%$ROOT%*|*%$NAME%*)
#set -vx #set -vx
TEST="$NAME: $KEYW ancillary message sets env SOCAT_$SCM_ENVNAME" TEST="$NAME: $KEYW ancillary message sets env SOCAT_$SCM_ENVNAME"
# idea: start a socat process with *-RECVFROM:..,... , ev. with ancillary # idea: start a socat process with *-RECVFROM:..,... , ev. with ancillary
@ -10110,30 +10215,30 @@ esac
N=$((N+1)) N=$((N+1))
# #
done <<<" done <<<"
IP4 UDP4 127.0.0.1 PORT ip-options=x01000000 ip-recvopts IP_OPTIONS user x01000000 IP4 UDP4 udp 127.0.0.1 PORT ip-options=x01000000 ip-recvopts IP_OPTIONS user x01000000
IP4 UDP4 127.0.0.1 PORT , so-timestamp TIMESTAMP user timestamp IP4 UDP4 udp 127.0.0.1 PORT , so-timestamp TIMESTAMP user timestamp
IP4 UDP4 127.0.0.1 PORT ip-ttl=53 ip-recvttl IP_TTL user 53 IP4 UDP4 udp 127.0.0.1 PORT ip-ttl=53 ip-recvttl IP_TTL user 53
IP4 UDP4 127.0.0.1 PORT ip-tos=7 ip-recvtos IP_TOS user 7 IP4 UDP4 udp 127.0.0.1 PORT ip-tos=7 ip-recvtos IP_TOS user 7
IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_LOCADDR user 127.0.0.1 IP4 UDP4 udp 127.0.0.1 PORT , ip-pktinfo IP_LOCADDR user 127.0.0.1
IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_DSTADDR user 127.0.0.1 IP4 UDP4 udp 127.0.0.1 PORT , ip-pktinfo IP_DSTADDR user 127.0.0.1
IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_IF user lo IP4 UDP4 udp 127.0.0.1 PORT , ip-pktinfo IP_IF user lo
IP4 UDP4 127.0.0.1 PORT , ip-recvif IP_IF user lo0 IP4 UDP4 udp 127.0.0.1 PORT , ip-recvif IP_IF user lo0
IP4 UDP4 127.0.0.1 PORT , ip-recvdstaddr IP_DSTADDR user 127.0.0.1 IP4 UDP4 udp 127.0.0.1 PORT , ip-recvdstaddr IP_DSTADDR user 127.0.0.1
IP4 IP4 127.0.0.1 PROTO ip-options=x01000000 ip-recvopts IP_OPTIONS root x01000000 IP4 IP4 rawip 127.0.0.1 PROTO ip-options=x01000000 ip-recvopts IP_OPTIONS root x01000000
IP4 IP4 127.0.0.1 PROTO , so-timestamp TIMESTAMP root timestamp IP4 IP4 rawip 127.0.0.1 PROTO , so-timestamp TIMESTAMP root timestamp
IP4 IP4 127.0.0.1 PROTO ip-ttl=53 ip-recvttl IP_TTL root 53 IP4 IP4 rawip 127.0.0.1 PROTO ip-ttl=53 ip-recvttl IP_TTL root 53
IP4 IP4 127.0.0.1 PROTO ip-tos=7 ip-recvtos IP_TOS root 7 IP4 IP4 rawip 127.0.0.1 PROTO ip-tos=7 ip-recvtos IP_TOS root 7
IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_LOCADDR root 127.0.0.1 IP4 IP4 rawip 127.0.0.1 PROTO , ip-pktinfo IP_LOCADDR root 127.0.0.1
IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_DSTADDR root 127.0.0.1 IP4 IP4 rawip 127.0.0.1 PROTO , ip-pktinfo IP_DSTADDR root 127.0.0.1
IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_IF root lo IP4 IP4 rawip 127.0.0.1 PROTO , ip-pktinfo IP_IF root lo
IP4 IP4 127.0.0.1 PROTO , ip-recvif IP_IF root lo0 IP4 IP4 rawip 127.0.0.1 PROTO , ip-recvif IP_IF root lo0
IP4 IP4 127.0.0.1 PROTO , ip-recvdstaddr IP_DSTADDR root 127.0.0.1 IP4 IP4 rawip 127.0.0.1 PROTO , ip-recvdstaddr IP_DSTADDR root 127.0.0.1
IP6 UDP6 [::1] PORT , ipv6-recvpktinfo IPV6_DSTADDR user [[]0000:0000:0000:0000:0000:0000:0000:0001[]] IP6 UDP6 udp [::1] PORT , ipv6-recvpktinfo IPV6_DSTADDR user [[]0000:0000:0000:0000:0000:0000:0000:0001[]]
IP6 UDP6 [::1] PORT ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT user 35 IP6 UDP6 udp [::1] PORT ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT user 35
IP6 UDP6 [::1] PORT ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS user x000000aa IP6 UDP6 udp [::1] PORT ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS user x000000aa
IP6 IP6 [::1] PROTO , ipv6-recvpktinfo IPV6_DSTADDR root [[]0000:0000:0000:0000:0000:0000:0000:0001[]] IP6 IP6 rawip [::1] PROTO , ipv6-recvpktinfo IPV6_DSTADDR root [[]0000:0000:0000:0000:0000:0000:0000:0001[]]
IP6 IP6 [::1] PROTO ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT root 35 IP6 IP6 rawip [::1] PROTO ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT root 35
IP6 IP6 [::1] PROTO ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS root x000000aa IP6 IP6 rawip [::1] PROTO ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS root x000000aa
#UNIX UNIX $td/test\$N.server - , so-timestamp TIMESTAMP user timestamp #UNIX UNIX $td/test\$N.server - , so-timestamp TIMESTAMP user timestamp
" "
@ -11471,7 +11576,8 @@ UNIX unix $td/test\$N.server -
# care for timing, understand what you want :-) # care for timing, understand what you want :-)
while read KEYW FEAT ADDR IPPORT SHUT; do # test the max-children option on pseudo connected sockets
while read KEYW FEAT SEL ADDR IPPORT SHUT; do
if [ -z "$KEYW" ] || [[ "$KEYW" == \#* ]]; then continue; fi if [ -z "$KEYW" ] || [[ "$KEYW" == \#* ]]; then continue; fi
RUNS=$(tolower $KEYW) RUNS=$(tolower $KEYW)
PROTO=$KEYW PROTO=$KEYW
@ -11479,7 +11585,7 @@ proto="$(echo "$PROTO" |tr A-Z a-z)"
# test the max-children option on pseudo connected sockets # test the max-children option on pseudo connected sockets
NAME=${KEYW}MAXCHILDREN NAME=${KEYW}MAXCHILDREN
case "$TESTS" in case "$TESTS" in
*%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%socket%*|*%listen%*|*%$NAME%*) *%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%$SEL%*|*%socket%*|*%listen%*|*%$NAME%*)
TEST="$NAME: max-children option" TEST="$NAME: max-children option"
# start a listen process with max-children=1; connect with a client, let it # start a listen process with max-children=1; connect with a client, let it
# send data and then sleep; connect with second client that wants to send # send data and then sleep; connect with second client that wants to send
@ -11546,8 +11652,8 @@ fi # NUMCOND
esac esac
N=$((N+1)) N=$((N+1))
done <<<" done <<<"
UDP4 UDP 127.0.0.1 PORT shut-null UDP4 UDP udp 127.0.0.1 PORT shut-null
UDP6 UDP [::1] PORT shut-null UDP6 UDP udp [::1] PORT shut-null
" "
# debugging this hanging test was difficult - following lessons learned: # debugging this hanging test was difficult - following lessons learned:
# kill <parent> had no effect when child process existed # kill <parent> had no effect when child process existed
@ -18205,6 +18311,394 @@ esac
N=$((N+1)) N=$((N+1))
NAME=UDPLITE4STREAM
case "$TESTS" in
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udplite%*|*%$NAME%*)
TEST="$NAME: echo via connection to UDP-Lite V4 socket"
if ! eval $NUMCOND; then :;
# Remove unneeded checks, adapt lists of the remaining ones
elif ! cond=$(checkconds \
"" \
"" \
"" \
"IP4 UDPLITE LISTEN STDIO PIPE" \
"UDPLITE4-LISTEN PIPE STDIO UDPLITE4" \
"so-reuseaddr" \
"udplite4" ); then
$PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
namesCANT="$namesCANT $NAME"
else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
tsl=$PORT
ts="$LOCALHOST:$tsl"
da="test$N $(date) $RANDOM"
CMD1="$TRACE $SOCAT $opts UDPLITE4-LISTEN:$tsl,$REUSEADDR PIPE"
CMD2="$TRACE $SOCAT $opts - UDPLITE4:$ts"
printf "test $F_n $TEST... " $N
$CMD1 >"$tf" 2>"${te}1" &
pid1=$!
waitudplite4port $tsl 1
echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
rc2=$?
kill $pid1 2>/dev/null; wait
if [ $rc2 -ne 0 ]; then
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
echo "$CMD1 &"
cat "${te}1" >&2
echo "$CMD2"
cat "${te}2" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED (diff)\n"
echo "$CMD1 &" >&2
cat "${te}1"
echo "$CMD2" >&2
cat "${te}2" >&2
echo "// diff:" >&2
cat "$tdiff" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
namesFAIL="$namesFAIL $NAME"
else
$PRINTF "$OK\n"
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
numOK=$((numOK+1))
fi
fi ;; # NUMCOND
esac
PORT=$((PORT+1))
N=$((N+1))
NAME=UDPLITE4STREAM
case "$TESTS" in
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udplite%*|*%$NAME%*)
TEST="$NAME: echo via connection to UDP-Lite V4 socket"
if ! eval $NUMCOND; then :;
# Remove unneeded checks, adapt lists of the remaining ones
elif ! cond=$(checkconds \
"" \
"" \
"" \
"IP4 UDPLITE LISTEN STDIO PIPE" \
"UDPLITE4-LISTEN PIPE STDIO UDPLITE4" \
"so-reuseaddr" \
"udplite4" ); then
$PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
namesCANT="$namesCANT $NAME"
else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
tsl=$PORT
ts="$LOCALHOST:$tsl"
da="test$N $(date) $RANDOM"
CMD1="$TRACE $SOCAT $opts UDPLITE4-LISTEN:$tsl,$REUSEADDR PIPE"
CMD2="$TRACE $SOCAT $opts - UDPLITE4:$ts"
printf "test $F_n $TEST... " $N
$CMD1 >"$tf" 2>"${te}1" &
pid1=$!
waitudplite4port $tsl 1
echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
rc2=$?
kill $pid1 2>/dev/null; wait
if [ $rc2 -ne 0 ]; then
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
echo "$CMD1 &"
cat "${te}1" >&2
echo "$CMD2"
cat "${te}2" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED (diff)\n"
echo "$CMD1 &" >&2
cat "${te}1"
echo "$CMD2" >&2
cat "${te}2" >&2
echo "// diff:" >&2
cat "$tdiff" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
namesFAIL="$namesFAIL $NAME"
else
$PRINTF "$OK\n"
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
numOK=$((numOK+1))
fi
fi ;; # NUMCOND
esac
PORT=$((PORT+1))
N=$((N+1))
NAME=UDPLITE4STREAM
case "$TESTS" in
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udplite%*|*%$NAME%*)
TEST="$NAME: echo via connection to UDP-Lite V4 socket"
if ! eval $NUMCOND; then :;
# Remove unneeded checks, adapt lists of the remaining ones
elif ! cond=$(checkconds \
"" \
"" \
"" \
"IP4 UDPLITE LISTEN STDIO PIPE" \
"UDPLITE4-LISTEN PIPE STDIO UDPLITE4" \
"so-reuseaddr" \
"udplite4" ); then
$PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
namesCANT="$namesCANT $NAME"
else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
tsl=$PORT
ts="$LOCALHOST:$tsl"
da="test$N $(date) $RANDOM"
CMD1="$TRACE $SOCAT $opts UDPLITE4-LISTEN:$tsl,$REUSEADDR PIPE"
CMD2="$TRACE $SOCAT $opts - UDPLITE4:$ts"
printf "test $F_n $TEST... " $N
$CMD1 >"$tf" 2>"${te}1" &
pid1=$!
waitudplite4port $tsl 1
echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
rc2=$?
kill $pid1 2>/dev/null; wait
if [ $rc2 -ne 0 ]; then
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
echo "$CMD1 &"
cat "${te}1" >&2
echo "$CMD2"
cat "${te}2" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED (diff)\n"
echo "$CMD1 &" >&2
cat "${te}1"
echo "$CMD2" >&2
cat "${te}2" >&2
echo "// diff:" >&2
cat "$tdiff" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
namesFAIL="$namesFAIL $NAME"
else
$PRINTF "$OK\n"
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
numOK=$((numOK+1))
fi
fi ;; # NUMCOND
esac
PORT=$((PORT+1))
N=$((N+1))
# test: setting of environment variables that describe a stream socket
# connection: SOCAT_SOCKADDR, SOCAT_PEERADDR; and SOCAT_SOCKPORT,
# SOCAT_PEERPORT when applicable
while read KEYW FEAT SEL TEST_SOCKADDR TEST_PEERADDR PORTMETHOD; do
if [ -z "$KEYW" ] || [[ "$KEYW" == \#* ]]; then continue; fi
#
protov="$(echo "$KEYW" |tr A-Z a-z)"
proto="${protov%%[0-9]}"
NAME=${KEYW}LISTENENV
case "$TESTS" in
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%$SEL%*|*%$proto%*|*%$protov%*|*%envvar%*|*%listen%*|*%$NAME%*)
TEST="$NAME: $KEYW-LISTEN sets environment variables with socket addresses"
# have a server accepting a connection and invoking some shell code. The shell
# code extracts and prints the SOCAT related environment vars.
# outside code then checks if the environment contains the variables correctly
# describing the peer and local sockets.
if ! eval $NUMCOND; then :;
elif ! cond=$(checkconds \
"" \
"" \
"" \
"$FEAT $(echo $SEL |tr a-z A-Z) STDIO SYSTEM" \
"$KEYW-LISTEN SYSTEM STDIO $KEYW-CONNECT" \
"$REUSEADDR bind" \
"$protov" ); then
$PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
namesCANT="$namesCANT $NAME"
else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
TEST_SOCKADDR="$(echo "$TEST_SOCKADDR" |sed "s/\$N/$N/g")" # actual vars
tsa="$TEST_SOCKADDR" # test server address
if [ "$PORTMETHOD" = PORT ]; then
newport $proto; tsp="$PORT"; # test server port
tsa1="$tsp"; tsa2="$tsa"; tsa="$tsa:$tsp" # tsa2 used for server bind=
else
tsa1="$tsa"; tsa2= # tsa1 used for addr parameter
fi
TEST_PEERADDR="$(echo "$TEST_PEERADDR" |sed "s/\$N/$N/g")" # actual vars
tca="$TEST_PEERADDR" # test client address
if [ "$PORTMETHOD" = PORT ]; then
newport $proto; tcp="$PORT"; # test client port
tca="$tca:$tcp"
fi
#CMD0="$TRACE $SOCAT $opts -u $KEYW-LISTEN:$tsa1 SYSTEM:\"export -p\""
CMD0="$TRACE $SOCAT $opts -u -lpsocat $KEYW-LISTEN:$tsa1,$REUSEADDR SYSTEM:\"echo SOCAT_SOCKADDR=\\\$SOCAT_SOCKADDR; echo SOCAT_PEERADDR=\\\$SOCAT_PEERADDR; echo SOCAT_SOCKPORT=\\\$SOCAT_SOCKPORT; echo SOCAT_PEERPORT=\\\$SOCAT_PEERPORT; sleep 1\""
CMD1="$TRACE $SOCAT $opts -u - $KEYW-CONNECT:$tsa,bind=$tca"
printf "test $F_n $TEST... " $N
eval "$CMD0 2>\"${te}0\" >\"$tf\" &"
pid0=$!
wait${protov}port $tsa1 1
{ echo; sleep 0.1; } |$CMD1 2>"${te}1"
rc1=$?
waitfile "$tf" 2
kill $pid0 2>/dev/null; wait
#set -vx
if [ $rc1 != 0 ]; then
$PRINTF "$NO_RESULT (client failed):\n"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif [ "$(grep SOCAT_SOCKADDR "${tf}" |sed -e 's/^[^=]*=//' |sed -e "s/[\"']//g")" = "$TEST_SOCKADDR" -a \
"$(grep SOCAT_PEERADDR "${tf}" |sed -e 's/^[^=]*=//' -e "s/[\"']//g")" = "$TEST_PEERADDR" -a \
\( "$PORTMETHOD" = ',' -o "$(grep SOCAT_SOCKPORT "${tf}" |sed -e 's/^[^=]*=//' |sed -e 's/"//g')" = "$tsp" \) -a \
\( "$PORTMETHOD" = ',' -o "$(grep SOCAT_PEERPORT "${tf}" |sed -e 's/^[^=]*=//' |sed -e 's/"//g')" = "$tcp" \) \
]; then
$PRINTF "$OK\n"
if [ "$debug" ]; then
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
fi
numOK=$((numOK+1))
else
$PRINTF "$FAILED\n"
echo "$CMD0 &"
cat "${te}0"
echo "$CMD1"
cat "${te}1"
echo -e "SOCAT_SOCKADDR=$TEST_SOCKADDR\nSOCAT_PEERADDR=$TEST_PEERADDR\nSOCAT_SOCKPORT=$TEST_SOCKPORT\nSOCAT_PEERPORT=$TEST_PEERPORT" |
diff - "${tf}"
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
fi
fi # NUMCOND, feats
;;
esac
N=$((N+1))
#set +xv
#
done <<<"
UDPLITE4 IP4 udplite 127.0.0.1 $SECONDADDR PORT
UDPLITE6 IP6 udplite [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] PORT
"
# test the max-children option on pseudo connected sockets
while read KEYW FEAT SEL ADDR IPPORT SHUT; do
if [ -z "$KEYW" ] || [[ "$KEYW" == \#* ]]; then continue; fi
RUNS=$(tolower $KEYW)
PROTO=$KEYW
proto="$(echo "$PROTO" |tr A-Z a-z)"
# test the max-children option on pseudo connected sockets
NAME=${KEYW}MAXCHILDREN
case "$TESTS" in
*%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%$SEL%*|*%socket%*|*%listen%*|*%$NAME%*)
TEST="$NAME: max-children option"
# start a listen process with max-children=1; connect with a client, let it
# send data and then sleep; connect with second client that wants to send
# data immediately, but keep first client active until server terminates.
#If max-children is working correctly only the first data should
# arrive.
if ! eval $NUMCOND; then :;
elif ! cond=$(checkconds \
"" \
"" \
"" \
"$FEAT IP${KEYW##*[A-Z]} FILE STDIO" \
"FILE $PROTO-LISTEN STDIO $PROTO-CONNECT" \
"$REUSEADDR o-trunc o-creat o-append fork max-children $SHUT" \
"$RUNS" ); then
$PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
namesCANT="$namesCANT $NAME"
else
case "X$IPPORT" in
"XPORT")
newport $proto
tsl=$PORT # test socket listen address
tsc="$ADDR:$PORT" # test socket connect address
;;
*)
tsl="$(eval echo "$ADDR")" # resolve $N
tsc=$tsl
esac
#ts="$td/test$N.sock"
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
# on some Linux distributions it hangs, thus -T option here
CMD0="$TRACE $SOCAT $opts -U -T 4 FILE:$tf,o-trunc,o-creat,o-append $PROTO-LISTEN:$tsl,$REUSEADDR,fork,max-children=1"
CMD1="$TRACE $SOCAT $opts -u - $PROTO-CONNECT:$tsc,$SHUT"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0" &
pid0=$!
wait${proto}port $tsl 1
(echo "$da 1"; sleep 3) |$CMD1 >"${tf}1" 2>"${te}1" &
pid1=$!
sleep 1
echo "$da 2" |$CMD1 >"${tf}2" 2>"${te}2" &
pid2=$!
sleep 1
cpids="$(childpids $pid0)"
kill $pid1 $pid2 $cpids $pid0 2>/dev/null; wait
if echo -e "$da 1" |diff - $tf >$tdiff; then
$PRINTF "$OK\n"
numOK=$((numOK+1))
else
$PRINTF "$FAILED\n"
echo "$CMD0 &"
echo "(echo \"$da 1\"; sleep 2) |$CMD1"
echo "echo \"$da 2\" |$CMD1"
cat "${te}0"
cat "${te}1"
cat "${te}2"
cat "$tdiff"
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
fi
fi # NUMCOND
;;
esac
N=$((N+1))
done <<<"
UDPLITE4 UDPLITE udplite 127.0.0.1 PORT shut-null
UDPLITE6 UDPLITE udplite [::1] PORT shut-null
"
# end of common tests # end of common tests
################################################################################## ##################################################################################

View file

@ -255,6 +255,7 @@ int xiogetaddrinfo(const char *node, const char *service,
free(numnode); free(numnode);
return STAT_NORETRY; return STAT_NORETRY;
} }
/* Probably unsupported protocol (e.g. UDP-Lite), fallback to 0 */
hints.ai_protocol = 0; hints.ai_protocol = 0;
continue; continue;
} }

View file

@ -149,7 +149,7 @@ static int xioopen_proxy_connect(
&themlist, us, &uslen, &themlist, us, &uslen,
&needbind, &lowport, socktype); &needbind, &lowport, socktype);
if (result != STAT_OK) if (result != STAT_OK)
return result; return result;
/* Count addrinfo entries */ /* Count addrinfo entries */
themp = themlist; themp = themlist;

View file

@ -1165,6 +1165,7 @@ int _xioopen_dgram_recvfrom(struct single *sfd, int xioflags,
} }
applyopts(sfd, -1, opts, PH_PASTSOCKET); applyopts(sfd, -1, opts, PH_PASTSOCKET);
applyopts(sfd, -1, opts, PH_FD);
applyopts_cloexec(sfd->fd, opts); applyopts_cloexec(sfd->fd, opts);
@ -1183,6 +1184,24 @@ int _xioopen_dgram_recvfrom(struct single *sfd, int xioflags,
} }
#endif /* WITH_UNIX */ #endif /* WITH_UNIX */
#if WITH_IP4 /*|| WITH_IP6*/
switch (proto) {
case IPPROTO_UDP:
#ifdef IPPROTO_UDPLITE
case IPPROTO_UDPLITE:
#endif
if (pf == PF_INET && ((struct sockaddr_in *)us)->sin_port == 0 ||
pf == PF_INET6 && ((struct sockaddr_in6 *)us)->sin6_port == 0) {
struct sockaddr_storage bound;
socklen_t bndlen = sizeof(bound);
char sockbuff[256];
Getsockname(sfd->fd, (struct sockaddr *)&bound, &bndlen);
sockaddr_info((struct sockaddr *)&bound, sizeof(struct sockaddr_storage), sockbuff, sizeof(sockbuff));
Notice1("_xioopen_dgram_recvfrom(): bound to %s", sockbuff);
}
}
#endif
/* for generic sockets, this has already been retrieved */ /* for generic sockets, this has already been retrieved */
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, pf, &sfd->para.socket.range, if (xioparserange(rangename, pf, &sfd->para.socket.range,
@ -1370,6 +1389,7 @@ int _xioopen_dgram_recv(struct single *sfd, int xioflags,
} }
applyopts(sfd, -1, opts, PH_PASTSOCKET); applyopts(sfd, -1, opts, PH_PASTSOCKET);
applyopts(sfd, -1, opts, PH_FD);
applyopts_cloexec(sfd->fd, opts); applyopts_cloexec(sfd->fd, opts);
@ -1386,6 +1406,23 @@ int _xioopen_dgram_recv(struct single *sfd, int xioflags,
#endif /* WITH_UNIX */ #endif /* WITH_UNIX */
#if WITH_IP4 /*|| WITH_IP6*/ #if WITH_IP4 /*|| WITH_IP6*/
switch (proto) {
case IPPROTO_UDP:
#ifdef IPPROTO_UDPLITE
case IPPROTO_UDPLITE:
#endif
if (pf == PF_INET && ((struct sockaddr_in *)us)->sin_port == 0 ||
pf == PF_INET6 && ((struct sockaddr_in6 *)us)->sin6_port == 0) {
struct sockaddr_storage bound;
socklen_t bndlen = sizeof(bound);
char sockbuff[256];
Getsockname(sfd->fd, (struct sockaddr *)&bound, &bndlen);
sockaddr_info((struct sockaddr *)&bound, sizeof(struct sockaddr_storage), sockbuff, sizeof(sockbuff));
Notice1("_xioopen_dgram_recv(): bound to %s", sockbuff);
}
}
#endif
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, pf, &sfd->para.socket.range, if (xioparserange(rangename, pf, &sfd->para.socket.range,
sfd->para.socket.ip.ai_flags) sfd->para.socket.ip.ai_flags)
@ -1396,7 +1433,6 @@ int _xioopen_dgram_recv(struct single *sfd, int xioflags,
free(rangename); free(rangename);
sfd->para.socket.dorange = true; sfd->para.socket.dorange = true;
} }
#endif
#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP #if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
xio_retropt_tcpwrap(sfd, opts); xio_retropt_tcpwrap(sfd, opts);

View file

@ -19,17 +19,6 @@
#include "xio-udp.h" #include "xio-udp.h"
static int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
static int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
static int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
static int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
static
int _xioopen_udp_sendto(const char *hostname, const char *servname,
struct opt *opts,
int xioflags, xiofile_t *xxfd, groups_t groups,
int pf, int socktype, int ipproto);
const struct addrdesc xioaddr_udp_connect = { "UDP-CONNECT", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_UNSPEC HELP(":<host>:<port>") }; const struct addrdesc xioaddr_udp_connect = { "UDP-CONNECT", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_UNSPEC HELP(":<host>:<port>") };
#if WITH_LISTEN #if WITH_LISTEN
const struct addrdesc xioaddr_udp_listen = { "UDP-LISTEN", 1+XIO_RDWR, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, IPPROTO_UDP, PF_UNSPEC HELP(":<port>") }; const struct addrdesc xioaddr_udp_listen = { "UDP-LISTEN", 1+XIO_RDWR, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, IPPROTO_UDP, PF_UNSPEC HELP(":<port>") };
@ -338,7 +327,7 @@ int xioopen_ipdgram_listen(
opts, pf, socktype, ipproto); opts, pf, socktype, ipproto);
} }
static int xioopen_udp_sendto( int xioopen_udp_sendto(
int argc, int argc,
const char *argv[], const char *argv[],
struct opt *opts, struct opt *opts,
@ -372,7 +361,6 @@ static int xioopen_udp_sendto(
OFUNC_OFFSET OFUNC_OFFSET
OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER, OPT_GROUP, OPT_CLOEXEC
*/ */
static
int _xioopen_udp_sendto(const char *hostname, const char *servname, int _xioopen_udp_sendto(const char *hostname, const char *servname,
struct opt *opts, struct opt *opts,
int xioflags, xiofile_t *xxfd, groups_t groups, int xioflags, xiofile_t *xxfd, groups_t groups,
@ -437,7 +425,7 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
} }
static int xioopen_udp_datagram( int xioopen_udp_datagram(
int argc, int argc,
const char *argv[], const char *argv[],
struct opt *opts, struct opt *opts,
@ -517,7 +505,7 @@ static int xioopen_udp_datagram(
} }
static int xioopen_udp_recvfrom( int xioopen_udp_recvfrom(
int argc, int argc,
const char *argv[], const char *argv[],
struct opt *opts, struct opt *opts,
@ -609,7 +597,7 @@ static int xioopen_udp_recvfrom(
} }
static int xioopen_udp_recv( int xioopen_udp_recv(
int argc, int argc,
const char *argv[], const char *argv[],
struct opt *opts, struct opt *opts,

View file

@ -28,6 +28,13 @@ extern int _xioopen_ipdgram_listen(struct single *sfd,
int xioflags, union sockaddr_union *us, socklen_t uslen, int xioflags, union sockaddr_union *us, socklen_t uslen,
struct opt *opts, int pf, int socktype, int ipproto); struct opt *opts, int pf, int socktype, int ipproto);
extern int xioopen_udp_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
extern int xioopen_udp_datagram(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
extern int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
extern int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
extern int _xioopen_udp_sendto(const char *hostname, const char *servname, struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int pf, int socktype, int ipproto);
extern int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *xfd, const struct addrdesc *addrdesc); extern int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *xfd, const struct addrdesc *addrdesc);
#endif /* !defined(__xio_udp_h_included) */ #endif /* !defined(__xio_udp_h_included) */

66
xio-udplite.c Normal file
View file

@ -0,0 +1,66 @@
/* source: xio-udplite.c */
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for handling UDPLITE addresses */
#include "xiosysincludes.h"
#if WITH_UDPLITE && (WITH_IP4 || WITH_IP6)
#include "xioopen.h"
#include "xio-socket.h"
#include "xio-ip4.h"
#include "xio-ip6.h"
#include "xio-ip.h"
#include "xio-ipapp.h"
#include "xio-tcpwrap.h"
#include "xio-udp.h"
#include "xio-udplite.h"
/* due to bug in Ubuntu-18.04 */
#ifndef UDPLITE_SEND_CSCOV
# define UDPLITE_SEND_CSCOV 10
#endif
#ifndef UDPLITE_RECV_CSCOV
# define UDPLITE_RECV_CSCOV 11
#endif
const struct addrdesc xioaddr_udplite_connect = { "UDPLITE-CONNECT", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE, SOCK_DGRAM, IPPROTO_UDPLITE, PF_UNSPEC HELP(":<host>:<port>") };
#if WITH_LISTEN
const struct addrdesc xioaddr_udplite_listen = { "UDPLITE-LISTEN", 1+XIO_RDWR, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, IPPROTO_UDPLITE, PF_UNSPEC HELP(":<port>") };
#endif /* WITH_LISTEN */
const struct addrdesc xioaddr_udplite_sendto = { "UDPLITE-SENDTO", 1+XIO_RDWR, xioopen_udp_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<host>:<port>") };
const struct addrdesc xioaddr_udplite_recvfrom = { "UDPLITE-RECVFROM", 1+XIO_RDWR, xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<port>") };
const struct addrdesc xioaddr_udplite_recv = { "UDPLITE-RECV", 1+XIO_RDONLY, xioopen_udp_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<port>") };
const struct addrdesc xioaddr_udplite_datagram = { "UDPLITE-DATAGRAM", 1+XIO_RDWR, xioopen_udp_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<host>:<port>") };
#if WITH_IP4
const struct addrdesc xioaddr_udplite4_connect = { "UDPLITE4-CONNECT", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_IP_UDPLITE, SOCK_DGRAM, IPPROTO_UDPLITE, PF_INET HELP(":<host>:<port>") };
#if WITH_LISTEN
const struct addrdesc xioaddr_udplite4_listen = { "UDPLITE4-LISTEN", 1+XIO_RDWR, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_INET, IPPROTO_UDPLITE, PF_INET HELP(":<port>") };
#endif /* WITH_LISTEN */
const struct addrdesc xioaddr_udplite4_sendto = { "UDPLITE4-SENDTO", 1+XIO_RDWR, xioopen_udp_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_IP_UDPLITE, PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<host>:<port>") };
const struct addrdesc xioaddr_udplite4_datagram = { "UDPLITE4-DATAGRAM", 1+XIO_RDWR, xioopen_udp_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<remote-address>:<port>") };
const struct addrdesc xioaddr_udplite4_recvfrom = { "UDPLITE4-RECVFROM", 1+XIO_RDWR, xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_CHILD|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<host>:<port>") };
const struct addrdesc xioaddr_udplite4_recv = { "UDPLITE4-RECV", 1+XIO_RDONLY, xioopen_udp_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<port>") };
#endif /* WITH_IP4 */
#if WITH_IP6
const struct addrdesc xioaddr_udplite6_connect = { "UDPLITE6-CONNECT", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE, SOCK_DGRAM, IPPROTO_UDPLITE, PF_INET6 HELP(":<host>:<port>") };
#if WITH_LISTEN
const struct addrdesc xioaddr_udplite6_listen = { "UDPLITE6-LISTEN", 1+XIO_RDWR, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_INET6, IPPROTO_UDPLITE, 0 HELP(":<port>") };
#endif /* WITH_LISTEN */
const struct addrdesc xioaddr_udplite6_sendto = { "UDPLITE6-SENDTO", 1+XIO_RDWR, xioopen_udp_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE, PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<host>:<port>") };
const struct addrdesc xioaddr_udplite6_datagram = { "UDPLITE6-DATAGRAM", 1+XIO_RDWR, xioopen_udp_datagram,GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<host>:<port>") };
const struct addrdesc xioaddr_udplite6_recvfrom = { "UDPLITE6-RECVFROM", 1+XIO_RDWR, xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_CHILD|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<port>") };
const struct addrdesc xioaddr_udplite6_recv = { "UDPLITE6-RECV", 1+XIO_RDONLY, xioopen_udp_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_IP_UDPLITE|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE HELP(":<port>") };
#endif /* WITH_IP6 */
const struct optdesc xioopt_udplite_send_cscov = { "udplite-send-cscov", NULL, OPT_UDPLITE_SEND_CSCOV, GROUP_IP_UDPLITE, PH_FD, TYPE_INT, OFUNC_SOCKOPT, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV};
const struct optdesc xioopt_udplite_recv_cscov = { "udplite-recv-cscov", NULL, OPT_UDPLITE_RECV_CSCOV, GROUP_IP_UDPLITE, PH_FD, TYPE_INT, OFUNC_SOCKOPT, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV};
#endif /* WITH_UDPLITE && (WITH_IP4 || WITH_IP6) */

30
xio-udplite.h Normal file
View file

@ -0,0 +1,30 @@
/* source: xio-udplite.h */
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_udplite_h_included
#define __xio_udplite_h_included 1
extern const struct addrdesc xioaddr_udplite_connect;
extern const struct addrdesc xioaddr_udplite_listen;
extern const struct addrdesc xioaddr_udplite_sendto;
extern const struct addrdesc xioaddr_udplite_datagram;
extern const struct addrdesc xioaddr_udplite_recvfrom;
extern const struct addrdesc xioaddr_udplite_recv;
extern const struct addrdesc xioaddr_udplite4_connect;
extern const struct addrdesc xioaddr_udplite4_listen;
extern const struct addrdesc xioaddr_udplite4_sendto;
extern const struct addrdesc xioaddr_udplite4_datagram;
extern const struct addrdesc xioaddr_udplite4_recvfrom;
extern const struct addrdesc xioaddr_udplite4_recv;
extern const struct addrdesc xioaddr_udplite6_connect;
extern const struct addrdesc xioaddr_udplite6_listen;
extern const struct addrdesc xioaddr_udplite6_sendto;
extern const struct addrdesc xioaddr_udplite6_datagram;
extern const struct addrdesc xioaddr_udplite6_recvfrom;
extern const struct addrdesc xioaddr_udplite6_recv;
extern const struct optdesc xioopt_udplite_send_cscov;
extern const struct optdesc xioopt_udplite_recv_cscov;
#endif /* !defined(__xio_udplite_h_included) */

2
xio.h
View file

@ -95,7 +95,7 @@ enum xiotag {
} ; } ;
/* Keep condition consistent with xioopts.h:GROUP_*! */ /* Keep condition consistent with xioopts.h:GROUP_*! */
#if WITH_POSIXMQ || WITH_SCTP || WITH_DCCP #if WITH_POSIXMQ || WITH_SCTP || WITH_DCCP || WITH_UDPLITE
typedef uint64_t groups_t; typedef uint64_t groups_t;
#define F_groups_t F_uint64_x #define F_groups_t F_uint64_x
#else #else

View file

@ -48,7 +48,7 @@ static const char *addressgroupnames[] = {
"UNIX", "IP4", "IP6", "INTERFACE", "UNIX", "IP4", "IP6", "INTERFACE",
"UDP", "TCP", "SOCKS4", "OPENSSL", "UDP", "TCP", "SOCKS4", "OPENSSL",
"PROCESS", "APPL", "HTTP", "undef", "PROCESS", "APPL", "HTTP", "undef",
"POSIXMQ", "SCTP", "DCCP" "POSIXMQ", "SCTP", "DCCP", "UDPLITE"
} ; } ;
/* keep consistent with xioopts.h:enum ephase ! */ /* keep consistent with xioopts.h:enum ephase ! */

View file

@ -32,6 +32,7 @@
#include "xio-udp.h" #include "xio-udp.h"
#include "xio-sctp.h" #include "xio-sctp.h"
#include "xio-dccp.h" #include "xio-dccp.h"
#include "xio-udplite.h"
#include "xio-socks.h" #include "xio-socks.h"
#include "xio-socks5.h" #include "xio-socks5.h"
#include "xio-proxy.h" #include "xio-proxy.h"

View file

@ -341,6 +341,54 @@ const struct addrname addressnames[] = {
{ "UDP6-SEND", &xioaddr_udp6_sendto }, { "UDP6-SEND", &xioaddr_udp6_sendto },
{ "UDP6-SENDTO", &xioaddr_udp6_sendto }, { "UDP6-SENDTO", &xioaddr_udp6_sendto },
#endif #endif
#if (WITH_IP4 || WITH_IP6) && WITH_UDPLITE
{ "UDPLITE", &xioaddr_udplite_connect },
{ "UDPLITE-CONNECT", &xioaddr_udplite_connect },
{ "UDPLITE-DATAGRAM", &xioaddr_udplite_datagram },
{ "UDPLITE-DGRAM", &xioaddr_udplite_datagram },
#endif
#if (WITH_IP4 || WITH_IP6) && WITH_UDPLITE && WITH_LISTEN
{ "UDPLITE-L", &xioaddr_udplite_listen },
{ "UDPLITE-LISTEN", &xioaddr_udplite_listen },
#endif
#if (WITH_IP4 || WITH_IP6) && WITH_UDPLITE
{ "UDPLITE-RECV", &xioaddr_udplite_recv },
{ "UDPLITE-RECVFROM", &xioaddr_udplite_recvfrom },
{ "UDPLITE-SEND", &xioaddr_udplite_sendto },
{ "UDPLITE-SENDTO", &xioaddr_udplite_sendto },
#endif
#if WITH_IP4 && WITH_UDPLITE
{ "UDPLITE4", &xioaddr_udplite4_connect },
{ "UDPLITE4-CONNECT", &xioaddr_udplite4_connect },
{ "UDPLITE4-DATAGRAM", &xioaddr_udplite4_datagram },
{ "UDPLITE4-DGRAM", &xioaddr_udplite4_datagram },
#endif
#if WITH_IP4 && WITH_UDPLITE && WITH_LISTEN
{ "UDPLITE4-L", &xioaddr_udplite4_listen },
{ "UDPLITE4-LISTEN", &xioaddr_udplite4_listen },
#endif
#if WITH_IP4 && WITH_UDPLITE
{ "UDPLITE4-RECV", &xioaddr_udplite4_recv },
{ "UDPLITE4-RECVFROM", &xioaddr_udplite4_recvfrom },
{ "UDPLITE4-SEND", &xioaddr_udplite4_sendto },
{ "UDPLITE4-SENDTO", &xioaddr_udplite4_sendto },
#endif
#if WITH_IP6 && WITH_UDPLITE
{ "UDPLITE6", &xioaddr_udplite6_connect },
{ "UDPLITE6-CONNECT", &xioaddr_udplite6_connect },
{ "UDPLITE6-DATAGRAM", &xioaddr_udplite6_datagram },
{ "UDPLITE6-DGRAM", &xioaddr_udplite6_datagram },
#endif
#if WITH_IP6 && WITH_UDPLITE && WITH_LISTEN
{ "UDPLITE6-L", &xioaddr_udplite6_listen },
{ "UDPLITE6-LISTEN", &xioaddr_udplite6_listen },
#endif
#if WITH_IP6 && WITH_UDPLITE
{ "UDPLITE6-RECV", &xioaddr_udplite6_recv },
{ "UDPLITE6-RECVFROM", &xioaddr_udplite6_recvfrom },
{ "UDPLITE6-SEND", &xioaddr_udplite6_sendto },
{ "UDPLITE6-SENDTO", &xioaddr_udplite6_sendto },
#endif
#if WITH_UNIX #if WITH_UNIX
{ "UNIX", &xioaddr_unix_client }, { "UNIX", &xioaddr_unix_client },
{ "UNIX-CLIENT", &xioaddr_unix_client }, { "UNIX-CLIENT", &xioaddr_unix_client },

View file

@ -102,6 +102,12 @@ bool xioopts_ignoregroups;
# define IF_DCCP(a,b) # define IF_DCCP(a,b)
#endif #endif
#if WITH_UDPLITE
# define IF_UDPLITE(a,b) {a,b},
#else
# define IF_UDPLITE(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
@ -1894,6 +1900,8 @@ const struct optname optionnames[] = {
IF_TUN ("tun-no-pi", &opt_iff_no_pi) IF_TUN ("tun-no-pi", &opt_iff_no_pi)
IF_TUN ("tun-type", &opt_tun_type) IF_TUN ("tun-type", &opt_tun_type)
IF_SOCKET ("type", &opt_so_type) IF_SOCKET ("type", &opt_so_type)
IF_UDPLITE("udplite-recv-cscov", &xioopt_udplite_recv_cscov)
IF_UDPLITE("udplite-send-cscov", &xioopt_udplite_send_cscov)
IF_ANY ("uid", &opt_user) IF_ANY ("uid", &opt_user)
IF_NAMED ("uid-e", &opt_user_early) IF_NAMED ("uid-e", &opt_user_early)
IF_ANY ("uid-l", &opt_user_late) IF_ANY ("uid-l", &opt_user_late)

View file

@ -190,20 +190,22 @@ enum e_func {
#define GROUP_HTTP 0x40000000 /* any HTTP client */ #define GROUP_HTTP 0x40000000 /* any HTTP client */
/* Keep condition consistent with xio.h:groups_t! */ /* Keep condition consistent with xio.h:groups_t! */
#if WITH_POSIXMQ || WITH_SCTP || WITH_DCCP #if WITH_POSIXMQ || WITH_SCTP || WITH_DCCP || WITH_UDPLITE
/* The following groups are not expected on systems without uint64_t */ /* The following groups are not expected on systems without uint64_t */
#define GROUP_POSIXMQ 0x0100000000U #define GROUP_POSIXMQ 0x0100000000U
#define GROUP_IP_SCTP 0x0200000000U #define GROUP_IP_SCTP 0x0200000000U
#define GROUP_IP_DCCP 0x0400000000U #define GROUP_IP_DCCP 0x0400000000U
#define GROUP_ALL 0x07ffffffffU #define GROUP_IP_UDPLITE 0x0800000000U
#else /* !(WITH_POSIXMQ || WITH_SCTP || WITH_DCCP) */ #define GROUP_ALL 0x0fffffffffU
#else /* !(WITH_POSIXMQ || WITH_SCTP || WITH_DCCP || WITH_UDPLITE) */
#define GROUP_POSIXMQ 0 #define GROUP_POSIXMQ 0
#define GROUP_IP_SCTP 0 #define GROUP_IP_SCTP 0
#define GROUP_IP_DCCP 0 #define GROUP_IP_DCCP 0
#define GROUP_IP_UDPLITE 0
#define GROUP_ALL 0xffffffffU #define GROUP_ALL 0xffffffffU
#endif /* !(WITH_POSIXMQ || WITH_SCTP || WITH_DCCP) */ #endif /* !(WITH_POSIXMQ || WITH_SCTP || WITH_DCCP || WITH_UDPLITE) */
#define GROUP_IPAPP (GROUP_IP_UDP|GROUP_IP_TCP|GROUP_IP_SCTP|GROUP_IP_DCCP) /* true: indicates one of UDP, TCP, SCTP, DCCP */ #define GROUP_IPAPP (GROUP_IP_UDP|GROUP_IP_TCP|GROUP_IP_SCTP|GROUP_IP_DCCP|GROUP_IP_UDPLITE) /* true: indicates one of UDP, TCP, SCTP, DCCP, UDPlite */
#define GROUP_ANY (GROUP_PROCESS|GROUP_APPL) #define GROUP_ANY (GROUP_PROCESS|GROUP_APPL)
@ -860,6 +862,8 @@ enum e_optcode {
OPT_TUN_DEVICE, /* tun: /dev/net/tun ... */ OPT_TUN_DEVICE, /* tun: /dev/net/tun ... */
OPT_TUN_NAME, /* tun: tun0 */ OPT_TUN_NAME, /* tun: tun0 */
OPT_TUN_TYPE, /* tun: tun|tap */ OPT_TUN_TYPE, /* tun: tun|tap */
OPT_UDPLITE_RECV_CSCOV,
OPT_UDPLITE_SEND_CSCOV,
OPT_UMASK, OPT_UMASK,
OPT_UNIX_BIND_TEMPNAME, /* UNIX domain sockets */ OPT_UNIX_BIND_TEMPNAME, /* UNIX domain sockets */
OPT_UNIX_TIGHTSOCKLEN, OPT_UNIX_TIGHTSOCKLEN,