mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
Added VSOCK stream addresses
This commit is contained in:
parent
1c7ddfef73
commit
1502f0cdcb
18 changed files with 442 additions and 4 deletions
3
CHANGES
3
CHANGES
|
@ -170,6 +170,9 @@ New features:
|
|||
Test: PROXYAUTHFILE
|
||||
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:
|
||||
|
||||
Corrections:
|
||||
|
|
14
EXAMPLES
14
EXAMPLES
|
@ -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
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
|
|
@ -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 \
|
||||
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-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-sctp.c xio-rawip.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 \
|
||||
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-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-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \
|
||||
xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \
|
||||
|
|
|
@ -279,6 +279,9 @@
|
|||
/* Define if you have the <linux/if_tun.h> header file. */
|
||||
#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. */
|
||||
#undef HAVE_NETPACKET_PACKET_H
|
||||
|
||||
|
@ -660,6 +663,7 @@
|
|||
#undef WITH_LISTEN
|
||||
#undef WITH_SOCKS4
|
||||
#undef WITH_SOCKS4A
|
||||
#undef WITH_VSOCK
|
||||
#undef WITH_PROXY
|
||||
#undef WITH_EXEC
|
||||
#undef WITH_SYSTEM
|
||||
|
|
23
configure.ac
23
configure.ac
|
@ -349,6 +349,29 @@ else
|
|||
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_ARG_ENABLE(listen, [ --disable-listen disable listen support],
|
||||
[case "$enableval" in
|
||||
|
|
81
doc/socat.yo
81
doc/socat.yo
|
@ -1352,6 +1352,37 @@ label(ADDRESS_UNIX_CLIENT)dit(bf(tt(UNIX-CLIENT:<filename>)))
|
|||
link(UNIX-SENDTO)(ADDRESS_UNIX_SENDTO),
|
||||
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-LISTEN:<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
|
||||
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)),
|
||||
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>)))
|
||||
Abort the connection attempt after <seconds> [link(timeval)(TYPE_TIMEVAL)]
|
||||
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
|
||||
code(strtoul()) as unsigned integer specifying a user id. Otherwise, it must
|
||||
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()
|
||||
|
||||
|
||||
|
@ -3444,6 +3484,45 @@ streaming eg. via TCP or SSL does not guarantee to retain packet boundaries and
|
|||
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)
|
||||
dit(bf(tt(socat PTY,link=/var/run/ppp,rawer INTERFACE:hdlc0)))
|
||||
|
||||
|
|
5
socat.c
5
socat.c
|
@ -528,6 +528,11 @@ void socat_version(FILE *fd) {
|
|||
#else
|
||||
fputs(" #undef WITH_SOCKS4A\n", fd);
|
||||
#endif
|
||||
#ifdef WITH_VSOCK
|
||||
fprintf(fd, " #define WITH_VSOCK %d\n", WITH_VSOCK);
|
||||
#else
|
||||
fputs(" #undef WITH_VSOCK\n", fd);
|
||||
#endif
|
||||
#ifdef WITH_PROXY
|
||||
fprintf(fd, " #define WITH_PROXY %d\n", WITH_PROXY);
|
||||
#else
|
||||
|
|
|
@ -185,5 +185,8 @@
|
|||
#include <openssl/err.h>
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
#if HAVE_LINUX_VM_SOCKETS_H
|
||||
#include <linux/vm_sockets.h>
|
||||
#endif
|
||||
|
||||
#endif /* !defined(__sysincludes_h_included) */
|
||||
|
|
41
sysutils.c
41
sysutils.c
|
@ -204,6 +204,10 @@ char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size
|
|||
#if WITH_IP6
|
||||
case AF_INET6: sockaddr_inet6_info(&sau->ip6, cp, blen);
|
||||
break;
|
||||
#endif
|
||||
#if WITH_VSOCK
|
||||
case AF_VSOCK: sockaddr_vm_info(&sau->vm, cp, blen);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
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 */
|
||||
|
||||
#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
|
||||
/* http://www.opengroup.org/onlinepubs/000095399/functions/inet_ntop.html */
|
||||
const char *inet_ntop(int pf, const void *binaddr,
|
||||
|
|
|
@ -27,6 +27,9 @@ union sockaddr_union {
|
|||
#if WITH_IP6
|
||||
struct sockaddr_in6 ip6;
|
||||
#endif /* WITH_IP6 */
|
||||
#if WITH_VSOCK
|
||||
struct sockaddr_vm vm;
|
||||
#endif /* WITH_IP6 */
|
||||
#if WITH_INTERFACE
|
||||
struct sockaddr_ll ll;
|
||||
#endif
|
||||
|
@ -68,6 +71,11 @@ extern char *sockaddr_inet4_info(const struct sockaddr_in *sa, char *buff, size_
|
|||
#if WITH_IP6
|
||||
extern char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen);
|
||||
#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
|
||||
extern const char *inet_ntop(int pf, const void *binaddr,
|
||||
char *addrtext, socklen_t textlen);
|
||||
|
|
57
test.sh
57
test.sh
|
@ -35,6 +35,7 @@ done
|
|||
opt_t="-t $val_t"
|
||||
|
||||
UNAME=`uname`
|
||||
UNAME_R=`uname -r`
|
||||
|
||||
#MICROS=100000
|
||||
case "X$val_t" in
|
||||
|
@ -14588,6 +14589,62 @@ PORT=$((PORT+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
|
||||
|
|
11
xio-ip.c
11
xio-ip.c
|
@ -167,6 +167,17 @@ int xiogetaddrinfo(const char *node, const char *service,
|
|||
if (service && service[0]=='\0') {
|
||||
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
|
||||
with NIS), so we handle this specially */
|
||||
if (service && isdigit(service[0]&0xff)) {
|
||||
|
|
12
xio-listen.c
12
xio-listen.c
|
@ -152,6 +152,18 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
|||
applyopts_offset(xfd, 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_BIND);
|
||||
if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
|
||||
|
|
157
xio-vsock.c
Normal file
157
xio-vsock.c
Normal 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
11
xio-vsock.h
Normal 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) */
|
|
@ -32,6 +32,7 @@
|
|||
#include "xio-sctp.h"
|
||||
#include "xio-socks.h"
|
||||
#include "xio-proxy.h"
|
||||
#include "xio-vsock.h"
|
||||
#endif /* _WITH_SOCKET */
|
||||
#include "xio-progcall.h"
|
||||
#include "xio-exec.h"
|
||||
|
|
|
@ -307,6 +307,12 @@ const struct addrname addressnames[] = {
|
|||
{ "unix-send", &xioaddr_unix_sendto },
|
||||
{ "unix-sendto", &xioaddr_unix_sendto },
|
||||
#endif
|
||||
#if WITH_VSOCK
|
||||
{ "vsock-connect", &addr_vsock_connect },
|
||||
#endif
|
||||
#if WITH_VSOCK && WITH_LISTEN
|
||||
{ "vsock-listen", &addr_vsock_listen },
|
||||
#endif
|
||||
#else /* !0 */
|
||||
# if WITH_INTEGRATE
|
||||
# include "xiointegrate.c"
|
||||
|
|
|
@ -3044,7 +3044,10 @@ int retropt_bind(struct opt *opts,
|
|||
}
|
||||
break;
|
||||
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
#if WITH_IP4 || WITH_IP6 || WITH_VSOCK
|
||||
#if WITH_VSOCK
|
||||
case AF_VSOCK:
|
||||
#endif
|
||||
#if WITH_IP4
|
||||
case AF_INET:
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue