Add AF_VSOCK

This patch extends the existing libxcb protocol framework
for AF_VSOCK by adding a new protocol name 'vsock':

DISPLAY=vsock/[<VMADDR_CID>]:<display_number>[.<screen_number>]

For example, in order to have X11 clients running in a virtual
machine forwarded to the X11 server running in the host, you
can set the DISPLAY variable as:

export DISPLAY=vsock/2:0.0

It can be shortened as the following:

export DISPLAY=vsock/:0

'2' is the assigned number for VMADDR_CID_HOST and it's used
as a default value when it's not found in the DISPLAY variable.
For a port number, it can be any 'unsigned int', but in order
to maintain consistency, it's defined the same as the TCP
method: 6000 + <display_number>.

See also:
https://stefano-garzarella.github.io/posts/2019-11-08-kvmforum-2019-vsock/
https://man7.org/linux/man-pages/man7/vsock.7.html
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/vm_sockets.h
This commit is contained in:
Choung Park 2022-04-25 04:14:01 -07:00
parent ddafdba11f
commit 8d251ee72a
2 changed files with 62 additions and 0 deletions

View File

@ -186,6 +186,11 @@ AC_SUBST(xcbincludedir)
XCB_CHECK_VISIBILITY()
AC_CHECK_FUNC(getaddrinfo, [AC_DEFINE(HAVE_GETADDRINFO, 1, [getaddrinfo() function is available])], )
AC_CHECK_HEADER([linux/vm_sockets.h], [], [AC_DEFINE(HAVE_VSOCK_H, 1, [Define to 1 if you have the <linux/vm_sockets.h> header file.])],
[#ifdef HAVE_VSOCK_H
#include <linux/vm_sockets.h>
#endif
])
case $host_os in
# darwin through Snow Leopard has poll() but can't be used to poll character devices.

View File

@ -44,6 +44,9 @@
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#ifdef HAVE_VSOCK_H
#include <linux/vm_sockets.h>
#endif
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
@ -216,6 +219,9 @@ int xcb_parse_display(const char *name, char **host, int *displayp,
}
static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port);
#ifdef HAVE_VSOCK_H
static int _xcb_open_vsock(const char *host, char *protocol, const unsigned short port);
#endif
#ifndef _WIN32
static int _xcb_open_unix(char *protocol, const char *file);
#endif /* !WIN32 */
@ -236,6 +242,14 @@ static int _xcb_open(const char *host, char *protocol, const int display)
char *file = NULL;
int actual_filelen;
#ifdef HAVE_VSOCK_H
if (protocol && (strcmp("vsock",protocol) == 0))
{
unsigned short port = X_TCP_PORT + display;
return _xcb_open_vsock(host, protocol, port);
}
#endif
/* If protocol or host is "unix", fall through to Unix socket code below */
if ((!protocol || (strcmp("unix",protocol) != 0)) &&
(*host != '\0') && (strcmp("unix",host) != 0))
@ -429,6 +443,49 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
#endif
}
#ifdef HAVE_VSOCK_H
static int _xcb_open_vsock(const char *host, char *protocol, const unsigned short port)
{
struct sockaddr_vm savm;
int fd;
if(protocol && strcmp("vsock",protocol))
return -1;
fd = _xcb_socket(AF_VSOCK, SOCK_STREAM, 0);
if(fd == -1)
return -1;
{
socklen_t len = sizeof(int);
int val = 0;
if((getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &len) == 0) && (val < (64 * 1024)))
{
val = (64 * 1024);
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, sizeof(int));
}
}
memset(&savm, 0, sizeof(savm));
savm.svm_family = AF_VSOCK;
savm.svm_cid = VMADDR_CID_HOST;
if(*host != '\0')
savm.svm_cid = (unsigned int)atoi(host);
savm.svm_port = port;
if(connect(fd, (struct sockaddr*)&savm, sizeof(savm)) == -1)
{
close(fd);
return -1;
}
return fd;
}
#endif
#ifndef _WIN32
static int _xcb_open_unix(char *protocol, const char *file)
{