From 2cfc39e9e53d4938296d92355248e55154b0dc6d Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Sat, 11 Nov 2023 17:18:06 +0100 Subject: [PATCH] UDP-Lite (UDPlite) support --- CHANGES | 10 + Makefile.in | 4 +- config.h.in | 1 + configure.ac | 19 ++ doc/socat.yo | 49 ++++- procan-cdefs.c | 7 +- socat.c | 5 + test.sh | 570 +++++++++++++++++++++++++++++++++++++++++++++---- xio-ip.c | 1 + xio-proxy.c | 2 +- xio-socket.c | 38 +++- xio-udp.c | 20 +- xio-udp.h | 7 + xio-udplite.c | 66 ++++++ xio-udplite.h | 30 +++ xio.h | 2 +- xiohelp.c | 2 +- xiomodes.h | 1 + xioopen.c | 48 +++++ xioopts.c | 8 + xioopts.h | 14 +- 21 files changed, 833 insertions(+), 71 deletions(-) create mode 100644 xio-udplite.c create mode 100644 xio-udplite.h diff --git a/CHANGES b/CHANGES index e7f93ca..4dbe5d5 100644 --- a/CHANGES +++ b/CHANGES @@ -179,6 +179,16 @@ Features: DCCP6-LISTEN (DCCP6-L) 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: 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/ diff --git a/Makefile.in b/Makefile.in index 5f67f8b..a80c5b5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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-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-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-termios.c xio-readline.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-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-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-system.h xio-shell.h xio-termios.h xio-readline.h \ xio-pty.h xio-openssl.h xio-streams.h xio-namespaces.h \ diff --git a/config.h.in b/config.h.in index f0d2842..0b4842c 100644 --- a/config.h.in +++ b/config.h.in @@ -712,6 +712,7 @@ #undef WITH_INTERFACE #undef WITH_TCP #undef WITH_UDP +#undef WITH_UDPLITE #undef WITH_SCTP #undef WITH_DCCP #undef WITH_LISTEN diff --git a/configure.ac b/configure.ac index f444ad8..33d1543 100644 --- a/configure.ac +++ b/configure.ac @@ -345,6 +345,25 @@ AC_ARG_ENABLE(udp, [ --disable-udp disable UDP support], esac], [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 +#include ], +[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_ARG_ENABLE(sctp, [ --disable-sctp disable SCTP support], [case "$enableval" in diff --git a/doc/socat.yo b/doc/socat.yo index c7a81a4..a9913b5 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -927,6 +927,7 @@ label(ADDRESS_SCTP6_LISTEN)dit(bf(tt(SCTP6-LISTEN:))) 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:::))) 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. @@ -1301,6 +1302,8 @@ label(ADDRESS_TUN)dit(bf(tt(TUN[:/]))) link(netns)(OPTION_NETNS)nl() See also: link(ip-recv)(ADDRESS_IP_RECV) + +label(ADDRESSES_UDP) label(ADDRESS_UDP_CONNECT)dit(bf(tt(UDP::))) Connects to [link(UDP service)(TYPE_UDP_SERVICE)] on [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:))) 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) +dit(bf(tt(UDPLITE-CONNECT::))) +dit(bf(tt(UDPLITE4-CONNECT::))) +dit(bf(tt(UDPLITE6-CONNECT::))) +dit(bf(tt(UDPLITE-DATAGRAM:
:))) +dit(bf(tt(UDPLITE4-DATAGRAM:
:))) +dit(bf(tt(UDPLITE6-DATAGRAM:
:))) +dit(bf(tt(UDPLITE-LISTEN:))) +dit(bf(tt(UDPLITE4-LISTEN:))) +dit(bf(tt(UDPLITE6-LISTEN:))) +dit(bf(tt(UDPLITE-SENDTO::))) +dit(bf(tt(UDPLITE4-SENDTO::))) +dit(bf(tt(UDPLITE6-SENDTO::))) +dit(bf(tt(UDPLITE-RECVFROM:))) +dit(bf(tt(UDPLITE4-RECVFROM:))) +dit(bf(tt(UDPLITE6-RECVFROM:))) +dit(bf(tt(UDPLITE-RECV:))) +dit(bf(tt(UDPLITE4-RECV:))) +dit(bf(tt(UDPLITE6-RECV:))) + 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:))) Connects to link()(TYPE_FILENAME) assuming it is a unixdomain() socket. @@ -2700,6 +2725,21 @@ enddit() 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)) These options may be applied to SCTP stream sockets. @@ -2726,13 +2766,14 @@ enddit() 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 -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() label(OPTION_SOURCEPORT)dit(bf(tt(sourceport=))) - For outgoing (client) TCP and UDP connections, it sets the source + For outgoing (client) connections, it sets the source link()(TYPE_PORT) using an extra code(bind()) call. With TCP or UDP listen addresses, socat immediately shuts down the connection if the client does not use this sourceport. UDP-RECV, @@ -2740,7 +2781,7 @@ label(OPTION_SOURCEPORT)dit(bf(tt(sourceport=))) it does not match. (link(example)(EXAMPLE_OPTION_SOURCEPORT)). 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 systems, this requires root privilege, and thus indicates that the client process is authorized by local root. diff --git a/procan-cdefs.c b/procan-cdefs.c index 19a3fce..3f8e660 100644 --- a/procan-cdefs.c +++ b/procan-cdefs.c @@ -126,11 +126,14 @@ int procan_cdefs(FILE *outfile) { #ifdef IPPROTO_UDP fprintf(outfile, "#define IPPROTO_UDP %d\n", IPPROTO_UDP); #endif +#ifdef IPPROTO_DCCP + fprintf(outfile, "#define IPPROTO_DCCP %d\n", IPPROTO_DCCP); +#endif #ifdef IPPROTO_SCTP fprintf(outfile, "#define IPPROTO_SCTP %d\n", IPPROTO_SCTP); #endif -#ifdef IPPROTO_DCCP - fprintf(outfile, "#define IPPROTO_DCCP %d\n", IPPROTO_DCCP); +#ifdef IPPROTO_UDPLITE + fprintf(outfile, "#define IPPROTO_UDPLITE %d\n", IPPROTO_UDPLITE); #endif #ifdef SOL_SOCKET fprintf(outfile, "#define SOL_SOCKET 0x%x\n", SOL_SOCKET); diff --git a/socat.c b/socat.c index f13f813..e98ecc2 100644 --- a/socat.c +++ b/socat.c @@ -604,6 +604,11 @@ void socat_version(FILE *fd) { #else fputs(" #undef WITH_DCCP\n", fd); #endif +#ifdef WITH_UDPLITE + fprintf(fd, " #define WITH_UDPLITE %d\n", WITH_UDPLITE); +#else + fputs(" #undef WITH_UDPLITE\n", fd); +#endif #ifdef WITH_LISTEN fprintf(fd, " #define WITH_LISTEN %d\n", WITH_LISTEN); #else diff --git a/test.sh b/test.sh index dd4ed16..f76d044 100755 --- a/test.sh +++ b/test.sh @@ -607,6 +607,10 @@ case "$TESTS" in $ECHO "testing if address array is sorted...\c" TF="$TD/socat-q" 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 '^<' |LC_ALL=C sort |diff "$TF" - >"$TF-diff" if [ -s "$TF-diff" ]; then @@ -994,6 +998,20 @@ runsdccp6 () { 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 runsunix () { # for now... @@ -1415,6 +1433,51 @@ waitsctp4port () { 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 # exits with 0 when it is not used checktcp6port () { @@ -1557,6 +1620,48 @@ waitsctp6port () { 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 waitunixport () { 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 # connection: SOCAT_SOCKADDR, SOCAT_PEERADDR; and SOCAT_SOCKPORT, # 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 # protov="$(echo "$KEYW" |tr A-Z a-z)" proto="${protov%%[0-9]}" NAME=${KEYW}LISTENENV 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" # have a server accepting a connection and invoking some shell code. The shell # code extracts and prints the SOCAT related environment vars. @@ -9993,19 +10098,19 @@ N=$((N+1)) #set +xv # done <<<" -TCP4 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 -UDP6 IP6 [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 -SCTP6 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 , +TCP4 TCP tcp 127.0.0.1 $SECONDADDR PORT +TCP6 IP6 tcp [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 sctp 127.0.0.1 $SECONDADDR PORT +SCTP6 SCTP sctp [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] PORT +UNIX UNIX unix $td/test\$N.server $td/test\$N.client , " # this one fails due to weakness in socats UDP4-LISTEN implementation: #UDP4 $LOCALHOST $SECONDADDR $((PORT+4)) $((PORT+5)) # 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 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)" NAME=${KEYW}ENV_$SCM_ENVNAME 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 TEST="$NAME: $KEYW ancillary message sets env SOCAT_$SCM_ENVNAME" # idea: start a socat process with *-RECVFROM:..,... , ev. with ancillary @@ -10110,30 +10215,30 @@ esac N=$((N+1)) # done <<<" -IP4 UDP4 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 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 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 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 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 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 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 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 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 -IP6 UDP6 [::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 [::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 [::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 +IP4 UDP4 udp 127.0.0.1 PORT ip-options=x01000000 ip-recvopts IP_OPTIONS user x01000000 +IP4 UDP4 udp 127.0.0.1 PORT , so-timestamp TIMESTAMP user timestamp +IP4 UDP4 udp 127.0.0.1 PORT ip-ttl=53 ip-recvttl IP_TTL user 53 +IP4 UDP4 udp 127.0.0.1 PORT ip-tos=7 ip-recvtos IP_TOS user 7 +IP4 UDP4 udp 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_DSTADDR user 127.0.0.1 +IP4 UDP4 udp 127.0.0.1 PORT , ip-pktinfo IP_IF user lo +IP4 UDP4 udp 127.0.0.1 PORT , ip-recvif IP_IF user lo0 +IP4 UDP4 udp 127.0.0.1 PORT , ip-recvdstaddr IP_DSTADDR user 127.0.0.1 +IP4 IP4 rawip 127.0.0.1 PROTO ip-options=x01000000 ip-recvopts IP_OPTIONS root x01000000 +IP4 IP4 rawip 127.0.0.1 PROTO , so-timestamp TIMESTAMP root timestamp +IP4 IP4 rawip 127.0.0.1 PROTO ip-ttl=53 ip-recvttl IP_TTL root 53 +IP4 IP4 rawip 127.0.0.1 PROTO ip-tos=7 ip-recvtos IP_TOS root 7 +IP4 IP4 rawip 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_DSTADDR root 127.0.0.1 +IP4 IP4 rawip 127.0.0.1 PROTO , ip-pktinfo IP_IF root lo +IP4 IP4 rawip 127.0.0.1 PROTO , ip-recvif IP_IF root lo0 +IP4 IP4 rawip 127.0.0.1 PROTO , ip-recvdstaddr IP_DSTADDR root 127.0.0.1 +IP6 UDP6 udp [::1] PORT , ipv6-recvpktinfo IPV6_DSTADDR user [[]0000:0000:0000:0000:0000:0000:0000:0001[]] +IP6 UDP6 udp [::1] PORT ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT user 35 +IP6 UDP6 udp [::1] PORT ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS user x000000aa +IP6 IP6 rawip [::1] PROTO , ipv6-recvpktinfo IPV6_DSTADDR root [[]0000:0000:0000:0000:0000:0000:0000:0001[]] +IP6 IP6 rawip [::1] PROTO ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT root 35 +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 " @@ -11471,7 +11576,8 @@ UNIX unix $td/test\$N.server - # 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 RUNS=$(tolower $KEYW) PROTO=$KEYW @@ -11479,7 +11585,7 @@ 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%*|*%socket%*|*%listen%*|*%$NAME%*) +*%$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 @@ -11546,8 +11652,8 @@ fi # NUMCOND esac N=$((N+1)) done <<<" -UDP4 UDP 127.0.0.1 PORT shut-null -UDP6 UDP [::1] PORT shut-null +UDP4 UDP udp 127.0.0.1 PORT shut-null +UDP6 UDP udp [::1] PORT shut-null " # debugging this hanging test was difficult - following lessons learned: # kill had no effect when child process existed @@ -18205,6 +18311,394 @@ esac 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 ################################################################################## diff --git a/xio-ip.c b/xio-ip.c index e1de0fa..c7c776a 100644 --- a/xio-ip.c +++ b/xio-ip.c @@ -255,6 +255,7 @@ int xiogetaddrinfo(const char *node, const char *service, free(numnode); return STAT_NORETRY; } + /* Probably unsupported protocol (e.g. UDP-Lite), fallback to 0 */ hints.ai_protocol = 0; continue; } diff --git a/xio-proxy.c b/xio-proxy.c index ae2027e..7c94660 100644 --- a/xio-proxy.c +++ b/xio-proxy.c @@ -149,7 +149,7 @@ static int xioopen_proxy_connect( &themlist, us, &uslen, &needbind, &lowport, socktype); if (result != STAT_OK) - return result; + return result; /* Count addrinfo entries */ themp = themlist; diff --git a/xio-socket.c b/xio-socket.c index e162b8f..eabdc23 100644 --- a/xio-socket.c +++ b/xio-socket.c @@ -1165,6 +1165,7 @@ int _xioopen_dgram_recvfrom(struct single *sfd, int xioflags, } applyopts(sfd, -1, opts, PH_PASTSOCKET); + applyopts(sfd, -1, opts, PH_FD); applyopts_cloexec(sfd->fd, opts); @@ -1183,6 +1184,24 @@ int _xioopen_dgram_recvfrom(struct single *sfd, int xioflags, } #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 */ if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { 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_FD); applyopts_cloexec(sfd->fd, opts); @@ -1386,6 +1406,23 @@ int _xioopen_dgram_recv(struct single *sfd, int xioflags, #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_recv(): bound to %s", sockbuff); + } + } +#endif + if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) { if (xioparserange(rangename, pf, &sfd->para.socket.range, sfd->para.socket.ip.ai_flags) @@ -1396,7 +1433,6 @@ int _xioopen_dgram_recv(struct single *sfd, int xioflags, free(rangename); sfd->para.socket.dorange = true; } -#endif #if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP xio_retropt_tcpwrap(sfd, opts); diff --git a/xio-udp.c b/xio-udp.c index 201d0e6..68743e6 100644 --- a/xio-udp.c +++ b/xio-udp.c @@ -19,17 +19,6 @@ #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("::") }; #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(":") }; @@ -338,7 +327,7 @@ int xioopen_ipdgram_listen( opts, pf, socktype, ipproto); } -static int xioopen_udp_sendto( +int xioopen_udp_sendto( int argc, const char *argv[], struct opt *opts, @@ -372,7 +361,6 @@ static int xioopen_udp_sendto( OFUNC_OFFSET 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, struct opt *opts, 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, const char *argv[], struct opt *opts, @@ -517,7 +505,7 @@ static int xioopen_udp_datagram( } -static int xioopen_udp_recvfrom( +int xioopen_udp_recvfrom( int argc, const char *argv[], struct opt *opts, @@ -609,7 +597,7 @@ static int xioopen_udp_recvfrom( } -static int xioopen_udp_recv( +int xioopen_udp_recv( int argc, const char *argv[], struct opt *opts, diff --git a/xio-udp.h b/xio-udp.h index e8058d4..3cdccba 100644 --- a/xio-udp.h +++ b/xio-udp.h @@ -28,6 +28,13 @@ extern int _xioopen_ipdgram_listen(struct single *sfd, int xioflags, union sockaddr_union *us, socklen_t uslen, 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); #endif /* !defined(__xio_udp_h_included) */ diff --git a/xio-udplite.c b/xio-udplite.c new file mode 100644 index 0000000..3e5add7 --- /dev/null +++ b/xio-udplite.c @@ -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("::") }; +#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(":") }; +#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("::") }; +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(":") }; +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(":") }; +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("::") }; + +#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("::") }; +#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(":") }; +#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("::") }; +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("::") }; +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("::") }; +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(":") }; +#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("::") }; +#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(":") }; +#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("::") }; +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("::") }; +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(":") }; +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(":") }; +#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) */ diff --git a/xio-udplite.h b/xio-udplite.h new file mode 100644 index 0000000..8a00239 --- /dev/null +++ b/xio-udplite.h @@ -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) */ diff --git a/xio.h b/xio.h index 1a68819..a7e6600 100644 --- a/xio.h +++ b/xio.h @@ -95,7 +95,7 @@ enum xiotag { } ; /* 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; #define F_groups_t F_uint64_x #else diff --git a/xiohelp.c b/xiohelp.c index 519b464..4641dbd 100644 --- a/xiohelp.c +++ b/xiohelp.c @@ -48,7 +48,7 @@ static const char *addressgroupnames[] = { "UNIX", "IP4", "IP6", "INTERFACE", "UDP", "TCP", "SOCKS4", "OPENSSL", "PROCESS", "APPL", "HTTP", "undef", - "POSIXMQ", "SCTP", "DCCP" + "POSIXMQ", "SCTP", "DCCP", "UDPLITE" } ; /* keep consistent with xioopts.h:enum ephase ! */ diff --git a/xiomodes.h b/xiomodes.h index 911bc6d..4d26052 100644 --- a/xiomodes.h +++ b/xiomodes.h @@ -32,6 +32,7 @@ #include "xio-udp.h" #include "xio-sctp.h" #include "xio-dccp.h" +#include "xio-udplite.h" #include "xio-socks.h" #include "xio-socks5.h" #include "xio-proxy.h" diff --git a/xioopen.c b/xioopen.c index 4599d1b..fdcb38d 100644 --- a/xioopen.c +++ b/xioopen.c @@ -341,6 +341,54 @@ const struct addrname addressnames[] = { { "UDP6-SEND", &xioaddr_udp6_sendto }, { "UDP6-SENDTO", &xioaddr_udp6_sendto }, #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 { "UNIX", &xioaddr_unix_client }, { "UNIX-CLIENT", &xioaddr_unix_client }, diff --git a/xioopts.c b/xioopts.c index a6d1849..d962f96 100644 --- a/xioopts.c +++ b/xioopts.c @@ -102,6 +102,12 @@ bool xioopts_ignoregroups; # define IF_DCCP(a,b) #endif +#if WITH_UDPLITE +# define IF_UDPLITE(a,b) {a,b}, +#else +# define IF_UDPLITE(a,b) +#endif + #if WITH_SOCKS4 # define IF_SOCKS4(a,b) {a,b}, #else @@ -1894,6 +1900,8 @@ const struct optname optionnames[] = { IF_TUN ("tun-no-pi", &opt_iff_no_pi) IF_TUN ("tun-type", &opt_tun_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_NAMED ("uid-e", &opt_user_early) IF_ANY ("uid-l", &opt_user_late) diff --git a/xioopts.h b/xioopts.h index 21281ba..d4dad86 100644 --- a/xioopts.h +++ b/xioopts.h @@ -190,20 +190,22 @@ enum e_func { #define GROUP_HTTP 0x40000000 /* any HTTP client */ /* 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 */ #define GROUP_POSIXMQ 0x0100000000U #define GROUP_IP_SCTP 0x0200000000U #define GROUP_IP_DCCP 0x0400000000U -#define GROUP_ALL 0x07ffffffffU -#else /* !(WITH_POSIXMQ || WITH_SCTP || WITH_DCCP) */ +#define GROUP_IP_UDPLITE 0x0800000000U +#define GROUP_ALL 0x0fffffffffU +#else /* !(WITH_POSIXMQ || WITH_SCTP || WITH_DCCP || WITH_UDPLITE) */ #define GROUP_POSIXMQ 0 #define GROUP_IP_SCTP 0 #define GROUP_IP_DCCP 0 +#define GROUP_IP_UDPLITE 0 #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) @@ -860,6 +862,8 @@ enum e_optcode { OPT_TUN_DEVICE, /* tun: /dev/net/tun ... */ OPT_TUN_NAME, /* tun: tun0 */ OPT_TUN_TYPE, /* tun: tun|tap */ + OPT_UDPLITE_RECV_CSCOV, + OPT_UDPLITE_SEND_CSCOV, OPT_UMASK, OPT_UNIX_BIND_TEMPNAME, /* UNIX domain sockets */ OPT_UNIX_TIGHTSOCKLEN,