From nobody Thu Apr 30 14:43:59 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4g5xkl3522z6c1yH for ; Thu, 30 Apr 2026 14:43:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4g5xkl2M9dz3x15 for ; Thu, 30 Apr 2026 14:43:59 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1777560239; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Ql2TUVggftLulilBt1Wf9n/UFzYzGpCkTYcy00kRVW8=; b=PH6t9BBzIxPY4zJU6pSZIYMcL9S+TQ9n+Hes13HVM6/DdkNrc49HeVDNC0UD8JK+XxKCrD JA0C1HHhk23uXCz1U0wbfLbtAw3rwUyCKV3OulGEZgOMHMcG/WAgfs1XYJ2Vh5HKydv4he G51I/WgiuqKgSjYiqcNVUSejacgLjJ9V8rNO5h4ZOLMMZ56K3mqucPc9qr9MPs84iMRW5e XhnzDcHd2SPd2H0fdPLVtN4T+Dp1puECty44h1MJ2eBpB4ipu5eVHmp3koqud1XIQzWaPA hMDxywt4dvQ+5daezaInGrxV+cpNvum7iU5OD6js6WkwSSIzvInsRmz6kfHxkg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1777560239; a=rsa-sha256; cv=none; b=XgM1B0O6Fx8BM8s6hDY2b6xuNN4Klvbn1UBdlD4olM6SudR9bZzpi/8mso/6krc6+krMHL U6Imic75N+ZA8vC2LGsTCNi4Cn6epooKv9fAsgQ5YbcC0OXiwRC1SxuPxaB5U3IHqnlsFm 0XShiOPZ9bQ5ulmSDwWtsWNzOMTFCpycm1BPWrAB1qshawIUAjsps5Ru2x1r0h8VKl9DOF YHwEujCSeoNYrlf7YNI+PaPPjSvV4E6gBgEgwCqZo9OISQ+0EYewdV+eHYD2xIPlrSPEVB X0tToGWelQWfH38Z4Y/ocQyJxKqHJt7OE94UOD5HSv2wFOfRxo9fEVKFo3+24Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1777560239; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Ql2TUVggftLulilBt1Wf9n/UFzYzGpCkTYcy00kRVW8=; b=h4Humo5Z2FGc9LxvGGKuWIAIKdsnAja/jiR481qPOK8ezFB7CJGPfLn7o7IUluWWyvevvo 2ntQLUEfQzKrrQ9Sk9v6PAW/TmuGoc5/EH/1K49ma1YoB5eHkcKyNyqDmGMBSdS5zKUsna G1tCjxMImX61ujg5Jk1eOc2LoqJQ9SL4Nix7Vx78AYLfluBn1Ku77zAYNC7lMbXHRYSOOS QGDOO2r30d7mJx3N/Rrf6EwgQ9koQCaOLs+xbfTnNsXOPsAfSTdwXOPS19bELViW21jHfQ bMFlNHI2Hro9zvHT1At7pPV3UsR7vDRzvGeiUwrOjVpyyCxHPZrbXJ042FdQcA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4g5xkl1hqhz17w for ; Thu, 30 Apr 2026 14:43:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3c6e8 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 30 Apr 2026 14:43:59 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Cc: Quent=?utf-8?Q?in Th=C3=A9?=bault From: Kyle Evans Subject: git: d29dd64b3f88 - stable/15 - bhyve: add UNIX domain socket support to rfb List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kevans X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: d29dd64b3f883079861fa53a21d3f7aac55eba5a Auto-Submitted: auto-generated Date: Thu, 30 Apr 2026 14:43:59 +0000 Message-Id: <69f36aaf.3c6e8.67af8b89@gitrepo.freebsd.org> The branch stable/15 has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=d29dd64b3f883079861fa53a21d3f7aac55eba5a commit d29dd64b3f883079861fa53a21d3f7aac55eba5a Author: Quentin Thébault AuthorDate: 2025-11-18 06:44:05 +0000 Commit: Kyle Evans CommitDate: 2026-04-30 14:37:07 +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 Sponsored by: Defenso Reviewed by: kevans, markj MFC after: 2 weeks (cherry picked from commit cbc6f7e941e42639a0314cd121b06493cce8e0e6) --- 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 ad3f6305cd08..d0237bad19a8 100644 --- a/usr.sbin/bhyve/bhyve.8 +++ b/usr.sbin/bhyve/bhyve.8 @@ -886,7 +886,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 @@ -897,9 +897,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 @@ -911,6 +911,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 #include +#include +#include #include #include @@ -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 7a1b5a7bee3f..c6c048d2b140 100644 --- a/usr.sbin/bhyve/rfb.c +++ b/usr.sbin/bhyve/rfb.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -1337,13 +1338,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 @@ -1384,25 +1387,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; } @@ -1438,14 +1458,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 + #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_ */