From a846b94e6c1f00feb7dbed7a3aa9c25787e3a7af Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Tue, 24 Oct 2023 20:33:01 +0200 Subject: [PATCH] Implementation of DCCP socket addresses --- CHANGES | 9 +++++ Makefile.in | 4 +-- config.h.in | 4 +++ configure.ac | 26 +++++++++++++++ doc/socat.yo | 91 ++++++++++++++++++++++++++++++++++++++++++++++----- socat.c | 5 +++ sysincludes.h | 4 ++- test.sh | 86 +++++++++++++++++++++++++++++++++++++++++++++--- xio-dccp.c | 46 ++++++++++++++++++++++++++ xio-dccp.h | 17 ++++++++++ xio-openssl.c | 2 +- xio.h | 2 +- xiohelp.c | 2 +- xiomodes.h | 1 + xioopen.c | 26 +++++++++++++++ xioopts.c | 12 +++++++ xioopts.h | 21 ++++++------ 17 files changed, 330 insertions(+), 28 deletions(-) create mode 100644 xio-dccp.c create mode 100644 xio-dccp.h diff --git a/CHANGES b/CHANGES index 8e5fb7a..e7f93ca 100644 --- a/CHANGES +++ b/CHANGES @@ -170,6 +170,15 @@ Features: than pipe buffer. Socat now tries to detect if transfer block size is large enough and issues a warning. + Added direct support of DCCP protocol, new addresses: + DCCP-CONNECT (DCCP) + DCCP-LISTEN (DCCP-L) + DCCP4-CONNECT (DCCP4) + DCCP4-LISTEN (DCCP4-L) + DCCP6-CONNECT (DCCP6) + DCCP6-LISTEN (DCCP6-L) + New option: dccp-set-ccid (ccid) + 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 3f8d86f..5f67f8b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -49,7 +49,7 @@ XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \ xio-socketpair.c xio-gopen.c xio-creat.c xio-file.c xio-named.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-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-progcall.c xio-exec.c xio-system.c xio-shell.c \ xio-termios.c xio-readline.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-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h xio-dccp.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 4ef4dd1..f0d2842 100644 --- a/config.h.in +++ b/config.h.in @@ -282,6 +282,9 @@ /* Define if you have the header file. */ #undef HAVE_LINUX_IF_TUN_H +/* Define if you have the header file. */ +#undef HAVE_LINUX_DCCP_H + /* Define if you have the header file. */ #undef HAVE_LINUX_VM_SOCKETS_H @@ -710,6 +713,7 @@ #undef WITH_TCP #undef WITH_UDP #undef WITH_SCTP +#undef WITH_DCCP #undef WITH_LISTEN #undef WITH_POSIXMQ #undef WITH_SOCKS4 diff --git a/configure.ac b/configure.ac index 41a9844..f444ad8 100644 --- a/configure.ac +++ b/configure.ac @@ -369,6 +369,32 @@ else fi fi +AC_MSG_CHECKING(whether to include DCCP support) +AC_ARG_ENABLE(dccp, [ --disable-dccp disable DCCP support], + [case "$enableval" in + no) AC_MSG_RESULT(no); WITH_DCCP= ;; + *) AC_MSG_RESULT(yes); WITH_DCCP=1 ;; + esac], + [AC_MSG_RESULT(yes); WITH_DCCP=1 ]) + +if test -n "$WITH_DCCP"; then +AC_MSG_CHECKING(for IPPROTO_DCCP) +AC_CACHE_VAL(sc_cv_define_ipproto_dccp, +[AC_TRY_COMPILE([#include +#include ], +[IPPROTO_DCCP;], +[sc_cv_define_ipproto_dccp=yes], +[sc_cv_define_ipproto_dccp=no])]) +AC_MSG_RESULT($sc_cv_define_ipproto_dccp) +if test $sc_cv_define_ipproto_dccp = yes; then + AC_DEFINE(WITH_DCCP) + AC_CHECK_HEADER(linux/dccp.h, + AC_DEFINE(HAVE_LINUX_DCCP_H)) +else + AC_MSG_WARN([IPPROTO_DCCP undefined, disabling DCCP support]) +fi +fi + AC_MSG_CHECKING(whether to include vsock support) AC_ARG_ENABLE(vsock, [ --disable-vsock disable vsock support], [case "$enableval" in diff --git a/doc/socat.yo b/doc/socat.yo index e00741d..c7a81a4 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -51,10 +51,10 @@ manpagedescription() Socat() is a command line based utility that establishes two bidirectional byte streams and transfers data between them. Because the streams can be constructed -from a large set of different types of data sinks and sources +from a large set of different types of data sinks and sources (see link(address types)(ADDRESS_TYPES)), and because lots of link(address options)(ADDRESS_OPTIONS) may be applied to the streams, socat can -be used for many different purposes. +be used for many different purposes. Filan() is a utility that prints information about its active file descriptors to stdout. It has been written for debugging socat(), but might be @@ -314,6 +314,69 @@ label(ADDRESS_CREAT)dit(bf(tt(CREATE:))) link(unlink-late)(OPTION_UNLINK_LATE), link(append)(OPTION_APPEND)nl() See also: link(OPEN)(ADDRESS_OPEN), link(GOPEN)(ADDRESS_GOPEN) + +label(ADDRESS_DCCP_CONNECT)dit(bf(tt(DCCP-CONNECT::)) (bf(tt(DCCP::)))) + Establishes a DCCP connect to the specified [link(IP + address)(TYPE_IP_ADDRESS)] and [link(DCCP service)(TYPE_TCP_SERVICE)] + using IP version 4 or 6 depending on address specification, name + resolution, or option link(pf)(OPTION_PROTOCOL_FAMILY).nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(SCTP)(GROUP_SCTP),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY) nl() + Useful options: + link(bind)(OPTION_BIND), + link(connect-timeout)(OPTION_CONNECT_TIMEOUT), + link(tos)(OPTION_TOS), + link(dccp-set-ccid)(OPTION_DCCP_SET_CCID), + link(nonblock)(OPTION_NONBLOCK), + link(sourceport)(OPTION_SOURCEPORT), + link(retry)(OPTION_RETRY), + link(readbytes)(OPTION_READBYTES)nl() + See also: + link(DCCP4-CONNECT)(ADDRESS_DCCP4_CONNECT), + link(DCCP6-CONNECT)(ADDRESS_DCCP6_CONNECT), + link(DCCP-LISTEN)(ADDRESS_DCCP_LISTEN), + link(TCP-CONNECT)(ADDRESS_TCP_CONNECT) + link(SCTP-CONNECT)(ADDRESS_SCTP_CONNECT) +label(ADDRESS_DCCP4_CONNECT)dit(bf(tt(DCCP4-CONNECT::)) (bf(tt(DCCP4::)))) + Like link(DCCP-CONNECT)(ADDRESS_DCCP_CONNECT), but only supports IPv4 protocol.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(DCCP)(GROUP_DCCP),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY) nl() +label(ADDRESS_DCCP6_CONNECT)dit(bf(tt(DCCP6-CONNECT::)) (bf(tt(DCCP6::)))) + Like link(DCCP-CONNECT)(ADDRESS_DCCP_CONNECT), but only supports IPv6 protocol.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP6)(GROUP_IP6),link(DCCP)(GROUP_DCCP),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY) nl() + +label(ADDRESS_DCCP_LISTEN)dit(bf(tt(DCCP-LISTEN:)) (bf(tt(DCCP-L:)))) + Listens on [link(DCCP service)(TYPE_TCP_SERVICE)] and accepts an + DCCP connection. The IP version is 4 or the one specified with + address option link(pf)(OPTION_PROTOCOL_FAMILY), socat option + (link(-4)(option_4), link(-6)(option_6)), or environment variable link(SOCAT_DEFAULT_LISTEN_IP)(ENV_SOCAT_DEFAULT_LISTEN_IP). + Note that opening + this address usually blocks until a client connects.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(DCCP)(GROUP_DCCP),link(RETRY)(GROUP_RETRY) nl() + Useful options: + link(fork)(OPTION_FORK), + link(bind)(OPTION_BIND), + link(range)(OPTION_RANGE), + link(max-children)(OPTION_MAX_CHILDREN), + link(backlog)(OPTION_BACKLOG), + link(accept-timeout)(OPTION_ACCEPT_TIMEOUT), + link(dccp-set-sid)(OPTION_DCCP_SET_CCID), + link(su)(OPTION_SUBSTUSER), + link(reuseaddr)(OPTION_SO_REUSEADDR), + link(retry)(OPTION_RETRY)nl() + See also: + link(DCCP4-LISTEN)(ADDRESS_DCCP4_LISTEN), + link(DCCP6-LISTEN)(ADDRESS_DCCP6_LISTEN), + link(TCP-LISTEN)(ADDRESS_TCP_LISTEN), + link(SCTP-LISTEN)(ADDRESS_SCTP_LISTEN), + link(DCCP-CONNECT)(ADDRESS_DCCP_CONNECT) +label(ADDRESS_DCCP4_LISTEN)dit(bf(tt(DCCP4-LISTEN:)) (bf(tt(DCCP4-L:)))) + Like link(DCCP-LISTEN)(ADDRESS_DCCP_LISTEN), but only supports IPv4 + protocol.nl() + Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP4)(GROUP_IP4),link(DCCP)(GROUP_DCCP),link(RETRY)(GROUP_RETRY) nl() +label(ADDRESS_DCCP6_LISTEN)dit(bf(tt(DCCP6-LISTEN:)) (bf(tt(DCCP6-L:)))) + Like link(DCCP-LISTEN)(ADDRESS_DCCP_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(DCCP)(GROUP_DCCP),link(RETRY)(GROUP_RETRY) nl() + label(ADDRESS_EXEC)dit(bf(tt(EXEC:))) Forks a sub process that establishes communication with its parent process and invokes the specified program with code(execvp()). @@ -2651,10 +2714,22 @@ enddit() startdit()enddit()nl() -em(bf(UDP, TCP, and SCTP option group)) +label(GROUP_DCCP)em(bf(DCCP option group)) + +These options may be applied to DCCP sockets. +startdit() +label(OPTION_DCCP_SET_CCID)dit(bf(tt(dccp-set-ccid=))) +dit(bf(tt(ccid=))) + Selects the desired congestion control mechanism (CCID). +enddit() + +startdit()enddit()nl() + + +em(bf(UDP, TCP, SCTP, and DCCP option group)) Here we find options that are related to the network port mechanism and thus -can be used with UDP, TCP, and SCTP client and server addresses. +can be used with UDP, TCP, SCTP, and DCCP client and server addresses. startdit() label(OPTION_SOURCEPORT)dit(bf(tt(sourceport=))) For outgoing (client) TCP and UDP connections, it sets the source @@ -4080,10 +4155,9 @@ htmlcommand(
socat \ TCP-LISTEN:10021,reuseaddr,socktype=6,protocol=33,fork \ PIPE
) -is a simple DCCP echo server. It uses socat()s TCP procedures, but changes the +is a simple DCCP echo server. DCCP is now directly provisioned in socat(), +however this example shows how use socat()s TCP procedures and change the socket type to SOCK_DCCP=6 (on Linux) and the IP protocol to IPPROTO_DCCP=33. -This works in contrast to attempts with UDP basis, even though DCCP is named a -datagram protocol. label(EXAMPLE_GENERIC_DCCP_CLIENT) @@ -4099,7 +4173,8 @@ mancommand(\.fi) htmlcommand(
socat - \ TCP::10021,reuseaddr,socktype=6,protocol=33,fork
) -is a simple DCCP client. It uses socat()s TCP procedures, but changes the +is a simple DCCP client. DCCP is now directly provisioned in socat(), +however this example shows how use socat()s TCP procedures, but changes the socket type to SOCK_DCCP=6 (on Linux) and the IP protocol to IPPROTO_DCCP=33. diff --git a/socat.c b/socat.c index c857b0b..f13f813 100644 --- a/socat.c +++ b/socat.c @@ -599,6 +599,11 @@ void socat_version(FILE *fd) { #else fputs(" #undef WITH_SCTP\n", fd); #endif +#ifdef WITH_DCCP + fprintf(fd, " #define WITH_DCCP %d\n", WITH_DCCP); +#else + fputs(" #undef WITH_DCCP\n", fd); +#endif #ifdef WITH_LISTEN fprintf(fd, " #define WITH_LISTEN %d\n", WITH_LISTEN); #else diff --git a/sysincludes.h b/sysincludes.h index b960dc4..0c2aff3 100644 --- a/sysincludes.h +++ b/sysincludes.h @@ -150,7 +150,9 @@ #if HAVE_LINUX_IF_TUN_H #include #endif - +#if HAVE_LINUX_DCCP_H +#include +#endif #if HAVE_TERMIOS_H && _WITH_TERMIOS #include #endif diff --git a/test.sh b/test.sh index 84f5909..dd4ed16 100755 --- a/test.sh +++ b/test.sh @@ -978,9 +978,25 @@ runssctp6 () { return 0; } -routesip6 () { - runsip6 >/dev/null || { echo route6; return 1; } - ping -c 1 -s 0 -6 2606:4700:4700::1111 >/dev/null 2>&1 || { echo route6; return 1; } +# check if DCCP on IPv4 is available on host +runsdccp4 () { + runsip4 >/dev/null || { echo DCCP4; return 1; } + $SOCAT -h |grep -i ' DCCP4-' >/dev/null || return 1 + $SOCAT /dev/null DCCP4-L:0,accept-timeout=0.001 2>/dev/null || return 1; + return 0; +} + +# check if DCCP on IPv6 is available on host +runsdccp6 () { + runsip6 >/dev/null || { echo DCCP6; return 1; } + $SOCAT -h |grep -i ' DCCP6-' >/dev/null || return 1 + $SOCAT /dev/null DCCP6-L:0,accept-timeout=0.001 2>/dev/null || return 1; + return 0; +} + +# check if UNIX domain sockets work +runsunix () { + # for now... return 0; } @@ -1066,7 +1082,7 @@ checkconds() { if [ "$inet" ]; then if [ -z "$NTERNET" ]; then - echo "Use test.sh option -internet" + echo "Use test.sh option --internet" return -1 fi fi @@ -18127,6 +18143,68 @@ esac N=$((N+1)) +NAME=DCCP4 +case "$TESTS" in +*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%dccp%*|*%listen%*|*%$NAME%*) +TEST="$NAME: DCCP over IPv4" +if ! eval $NUMCOND; then : +elif ! cond=$(checkconds "" "" "" \ + "IP4 DCCP LISTEN STDIO PIPE" \ + "DCCP4-LISTEN PIPE STDIN STDOUT DCCP4" \ + "so-reuseaddr" \ + "dccp4" ); then + $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N + numCANT=$((numCANT+1)) + listCANT="$listCANT $N" +else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +newport dccp4; tsl=$PORT +ts="127.0.0.1:$tsl" +da="test$N $(date) $RANDOM" +CMD1="$TRACE $SOCAT $opts DCCP4-LISTEN:$tsl,$REUSEADDR PIPE" +CMD2="$TRACE $SOCAT $opts STDIN!!STDOUT DCCP4:$ts" +printf "test $F_n $TEST... " $N +$CMD1 >"$tf" 2>"${te}1" & +pid1=$! +waittcp4port $tsl 1 +echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" +if [ $? -ne 0 ]; then + $PRINTF "$FAILED\n" + echo "$CMD0 &" + cat "${te}0" >&2 + echo "$CMD1" + cat "${te}1" >&2 + numFAIL=$((numFAIL+1)) + listFAIL="$listFAIL $N" + namesFAIL="$namesFAIL $NAME" +elif ! echo "$da" |diff - "$tf" >"$tdiff"; then + $PRINTF "$FAILED\n" + echo "$CMD0 &" + cat "${te}0" >&2 + echo "$CMD1" + cat "${te}1" >&2 + echo "// diff:" >&2 + cat "$tdiff" >&2 + numFAIL=$((numFAIL+1)) + listFAIL="$listFAIL $N" + namesFAIL="$namesFAIL $NAME" +else + $PRINTF "$OK\n" + if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi + if [ "$DEBUG" ]; then cat "${te}0" >&2; fi + if [ "$VERBOSE" ]; then echo "$CMD1"; fi + if [ "$DEBUG" ]; then cat "${te}1" >&2; fi + numOK=$((numOK+1)) +fi +kill $pid1 2>/dev/null +wait +fi ;; # NUMCOND, checkconds +esac +N=$((N+1)) + + # end of common tests ################################################################################## diff --git a/xio-dccp.c b/xio-dccp.c new file mode 100644 index 0000000..4a37416 --- /dev/null +++ b/xio-dccp.c @@ -0,0 +1,46 @@ +/* source: xio-dccp.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 DCCP related functions and options */ + +#include "xiosysincludes.h" + +#if WITH_DCCP + +#include "xioopen.h" +#include "xio-listen.h" +#include "xio-ip4.h" +#include "xio-ipapp.h" +#include "xio-dccp.h" + +/****** DCCP addresses ******/ + +#if WITH_IP4 || WITH_IP6 +const struct addrdesc xioaddr_dccp_connect = { "DCCP-CONNECT", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_DCCP|GROUP_CHILD|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_UNSPEC HELP("::") }; +#if WITH_LISTEN +const struct addrdesc xioaddr_dccp_listen = { "DCCP-LISTEN", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_DCCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_UNSPEC HELP(":") }; +#endif +#endif + +#if WITH_IP4 +const struct addrdesc xioaddr_dccp4_connect = { "DCCP4-CONNECT", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_DCCP|GROUP_CHILD|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_INET HELP("::") }; +#if WITH_LISTEN +const struct addrdesc xioaddr_dccp4_listen = { "DCCP4-LISTEN", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_DCCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_INET HELP(":") }; +#endif +#endif /* WITH_IP4 */ + +#if WITH_IP6 +const struct addrdesc xioaddr_dccp6_connect = { "DCCP6-CONNECT", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_DCCP|GROUP_CHILD|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_INET6 HELP("::") }; +#if WITH_LISTEN +const struct addrdesc xioaddr_dccp6_listen = { "DCCP6-LISTEN", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_DCCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_INET6 HELP(":") }; +#endif +#endif /* WITH_IP6 */ + +/****** DCCP address options ******/ + +#if defined(SOL_DCCP) && defined(DCCP_SOCKOPT_QPOLICY_ID) +const struct optdesc xioopt_dccp_set_ccid = { "dccp-set-ccid", "ccid", OPT_DCCP_SET_CCID, GROUP_IP_DCCP, PH_PASTSOCKET, TYPE_BYTE, OFUNC_SOCKOPT, SOL_DCCP, DCCP_SOCKOPT_CCID }; +#endif + +#endif /* WITH_DCCP */ diff --git a/xio-dccp.h b/xio-dccp.h new file mode 100644 index 0000000..0ec5455 --- /dev/null +++ b/xio-dccp.h @@ -0,0 +1,17 @@ +/* source: xio-dccp.h */ +/* Copyright Gerhard Rieger and contributors (see file CHANGES) */ +/* Published under the GNU General Public License V.2, see file COPYING */ + +#ifndef __xio_dccp_h_included +#define __xio_dccp_h_included 1 + +extern const struct addrdesc xioaddr_dccp_connect; +extern const struct addrdesc xioaddr_dccp_listen; +extern const struct addrdesc xioaddr_dccp4_connect; +extern const struct addrdesc xioaddr_dccp4_listen; +extern const struct addrdesc xioaddr_dccp6_connect; +extern const struct addrdesc xioaddr_dccp6_listen; + +extern const struct optdesc xioopt_dccp_set_ccid; + +#endif /* !defined(__xio_dccp_h_included) */ diff --git a/xio-openssl.c b/xio-openssl.c index 4ea3a51..2948cab 100644 --- a/xio-openssl.c +++ b/xio-openssl.c @@ -640,7 +640,7 @@ static int xioopen_openssl_listen( /* this can fork() for us; it only returns on error or on successful establishment of connection */ - if (ipproto == IPPROTO_TCP) { + if (ipproto == IPPROTO_TCP || ipproto == IPPROTO_DCCP) { result = _xioopen_listen(sfd, xioflags, (struct sockaddr *)us, uslen, opts, pf, socktype, ipproto, diff --git a/xio.h b/xio.h index 71bddc6..1a68819 100644 --- a/xio.h +++ b/xio.h @@ -95,7 +95,7 @@ enum xiotag { } ; /* Keep condition consistent with xioopts.h:GROUP_*! */ -#if WITH_SCTP || WITH_POSIXMQ +#if WITH_POSIXMQ || WITH_SCTP || WITH_DCCP typedef uint64_t groups_t; #define F_groups_t F_uint64_x #else diff --git a/xiohelp.c b/xiohelp.c index b05127a..519b464 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", - "SCTP", "POSIXMQ" + "POSIXMQ", "SCTP", "DCCP" } ; /* keep consistent with xioopts.h:enum ephase ! */ diff --git a/xiomodes.h b/xiomodes.h index 68b6fbd..911bc6d 100644 --- a/xiomodes.h +++ b/xiomodes.h @@ -31,6 +31,7 @@ #include "xio-tcp.h" #include "xio-udp.h" #include "xio-sctp.h" +#include "xio-dccp.h" #include "xio-socks.h" #include "xio-socks5.h" #include "xio-proxy.h" diff --git a/xioopen.c b/xioopen.c index 3ffa375..4599d1b 100644 --- a/xioopen.c +++ b/xioopen.c @@ -43,6 +43,32 @@ const struct addrname addressnames[] = { #endif #if WITH_GENERICSOCKET { "DATAGRAM", &xioaddr_socket_datagram }, +#endif +#if (WITH_IP4 || WITH_IP6) && WITH_DCCP + { "DCCP", &xioaddr_dccp_connect }, + { "DCCP-CONNECT", &xioaddr_dccp_connect }, +#if WITH_LISTEN + { "DCCP-L", &xioaddr_dccp_listen }, + { "DCCP-LISTEN", &xioaddr_dccp_listen }, +#endif +#if WITH_IP4 + { "DCCP4", &xioaddr_dccp4_connect }, + { "DCCP4-CONNECT", &xioaddr_dccp4_connect }, +#if WITH_LISTEN + { "DCCP4-L", &xioaddr_dccp4_listen }, + { "DCCP4-LISTEN", &xioaddr_dccp4_listen }, +#endif +#endif /* WITH_IP4 */ +#if WITH_IP6 + { "DCCP6", &xioaddr_dccp6_connect }, + { "DCCP6-CONNECT", &xioaddr_dccp6_connect }, +#if WITH_LISTEN + { "DCCP6-L", &xioaddr_dccp6_listen }, + { "DCCP6-LISTEN", &xioaddr_dccp6_listen }, +#endif +#endif /* WITH_IP6 */ +#endif /* (WITH_IP4 || WITH_IP6) && WITH_DCCP */ +#if WITH_GENERICSOCKET { "DGRAM", &xioaddr_socket_datagram }, #endif #if WITH_OPENSSL diff --git a/xioopts.c b/xioopts.c index a428586..a6d1849 100644 --- a/xioopts.c +++ b/xioopts.c @@ -96,6 +96,12 @@ bool xioopts_ignoregroups; # define IF_SCTP(a,b) #endif +#if WITH_DCCP +# define IF_DCCP(a,b) {a,b}, +#else +# define IF_DCCP(a,b) +#endif + #if WITH_SOCKS4 # define IF_SOCKS4(a,b) {a,b}, #else @@ -315,6 +321,9 @@ const struct optname optionnames[] = { IF_ANY ("bytes", &opt_readbytes) IF_OPENSSL("cafile", &opt_openssl_cafile) IF_OPENSSL("capath", &opt_openssl_capath) +#if defined(SOL_DCCP) && defined(DCCP_SOCKOPT_QPOLICY_ID) + IF_DCCP ("ccid", &xioopt_dccp_set_ccid) +#endif IF_ANY ("cd", &opt_chdir) IF_OPENSSL("cert", &opt_openssl_certificate) IF_OPENSSL("certificate", &opt_openssl_certificate) @@ -392,6 +401,9 @@ const struct optname optionnames[] = { IF_TERMIOS("ctlecho", &opt_echoctl) IF_TERMIOS("ctty", &opt_tiocsctty) IF_EXEC ("dash", &opt_dash) +#if defined(SOL_DCCP) && defined(DCCP_SOCKOPT_QPOLICY_ID) + IF_DCCP ("dccp-set-ccid", &xioopt_dccp_set_ccid) +#endif IF_SOCKET ("debug", &opt_so_debug) /*IF_RESOLVE("debug", &opt_res_debug)*/ #ifdef O_DEFER diff --git a/xioopts.h b/xioopts.h index f0f9894..21281ba 100644 --- a/xioopts.h +++ b/xioopts.h @@ -182,7 +182,6 @@ enum e_func { #define GROUP_IP_UDP 0x01000000 /* not yet used? */ #define GROUP_IP_TCP 0x02000000 -#define GROUP_IPAPP (GROUP_IP_UDP|GROUP_IP_TCP|GROUP_IP_SCTP) /* true: indicates one of UDP, TCP, SCTP */ #define GROUP_IP_SOCKS4 0x04000000 #define GROUP_OPENSSL 0x08000000 @@ -191,19 +190,20 @@ enum e_func { #define GROUP_HTTP 0x40000000 /* any HTTP client */ /* Keep condition consistent with xio.h:groups_t! */ -#if WITH_SCTP || WITH_POSIXMQ +#if WITH_POSIXMQ || WITH_SCTP || WITH_DCCP /* The following groups are not expected on systems without uint64_t */ -/* The following groups are not expected on systems withous uint64_t */ -#define GROUP_IP_SCTP 0x0100000000U -#define GROUP_POSIXMQ 0x0200000000U -#define GROUP_ALL 0x03ffffffffU -#else -#define GROUP_IP_SCTP 0 +#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_POSIXMQ 0 +#define GROUP_IP_SCTP 0 +#define GROUP_IP_DCCP 0 #define GROUP_ALL 0xffffffffU -#endif +#endif /* !(WITH_POSIXMQ || WITH_SCTP || WITH_DCCP) */ -#define GROUP_IPAPP (GROUP_IP_UDP|GROUP_IP_TCP|GROUP_IP_SCTP) /* true: indicates one of UDP, TCP, SCTP */ +#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_ANY (GROUP_PROCESS|GROUP_APPL) @@ -300,6 +300,7 @@ enum e_optcode { OPT_CSIZE, /* termios.c_cflag */ OPT_CSTOPB, /* termios.c_cflag */ OPT_DASH, /* exec() */ + OPT_DCCP_SET_CCID, OPT_ECHO, /* termios.c_lflag */ OPT_ECHOCTL, /* termios.c_lflag */ OPT_ECHOE, /* termios.c_lflag */