Date: Thu, 08 Jan 2026 16:06:07 +0000 From: Mark Johnston <markj@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Quent=?utf-8?Q?in Th=C3=A9?=bault <quentin.thebault@defenso.fr> Subject: git: cbc6f7e941e4 - main - bhyve: add UNIX domain socket support to rfb Message-ID: <695fd5ef.2179f.71e9bb42@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=cbc6f7e941e42639a0314cd121b06493cce8e0e6 commit cbc6f7e941e42639a0314cd121b06493cce8e0e6 Author: Quentin Thébault <quentin.thebault@defenso.fr> AuthorDate: 2025-11-18 06:44:05 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-01-08 15:24:52 +0000 bhyve: add UNIX domain socket support to rfb This commit adds support for a UNIX domain socket to bhyve's remote framebuffer. It enables the use of the graphical console when the bhyve instance is running in a jail with no networking, for instance. A VNC client running on the host can then connect to the UNIX domain socket through the filesystem. Signed-off-by: Quentin Thébault <quentin.thebault@defenso.fr> Sponsored by: Defenso Reviewed by: kevans, markj MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D53814 --- usr.sbin/bhyve/bhyve.8 | 12 +++++++---- usr.sbin/bhyve/bhyve_config.5 | 7 ++++++- usr.sbin/bhyve/pci_fbuf.c | 22 ++++++++++++++++++- usr.sbin/bhyve/rfb.c | 49 +++++++++++++++++++++++++++++++------------ usr.sbin/bhyve/rfb.h | 4 +++- 5 files changed, 74 insertions(+), 20 deletions(-) diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8 index d3b067509ced..496539f30885 100644 --- a/usr.sbin/bhyve/bhyve.8 +++ b/usr.sbin/bhyve/bhyve.8 @@ -891,7 +891,7 @@ to guest by VirtIO Input Interface. .Bl -bullet .Sm off .It -.Op Cm rfb= Ar ip-and-port +.Op Cm rfb= Ar address .Op Cm ,w= Ar width .Op Cm ,h= Ar height .Op Cm ,vga= Ar vgaconf @@ -902,9 +902,9 @@ to guest by VirtIO Input Interface. .Pp Configuration options are defined as follows: .Bl -tag -width 10n -.It Cm rfb= Ns Ar ip-and-port Pq or Cm tcp= Ns Ar ip-and-port -An IP address and a port VNC should listen on. -There are two formats: +.It Cm rfb= Ns Ar address Pq or Cm tcp= Ns Ar address +A UNIX domain socket or IP address and a port VNC should listen on. +There are three possible formats: .Pp .Bl -bullet -compact .It @@ -916,6 +916,10 @@ There are two formats: .Sm off .Cm \&[ Ar IPv6%zone Cm \&] Cm \&: Ar port .Sm on +.It +.Sm off +.Cm unix: Ar my/unix.sock +.Sm on .El .Pp The default is to listen on localhost IPv4 address and default VNC port 5900. diff --git a/usr.sbin/bhyve/bhyve_config.5 b/usr.sbin/bhyve/bhyve_config.5 index 4ead94690d91..429ce3e38138 100644 --- a/usr.sbin/bhyve/bhyve_config.5 +++ b/usr.sbin/bhyve/bhyve_config.5 @@ -523,7 +523,7 @@ the device name. If specified, it must be a unicast MAC address. .El .Ss Frame Buffer Settings -.Bl -column "password" "[IP:]port" "127.0.0.1:5900" +.Bl -column "password" "unix:my/unix.sock" "127.0.0.1:5900" .It Sy Name Ta Sy Format Ta Sy Default Ta Sy Description .It Va wait Ta bool Ta false Ta Wait for a remote connection before starting the VM. @@ -535,6 +535,11 @@ support scoped identifiers as described in .Xr getaddrinfo 3 . A bare port number may be given in which case the IPv4 localhost address is used. +.It Va rfb Ta +.Sm off +.Cm unix: Ar my/unix.sock Ta Ta +.Sm on +Alternatively, provide a path to a UNIX domain socket. .It Va vga Ta string Ta io Ta VGA configuration. More details are provided in diff --git a/usr.sbin/bhyve/pci_fbuf.c b/usr.sbin/bhyve/pci_fbuf.c index 1e3ec77c15b0..560c2bc839d6 100644 --- a/usr.sbin/bhyve/pci_fbuf.c +++ b/usr.sbin/bhyve/pci_fbuf.c @@ -28,6 +28,8 @@ #include <sys/types.h> #include <sys/mman.h> +#include <sys/socket.h> +#include <sys/un.h> #include <dev/vmm/vmm_mem.h> #include <machine/vmm.h> @@ -94,6 +96,7 @@ struct pci_fbuf_softc { } __packed memregs; /* rfb server */ + sa_family_t rfb_family; char *rfb_host; char *rfb_password; int rfb_port; @@ -252,11 +255,13 @@ pci_fbuf_parse_config(struct pci_fbuf_softc *sc, nvlist_t *nvl) value = get_config_value_node(nvl, "tcp"); if (value != NULL) { /* + * UNIX -- unix:path/to/socket.sock * IPv4 -- host-ip:port * IPv6 -- [host-ip%zone]:port * XXX for now port is mandatory for IPv4. */ if (value[0] == '[') { + sc->rfb_family = AF_INET6; cp = strchr(value + 1, ']'); if (cp == NULL || cp == value + 1) { EPRINTLN("fbuf: Invalid IPv6 address: \"%s\"", @@ -279,7 +284,21 @@ pci_fbuf_parse_config(struct pci_fbuf_softc *sc, nvlist_t *nvl) value); return (-1); } + } else if (strncmp("unix:", value, 5) == 0) { + if (strlen(value + 5) > SUNPATHLEN) { + EPRINTLN( + "fbuf: UNIX socket path too long: \"%s\"", + value + 5); + return (-1); + } else if (*(value + 5) == '\0') { + EPRINTLN("fbuf: UNIX socket path is empty"); + return (-1); + } else { + sc->rfb_family = AF_UNIX; + sc->rfb_host = strdup(value + 5); + } } else { + sc->rfb_family = AF_UNSPEC; cp = strchr(value, ':'); if (cp == NULL) { sc->rfb_port = atoi(value); @@ -433,7 +452,8 @@ pci_fbuf_init(struct pci_devinst *pi, nvlist_t *nvl) memset((void *)sc->fb_base, 0, FB_SIZE); - error = rfb_init(sc->rfb_host, sc->rfb_port, sc->rfb_wait, sc->rfb_password); + error = rfb_init(sc->rfb_family, sc->rfb_host, sc->rfb_port, + sc->rfb_wait, sc->rfb_password); done: if (error) free(sc); diff --git a/usr.sbin/bhyve/rfb.c b/usr.sbin/bhyve/rfb.c index 716e191e2fc0..aeaf8d1c0639 100644 --- a/usr.sbin/bhyve/rfb.c +++ b/usr.sbin/bhyve/rfb.c @@ -35,6 +35,7 @@ #include <sys/socket.h> #include <sys/select.h> #include <sys/time.h> +#include <sys/un.h> #include <arpa/inet.h> #include <stdatomic.h> #include <machine/cpufunc.h> @@ -1254,13 +1255,15 @@ sse42_supported(void) } int -rfb_init(const char *hostname, int port, int wait, const char *password) +rfb_init(sa_family_t family, const char *hostname, int port, int wait, + const char *password) { int e; char servname[6]; struct rfb_softc *rc; struct addrinfo *ai = NULL; struct addrinfo hints; + struct sockaddr_un sun; int on = 1; int cnt; #ifndef WITHOUT_CAPSICUM @@ -1301,25 +1304,42 @@ rfb_init(const char *hostname, int port, int wait, const char *password) hostname = "[::1]"; #endif - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE; - - if ((e = getaddrinfo(hostname, servname, &hints, &ai)) != 0) { - EPRINTLN("getaddrinfo: %s", gai_strerror(e)); - goto error; + if (family == AF_UNIX) { + memset(&sun, 0, sizeof(sun)); + sun.sun_family = AF_UNIX; + if (strlcpy(sun.sun_path, hostname, sizeof(sun.sun_path)) >= + sizeof(sun.sun_path)) { + EPRINTLN("rfb: socket path too long"); + goto error; + } + rc->sfd = socket(AF_UNIX, SOCK_STREAM, 0); + } else { + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = family; + hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE; + + if ((e = getaddrinfo(hostname, servname, &hints, &ai)) != 0) { + EPRINTLN("getaddrinfo: %s", gai_strerror(e)); + goto error; + } + rc->sfd = socket(ai->ai_family, ai->ai_socktype, 0); } - rc->sfd = socket(ai->ai_family, ai->ai_socktype, 0); if (rc->sfd < 0) { perror("socket"); goto error; } + /* No effect for UNIX domain sockets. */ setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - if (bind(rc->sfd, ai->ai_addr, ai->ai_addrlen) < 0) { + if (family == AF_UNIX) { + unlink(hostname); + e = bind(rc->sfd, (struct sockaddr *)&sun, SUN_LEN(&sun)); + } else + e = bind(rc->sfd, ai->ai_addr, ai->ai_addrlen); + if (e < 0) { perror("bind"); goto error; } @@ -1355,14 +1375,17 @@ rfb_init(const char *hostname, int port, int wait, const char *password) DPRINTF(("rfb client connected")); } - freeaddrinfo(ai); + if (family != AF_UNIX) + freeaddrinfo(ai); return (0); error: if (rc->pixfmt_mtx) pthread_mutex_destroy(&rc->pixfmt_mtx); - if (ai != NULL) + if (ai != NULL) { + assert(family != AF_UNIX); freeaddrinfo(ai); + } if (rc->sfd != -1) close(rc->sfd); free(rc->crc); diff --git a/usr.sbin/bhyve/rfb.h b/usr.sbin/bhyve/rfb.h index 347ced083a22..c11d40f031af 100644 --- a/usr.sbin/bhyve/rfb.h +++ b/usr.sbin/bhyve/rfb.h @@ -29,9 +29,11 @@ #ifndef _RFB_H_ #define _RFB_H_ +#include <sys/socket.h> + #define RFB_PORT 5900 -int rfb_init(const char *hostname, int port, int wait, +int rfb_init(sa_family_t family, const char *hostname, int port, int wait, const char *password); #endif /* _RFB_H_ */home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?695fd5ef.2179f.71e9bb42>
