Added VSOCK stream addresses

This commit is contained in:
Gerhard Rieger 2020-12-26 22:46:36 +01:00
parent 1c7ddfef73
commit 1502f0cdcb
18 changed files with 442 additions and 4 deletions

View file

@ -170,6 +170,9 @@ New features:
Test: PROXYAUTHFILE Test: PROXYAUTHFILE
Thanks to Charles Stephens for sending an initial patch. Thanks to Charles Stephens for sending an initial patch.
Added AF_VSOCK support with VSOCK-CONNECT and VSOCK-LISTEN addresses.
Developed by Stefano Garzarella.
####################### V 1.7.3.4: ####################### V 1.7.3.4:
Corrections: Corrections:

View file

@ -232,6 +232,20 @@ $ socat -d -d tcp:localhost:25,crlf,nodelay exec:'/usr/sbin/chat -v -s "\"220 \"
# socat readline TCP6:[::1]:21 # if your inetd/ftp is listening on ip6 # socat readline TCP6:[::1]:21 # if your inetd/ftp is listening on ip6
//////////////////////////////////////////////////////////////////////////////
// VSOCK
# start a linux VM with cid=21
# qemu-system-x86_64 -m 1G -smp 2 -cpu host -M accel=kvm \
# -drive if=virtio,file=/path/to/fedora.img,format=qcow2 \
# -device vhost-vsock-pci,guest-cid=21
# guest listens on port 1234 and host connects to it
guest$ socat - vsock-listen:1234
host$ socat - vsock-connect:21:1234
# host (well know CID_HOST = 2) listens on port 4321 and guest connects to it
host$ socat - vsock-listen:4321
guest$ socat - vsock-connect:2:4321
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// application server solutions // application server solutions

View file

@ -45,7 +45,7 @@ XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \
xiolayer.c xioshutdown.c xioclose.c xioexit.c \ xiolayer.c xioshutdown.c xioclose.c xioexit.c \
xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \ xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \
xio-gopen.c xio-creat.c xio-file.c xio-named.c \ xio-gopen.c xio-creat.c xio-file.c xio-named.c \
xio-socket.c xio-interface.c xio-listen.c xio-unix.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-rawip.c \ xio-sctp.c xio-rawip.c \
xio-socks.c xio-proxy.c xio-udp.c \ xio-socks.c xio-proxy.c xio-udp.c \
@ -63,7 +63,7 @@ HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.
xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.h \ xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.h \
xiomodes.h xiolayer.h xio-process.h xio-fd.h xio-fdnum.h xio-stdio.h \ xiomodes.h xiolayer.h xio-process.h xio-fd.h xio-fdnum.h xio-stdio.h \
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-socket.h xio-interface.h xio-listen.h xio-unix.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-ip.h xio-ip4.h xio-ip6.h xio-rawip.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-socks.h xio-proxy.h xio-progcall.h xio-exec.h \ xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \

View file

@ -279,6 +279,9 @@
/* Define if you have the <linux/if_tun.h> header file. */ /* Define if you have the <linux/if_tun.h> header file. */
#undef HAVE_LINUX_IF_TUN_H #undef HAVE_LINUX_IF_TUN_H
/* Define if you have the <linux/vm_sockets.h> header file. */
#undef HAVE_LINUX_VM_SOCKETS_H
/* Define if you have the <netpacket/packet.h> header file. */ /* Define if you have the <netpacket/packet.h> header file. */
#undef HAVE_NETPACKET_PACKET_H #undef HAVE_NETPACKET_PACKET_H
@ -660,6 +663,7 @@
#undef WITH_LISTEN #undef WITH_LISTEN
#undef WITH_SOCKS4 #undef WITH_SOCKS4
#undef WITH_SOCKS4A #undef WITH_SOCKS4A
#undef WITH_VSOCK
#undef WITH_PROXY #undef WITH_PROXY
#undef WITH_EXEC #undef WITH_EXEC
#undef WITH_SYSTEM #undef WITH_SYSTEM

View file

@ -349,6 +349,29 @@ else
fi fi
fi fi
AC_MSG_CHECKING(whether to include vsock support)
AC_ARG_ENABLE(vsock, [ --disable-vsock disable vsock support],
[case "$enableval" in
no) AC_MSG_RESULT(no); WITH_VSOCK= ;;
*) AC_MSG_RESULT(yes); WITH_VSOCK=1 ;;
esac],
[AC_MSG_RESULT(yes); WITH_VSOCK=1 ])
if test "$WITH_VSOCK"; then
AC_CHECK_HEADER(linux/vm_sockets.h,
AC_DEFINE(HAVE_LINUX_VM_SOCKETS_H),
[WITH_VSOCK=;
AC_MSG_WARN([include file linux/vm_sockets.h not found, disabling vsock])],
[AC_INCLUDES_DEFAULT
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
]
)
fi
if test "$WITH_VSOCK"; then
AC_DEFINE(WITH_VSOCK)
fi
AC_MSG_CHECKING(whether to include listen support) AC_MSG_CHECKING(whether to include listen support)
AC_ARG_ENABLE(listen, [ --disable-listen disable listen support], AC_ARG_ENABLE(listen, [ --disable-listen disable listen support],
[case "$enableval" in [case "$enableval" in

View file

@ -1352,6 +1352,37 @@ label(ADDRESS_UNIX_CLIENT)dit(bf(tt(UNIX-CLIENT:<filename>)))
link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO), link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO),
link(GOPEN)(ADDRESS_GOPEN) link(GOPEN)(ADDRESS_GOPEN)
label(ADDRESS_VSOCK_CONNECT)dit(bf(tt(VSOCK-CONNECT:<cid>:<port>)))
Establishes a VSOCK stream connection to the specified <cid> [link(VSOCK
cid)(TYPE_VSOCK_ADDRESS)] and <port> [link(VSOCK port)(TYPE_VSOCK_PORT)].nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(CHILD)(GROUP_CHILD),link(RETRY)(GROUP_RETRY) nl()
Useful options:
link(bind)(OPTION_BIND),
link(pf)(OPTION_PROTOCOL_FAMILY),
link(connect-timeout)(OPTION_CONNECT_TIMEOUT),
link(retry)(OPTION_RETRY),
link(readbytes)(OPTION_READBYTES)nl()
See also:
link(VSOCK-LISTEN)(ADDRESS_VSOCK_LISTEN),
label(ADDRESS_VSOCK_LISTEN)dit(bf(tt(VSOCK-LISTEN:<port>)))
Listens on <port> [link(VSOCK port)(TYPE_VSOCK_PORT)] and accepts a
VSOCK connection.
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(RETRY)(GROUP_RETRY) nl()
Useful options:
link(fork)(OPTION_FORK),
link(bind)(OPTION_BIND),
link(pf)(OPTION_PROTOCOL_FAMILY),
link(max-children)(OPTION_MAX_CHILDREN),
link(backlog)(OPTION_BACKLOG),
link(su)(OPTION_SUBSTUSER),
link(reuseaddr)(OPTION_REUSEADDR),
link(retry)(OPTION_RETRY),
link(cool-write)(OPTION_COOL_WRITE)nl()
See also:
link(VSOCK-CONNECT)(ADDRESS_VSOCK_CONNECT)
dit(bf(tt(ABSTRACT-CONNECT:<string>))) dit(bf(tt(ABSTRACT-CONNECT:<string>)))
dit(bf(tt(ABSTRACT-LISTEN:<string>))) dit(bf(tt(ABSTRACT-LISTEN:<string>)))
dit(bf(tt(ABSTRACT-SENDTO:<string>))) dit(bf(tt(ABSTRACT-SENDTO:<string>)))
@ -1885,7 +1916,8 @@ label(OPTION_BIND)dit(bf(tt(bind=<sockname>)))
Binds the socket to the given socket address using the code(bind()) system Binds the socket to the given socket address using the code(bind()) system
call. The form of <sockname> is socket domain dependent: call. The form of <sockname> is socket domain dependent:
IP4 and IP6 allow the form [hostname|hostaddress][:(service|port)] (link(example)(EXAMPLE_OPTION_BIND_TCP4)), IP4 and IP6 allow the form [hostname|hostaddress][:(service|port)] (link(example)(EXAMPLE_OPTION_BIND_TCP4)),
unixdomain() sockets require link(<filename>)(TYPE_FILENAME). unixdomain() sockets require link(<filename>)(TYPE_FILENAME),
VSOCK allow the form [cid][:(port)].
label(OPTION_CONNECT_TIMEOUT)dit(bf(tt(connect-timeout=<seconds>))) label(OPTION_CONNECT_TIMEOUT)dit(bf(tt(connect-timeout=<seconds>)))
Abort the connection attempt after <seconds> [link(timeval)(TYPE_TIMEVAL)] Abort the connection attempt after <seconds> [link(timeval)(TYPE_TIMEVAL)]
with error status. with error status.
@ -3041,6 +3073,14 @@ label(TYPE_USER)dit(user)
If the first character is a decimal digit, the value is read with If the first character is a decimal digit, the value is read with
code(strtoul()) as unsigned integer specifying a user id. Otherwise, it must code(strtoul()) as unsigned integer specifying a user id. Otherwise, it must
be an existing user name. be an existing user name.
label(TYPE_VSOCK_ADDRESS)dit(VSOCK cid)
A uint32_t (32 bit unsigned number) specifying a VSOCK Context Identifier
(CID), read with code(strtoul()).
There are several special addresses: VMADDR_CID_ANY (-1U) means any address
for binding; VMADDR_CID_HOST (2) is the well-known address of the host.
label(TYPE_VSOCK_PORT)dit(VSOCK port)
A uint32_t (32 bit unsigned number) specifying a VSOCK port, read
with code(strtoul()).
enddit() enddit()
@ -3444,6 +3484,45 @@ streaming eg. via TCP or SSL does not guarantee to retain packet boundaries and
may thus cause packet loss. may thus cause packet loss.
label(EXAMPLE_ADDRESS_VSOCK)
dit(bf(tt(socat - VSOCK-CONNECT:2:1234)))
establishes a VSOCK connection with the host (host is always reachable with
the well-know CID=2) on 1234 port.
dit(bf(tt(socat - VSOCK-LISTEN:1234)))
listens for a VSOCK connection on 1234 port.
dit(bf(tt(socat - VSOCK-CONNECT:31:4321,bind:5555)))
establishes a VSOCK connection with the guest that have CID=31 on 1234 port,
binding the local socket to the 5555 port.
dit(bf(tt(socat VSOCK-LISTEN:3333,reuseaddr,fork VSOCK-CONNECT:42,3333)))
starts a forwarder that accepts VSOCK connections on port 3333, and directs
them to the guest with CID=42 on the same port.
dit(bf(tt(socat VSOCK-LISTEN:22,reuseaddr,fork TCP:localhost:22)))
forwards VSOCK connections from 22 port to the local SSH server.
Running this in a VM allows you to connect via SSH from the host using VSOCK,
as in the example below.
dit(bf(tt(socat TCP4-LISTEN:22222,reuseaddr,fork VSOCK-CONNECT:33:22)))
forwards TCP connections from 22222 port to the guest with CID=33 listening on
VSOCK port 22.
Running this in the host, allows you to connect via SSH running
"ssh -p 22222 user@localhost", if the guest runs the example above.
label(EXAMPLE_INTERFACE) label(EXAMPLE_INTERFACE)
dit(bf(tt(socat PTY,link=/var/run/ppp,rawer INTERFACE:hdlc0))) dit(bf(tt(socat PTY,link=/var/run/ppp,rawer INTERFACE:hdlc0)))

View file

@ -528,6 +528,11 @@ void socat_version(FILE *fd) {
#else #else
fputs(" #undef WITH_SOCKS4A\n", fd); fputs(" #undef WITH_SOCKS4A\n", fd);
#endif #endif
#ifdef WITH_VSOCK
fprintf(fd, " #define WITH_VSOCK %d\n", WITH_VSOCK);
#else
fputs(" #undef WITH_VSOCK\n", fd);
#endif
#ifdef WITH_PROXY #ifdef WITH_PROXY
fprintf(fd, " #define WITH_PROXY %d\n", WITH_PROXY); fprintf(fd, " #define WITH_PROXY %d\n", WITH_PROXY);
#else #else

View file

@ -185,5 +185,8 @@
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#endif #endif
#if HAVE_LINUX_VM_SOCKETS_H
#include <linux/vm_sockets.h>
#endif
#endif /* !defined(__sysincludes_h_included) */ #endif /* !defined(__sysincludes_h_included) */

View file

@ -204,6 +204,10 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
#if WITH_IP6 #if WITH_IP6
case AF_INET6: sockaddr_inet6_info(&sau->ip6, cp, blen); case AF_INET6: sockaddr_inet6_info(&sau->ip6, cp, blen);
break; break;
#endif
#if WITH_VSOCK
case AF_VSOCK: sockaddr_vm_info(&sau->vm, cp, blen);
break;
#endif #endif
default: default:
n = xio_snprintf(cp, blen, "AF=%d ", sa->sa_family); n = xio_snprintf(cp, blen, "AF=%d ", sa->sa_family);
@ -297,6 +301,43 @@ char *sockaddr_inet4_info(const struct sockaddr_in *sa, char *buff, size_t blen)
} }
#endif /* WITH_IP4 */ #endif /* WITH_IP4 */
#if WITH_VSOCK
char *sockaddr_vm_info(const struct sockaddr_vm *sa, char *buff, size_t blen) {
if (xio_snprintf(buff, blen, "cid:%u port:%u", sa->svm_cid, sa->svm_port) >= blen) {
Warn("sockaddr_vm_info(): buffer too short");
buff[blen-1] = '\0';
}
return buff;
}
int sockaddr_vm_parse(struct sockaddr_vm *sa, const char *cid_str,
const char *port_str)
{
char *garbage = NULL;
if (!cid_str) {
sa->svm_cid = VMADDR_CID_ANY;
} else {
sa->svm_cid = strtoul(cid_str, &garbage, 0);
if (*garbage != '\0') {
Error1("sockaddr_vm - garbage in cid: \"%s\"", garbage);
return -EINVAL;
}
}
if (!port_str) {
sa->svm_port = VMADDR_PORT_ANY;
} else {
sa->svm_port = strtoul(port_str, &garbage, 0);
if (*garbage != '\0') {
Error1("sockaddr_vm - garbage in port: \"%s\"", garbage);
return -EINVAL;
}
}
return 0;
}
#endif /* WITH_IP4 */
#if !HAVE_INET_NTOP #if !HAVE_INET_NTOP
/* http://www.opengroup.org/onlinepubs/000095399/functions/inet_ntop.html */ /* http://www.opengroup.org/onlinepubs/000095399/functions/inet_ntop.html */
const char *inet_ntop(int pf, const void *binaddr, const char *inet_ntop(int pf, const void *binaddr,

View file

@ -27,6 +27,9 @@ union sockaddr_union {
#if WITH_IP6 #if WITH_IP6
struct sockaddr_in6 ip6; struct sockaddr_in6 ip6;
#endif /* WITH_IP6 */ #endif /* WITH_IP6 */
#if WITH_VSOCK
struct sockaddr_vm vm;
#endif /* WITH_IP6 */
#if WITH_INTERFACE #if WITH_INTERFACE
struct sockaddr_ll ll; struct sockaddr_ll ll;
#endif #endif
@ -68,6 +71,11 @@ extern char *sockaddr_inet4_info(const struct sockaddr_in *sa, char *buff, size_
#if WITH_IP6 #if WITH_IP6
extern char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen); extern char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen);
#endif /* WITH_IP6 */ #endif /* WITH_IP6 */
#if WITH_VSOCK
extern char *sockaddr_vm_info(const struct sockaddr_vm *sa, char *buff, size_t blen);
extern int sockaddr_vm_parse(struct sockaddr_vm *sa, const char *cid_str,
const char *port_str);
#endif /* WITH_VSOCK */
#if !HAVE_INET_NTOP #if !HAVE_INET_NTOP
extern const char *inet_ntop(int pf, const void *binaddr, extern const char *inet_ntop(int pf, const void *binaddr,
char *addrtext, socklen_t textlen); char *addrtext, socklen_t textlen);

57
test.sh
View file

@ -35,6 +35,7 @@ done
opt_t="-t $val_t" opt_t="-t $val_t"
UNAME=`uname` UNAME=`uname`
UNAME_R=`uname -r`
#MICROS=100000 #MICROS=100000
case "X$val_t" in case "X$val_t" in
@ -14588,6 +14589,62 @@ PORT=$((PORT+1))
N=$((N+1)) N=$((N+1))
# Test communication via vsock loopback socket
NAME=VSOCK_ECHO
case "$TESTS" in
*%$N%*|*%functions%*|*%vsock%*|*%socket%*|*%$NAME%*)
TEST="$NAME: test communication via vsock loopback socket"
# Start a listening echo server
# Connect with a client, send data and compare reply with original data
if ! eval $NUMCOND; then :; else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
CMD0="$TRACE $SOCAT $opts VSOCK-LISTEN:$PORT PIPE"
CMD1="$TRACE $SOCAT $opts - VSOCK-CONNECT:1:$PORT"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0" &
pid0=$!
sleep 1
echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
rc1=$?
kill $pid0 2>/dev/null; wait
if [ $rc1 -ne 0 ] && [ "$UNAME" != Linux ]; then
$PRINTF "${YELLOW}works only on Linux?${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif [ $rc1 -ne 0 ] && [ "$UNAME" = Linux ] && ! [[ $UNAME_R =~ ^[6-9]\.* ]] && ! [[ $UNAME_R =~ ^5\.[6-]\.* ]] && ! [[ $UNAME_R =~ ^5\.[1-9][0-9].* ]]; then
$PRINTF "${YELLOW}works only on Linux from 5.6${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif [ $rc1 -ne 0 ]; then
$PRINTF "$FAILED\n"
echo "$CMD0 &" >&2
cat "${te}0" >&2
echo "$CMD1" >&2
cat "${te}1" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
elif echo "$da" |diff - ${tf}1 >${tfdiff}$N; then
$PRINTF "$OK\n"
numOK=$((numOK+1))
else
$PRINTF "$FAILED\n"
echo "$CMD0 &" >&2
cat "${te}0" >&2
echo "$CMD1" >&2
cat "${te}1" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
fi
fi # NUMCOND
;;
esac
PORT=$((PORT+1))
N=$((N+1))
################################################################################## ##################################################################################
#================================================================================= #=================================================================================
# here come tests that might affect your systems integrity. Put normal tests # here come tests that might affect your systems integrity. Put normal tests

View file

@ -167,6 +167,17 @@ int xiogetaddrinfo(const char *node, const char *service,
if (service && service[0]=='\0') { if (service && service[0]=='\0') {
Error("empty port/service"); Error("empty port/service");
} }
#ifdef WITH_VSOCK
if (family == AF_VSOCK) {
error_num = sockaddr_vm_parse(&sau->vm, node, service);
if (error_num < 0)
return STAT_NORETRY;
return STAT_OK;
}
#endif /* WITH_VSOCK */
/* if service is numeric we don't want to have a lookup (might take long /* if service is numeric we don't want to have a lookup (might take long
with NIS), so we handle this specially */ with NIS), so we handle this specially */
if (service && isdigit(service[0]&0xff)) { if (service && isdigit(service[0]&0xff)) {

View file

@ -152,6 +152,18 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
applyopts_offset(xfd, opts); applyopts_offset(xfd, opts);
applyopts_cloexec(xfd->fd, opts); applyopts_cloexec(xfd->fd, opts);
#if defined(WITH_VSOCK) && defined(IOCTL_VM_SOCKETS_GET_LOCAL_CID)
{
unsigned int cid;
if (Ioctl(xfd->fd, IOCTL_VM_SOCKETS_GET_LOCAL_CID, &cid) < 0) {
Warn2("ioctl(%d, IOCTL_VM_SOCKETS_GET_LOCAL_CID, ...): %s",
xfd->fd, strerror(errno));
} else {
Notice1("VSOCK CID=%u", cid);
}
}
#endif
applyopts(xfd->fd, opts, PH_PREBIND); applyopts(xfd->fd, opts, PH_PREBIND);
applyopts(xfd->fd, opts, PH_BIND); applyopts(xfd->fd, opts, PH_BIND);
if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) { if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {

157
xio-vsock.c Normal file
View file

@ -0,0 +1,157 @@
/* source: xio-vsock.c */
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
/* Author: Stefano Garzarella <sgarzare@redhat.com */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of VSOCK socket type */
#include "xiosysincludes.h"
#ifdef WITH_VSOCK
#include "xioopen.h"
#include "xio-listen.h"
#include "xio-socket.h"
#include "xio-vsock.h"
static int xioopen_vsock_connect(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, unsigned groups, int abstract,
int dummy2, int dummy3);
static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, unsigned groups, int abstract,
int dummy2, int dummy3);
const struct addrdesc addr_vsock_connect = { "vsock-connect", 1 + XIO_RDWR,
xioopen_vsock_connect,
GROUP_FD|GROUP_SOCKET|GROUP_CHILD|GROUP_RETRY,
0, 0, 0 HELP(":<cid>:<port>") };
#if WITH_LISTEN
const struct addrdesc addr_vsock_listen = { "vsock-listen", 1 + XIO_RDWR,
xioopen_vsock_listen,
GROUP_FD|GROUP_SOCKET|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY,
0, 0, 0 HELP(":<port>") };
#endif /* WITH_LISTEN */
static int vsock_addr_init(struct sockaddr_vm *sa, const char *cid_str,
const char *port_str) {
int ret;
memset(sa, 0, sizeof(*sa));
sa->svm_family = AF_VSOCK;
ret = sockaddr_vm_parse(sa, cid_str, port_str);
if (ret < 0)
return STAT_NORETRY;
return STAT_OK;
}
static int vsock_init(struct opt *opts, struct single *xfd) {
xfd->howtoend = END_SHUTDOWN;
if (applyopts_single(xfd, opts, PH_INIT) < 0)
return STAT_NORETRY;
applyopts(-1, opts, PH_INIT);
applyopts(-1, opts, PH_EARLY);
xfd->dtype = XIODATA_STREAM;
return STAT_OK;
}
static int xioopen_vsock_connect(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, unsigned groups,
int abstract, int dummy2, int dummy3) {
/* we expect the form :cid:port */
struct single *xfd = &xxfd->stream;
struct sockaddr_vm sa, sa_local;
socklen_t sa_len = sizeof(sa);
bool needbind = false;
int socktype = SOCK_STREAM;
int pf = PF_VSOCK;
int protocol = 0;
int ret;
if (argc != 3) {
Error2("%s: wrong number of parameters (%d instead of 2)",
argv[0], argc-1);
return STAT_NORETRY;
}
ret = vsock_addr_init(&sa, argv[1], argv[2]);
if (ret) {
return ret;
}
ret = vsock_init(opts, xfd);
if (ret) {
return ret;
}
ret = retropt_bind(opts, pf, socktype, protocol,
(struct sockaddr *)&sa_local, &sa_len, 3, 0, 0);
if (ret == STAT_NORETRY)
return ret;
if (ret == STAT_OK)
needbind = true;
ret = xioopen_connect(xfd, needbind ? (union sockaddr_union *)&sa_local : NULL,
sa_len, (struct sockaddr *)&sa, sizeof(sa),
opts, pf, socktype, protocol, false);
if (ret)
return ret;
ret = _xio_openlate(xfd, opts);
if (ret < 0)
return ret;
return STAT_OK;
}
#if WITH_LISTEN
static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, unsigned groups, int abstract,
int dummy2, int dummy3) {
/* we expect the form :port */
struct single *xfd = &xxfd->stream;
struct sockaddr_vm sa, sa_bind;
socklen_t sa_len = sizeof(sa_bind);
struct opt *opts0;
int socktype = SOCK_STREAM;
int pf = PF_VSOCK;
int protocol = 0;
int ret;
if (argc != 2) {
Error2("%s: wrong number of parameters (%d instead of 1)",
argv[0], argc-1);
return STAT_NORETRY;
}
ret = vsock_addr_init(&sa, NULL, argv[1]);
if (ret) {
return ret;
}
ret = vsock_init(opts, xfd);
if (ret) {
return ret;
}
opts0 = copyopts(opts, GROUP_ALL);
ret = retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&sa_bind,
&sa_len, 1, 0, 0);
if (ret == STAT_NORETRY)
return ret;
if (ret == STAT_OK)
sa.svm_cid = sa_bind.svm_cid;
/* this may fork() */
return xioopen_listen(xfd, xioflags, (struct sockaddr *)&sa, sizeof(sa),
opts, opts0, pf, socktype, protocol);
}
#endif /* WITH_LISTEN */
#endif /* WITH_VSOCK */

11
xio-vsock.h Normal file
View file

@ -0,0 +1,11 @@
/* source: xio-vsock.h */
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
/* Author: Stefano Garzarella <sgarzare@redhat.com */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __xio_vsock_h_included
#define __xio_vsock_h_included 1
extern const struct addrdesc addr_vsock_connect;
extern const struct addrdesc addr_vsock_listen;
#endif /* !defined(__xio_vsock_h_included) */

View file

@ -32,6 +32,7 @@
#include "xio-sctp.h" #include "xio-sctp.h"
#include "xio-socks.h" #include "xio-socks.h"
#include "xio-proxy.h" #include "xio-proxy.h"
#include "xio-vsock.h"
#endif /* _WITH_SOCKET */ #endif /* _WITH_SOCKET */
#include "xio-progcall.h" #include "xio-progcall.h"
#include "xio-exec.h" #include "xio-exec.h"

View file

@ -307,6 +307,12 @@ const struct addrname addressnames[] = {
{ "unix-send", &xioaddr_unix_sendto }, { "unix-send", &xioaddr_unix_sendto },
{ "unix-sendto", &xioaddr_unix_sendto }, { "unix-sendto", &xioaddr_unix_sendto },
#endif #endif
#if WITH_VSOCK
{ "vsock-connect", &addr_vsock_connect },
#endif
#if WITH_VSOCK && WITH_LISTEN
{ "vsock-listen", &addr_vsock_listen },
#endif
#else /* !0 */ #else /* !0 */
# if WITH_INTEGRATE # if WITH_INTEGRATE
# include "xiointegrate.c" # include "xiointegrate.c"

View file

@ -3044,7 +3044,10 @@ int retropt_bind(struct opt *opts,
} }
break; break;
#if WITH_IP4 || WITH_IP6 #if WITH_IP4 || WITH_IP6 || WITH_VSOCK
#if WITH_VSOCK
case AF_VSOCK:
#endif
#if WITH_IP4 #if WITH_IP4
case AF_INET: case AF_INET:
#endif #endif