From 8d251ee72a204600fcb474d4a0b6cb3e02ad7400 Mon Sep 17 00:00:00 2001 From: Choung Park Date: Mon, 25 Apr 2022 04:14:01 -0700 Subject: [PATCH] Add AF_VSOCK This patch extends the existing libxcb protocol framework for AF_VSOCK by adding a new protocol name 'vsock': DISPLAY=vsock/[]:[.] 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 + . 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 --- configure.ac | 5 +++++ src/xcb_util.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/configure.ac b/configure.ac index 2d7a172..ccdf990 100644 --- a/configure.ac +++ b/configure.ac @@ -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 header file.])], +[#ifdef HAVE_VSOCK_H +#include +#endif +]) case $host_os in # darwin through Snow Leopard has poll() but can't be used to poll character devices. diff --git a/src/xcb_util.c b/src/xcb_util.c index 0296ce0..da346e6 100644 --- a/src/xcb_util.c +++ b/src/xcb_util.c @@ -44,6 +44,9 @@ #include #include #include +#ifdef HAVE_VSOCK_H +#include +#endif #include #include #include @@ -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) { -- GitLab