From 5e060e63804e1ecc636b29714d32113e483d6c60 Mon Sep 17 00:00:00 2001 From: bz Date: Wed, 31 Oct 2018 11:37:05 +0000 Subject: [PATCH] MFC r339586: In bhyve's fbuf emulation improve the overall "usage" message and for the vga option, rather than printing the entire option string, only print vga (as we do for everything else). MFC r339681: Allow the bhyve VNC server to listen on IPv6 for incoming connections. Alternatively to IPv4 address:port this will allow to listen on IPv6 link-local (incl. scope), a specific address, or ::. Addresses have to be given in RFC2732 format so that [::]:port parsing will work. This patch also starts to introduce WITH_INET/INET6_SUPPORT to bhyve. PR: 232018 Submitted by: Dave Rush (northwoodlogic.free gmail.com) (original) Reviewed by: Dave Rush (updated verison) --- usr.sbin/bhyve/Makefile | 6 ++++++ usr.sbin/bhyve/bhyve.8 | 21 +++++++++++++++++--- usr.sbin/bhyve/pci_fbuf.c | 39 ++++++++++++++++++++++++++++--------- usr.sbin/bhyve/rfb.c | 41 ++++++++++++++++++++++++++++----------- 4 files changed, 84 insertions(+), 23 deletions(-) diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile index 8159d7ddbd7..d3c3e4d0f8d 100644 --- a/usr.sbin/bhyve/Makefile +++ b/usr.sbin/bhyve/Makefile @@ -65,6 +65,12 @@ SRCS+= vmm_instruction_emul.c LIBADD= vmmapi md pthread z +.if ${MK_INET_SUPPORT} != "no" +CFLAGS+=-DINET +.endif +.if ${MK_INET6_SUPPORT} != "no" +CFLAGS+=-DINET6 +.endif .if ${MK_OPENSSL} == "no" CFLAGS+=-DNO_OPENSSL .else diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8 index 6e9507f3a55..9d2f190fb94 100644 --- a/usr.sbin/bhyve/bhyve.8 +++ b/usr.sbin/bhyve/bhyve.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd Jul 11, 2018 +.Dd October 24, 2018 .Dt BHYVE 8 .Os .Sh NAME @@ -311,14 +311,15 @@ Framebuffer devices: .Bl -tag -width 10n .It Oo rfb= Ns Oo Ar IP: Oc Ns Ar port Oc Ns Oo ,w= Ns Ar width Oc Ns Oo ,h= Ns Ar height Oc Ns Oo ,vga= Ns Ar vgaconf Oc Ns Oo Ns ,wait Oc Ns Oo ,password= Ns Ar password Oc .Bl -tag -width 8n -.It Ar IP:port +.It Ar IPv4:port No or Ar [IPv6%zone]:port An .Ar IP address and a .Ar port VNC should listen on. The default is to listen on localhost IPv4 address and default VNC port 5900. -Listening on an IPv6 address is not supported. +An IPv6 address must be enclosed in square brackets and may contain an +optional zone identifer. .It Ar width No and Ar height A display resolution, width and height, respectively. If not specified, a default resolution of 1024x768 pixels will be used. @@ -490,6 +491,20 @@ bhyve -c 2 -m 4G -w -H \\ -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \\ uefivm .Ed +.Pp +Run a UEFI virtual machine with a VNC display that is bound to all IPv6 +addresses on port 5900. +.Bd -literal -offset indent +bhyve -c 2 -m 4G -w -H \\ + -s 0,hostbridge \\ + -s 4,ahci-hd,disk.img \\ + -s 5,virtio-net,tap0 \\ + -s 29,fbuf,tcp=[::]:5900,w=800,h=600 \\ + -s 30,xhci,tablet \\ + -s 31,lpc -l com1,stdio \\ + -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \\ + uefivm +.Ed .Sh SEE ALSO .Xr bhyve 4 , .Xr nmdm 4 , diff --git a/usr.sbin/bhyve/pci_fbuf.c b/usr.sbin/bhyve/pci_fbuf.c index 052e071bf79..2669ea14d3f 100644 --- a/usr.sbin/bhyve/pci_fbuf.c +++ b/usr.sbin/bhyve/pci_fbuf.c @@ -117,8 +117,9 @@ static void pci_fbuf_usage(char *opt) { - fprintf(stderr, "Invalid fbuf emulation \"%s\"\r\n", opt); - fprintf(stderr, "fbuf: {wait,}{vga=on|io|off,}rfb=:port\r\n"); + fprintf(stderr, "Invalid fbuf emulation option \"%s\"\r\n", opt); + fprintf(stderr, "fbuf: {wait,}{vga=on|io|off,}rfb=:port" + "{,w=width}{,h=height}\r\n"); } static void @@ -250,13 +251,33 @@ pci_fbuf_parse_opts(struct pci_fbuf_softc *sc, char *opts) xopts, config)); if (!strcmp(xopts, "tcp") || !strcmp(xopts, "rfb")) { - /* parse host-ip:port */ - tmpstr = strsep(&config, ":"); - if (!config) - sc->rfb_port = atoi(tmpstr); - else { - sc->rfb_port = atoi(config); + /* + * IPv4 -- host-ip:port + * IPv6 -- [host-ip%zone]:port + * XXX for now port is mandatory. + */ + tmpstr = strsep(&config, "]"); + if (config) { + if (tmpstr[0] == '[') + tmpstr++; sc->rfb_host = tmpstr; + if (config[0] == ':') + config++; + else { + pci_fbuf_usage(xopts); + ret = -1; + goto done; + } + sc->rfb_port = atoi(config); + } else { + config = tmpstr; + tmpstr = strsep(&config, ":"); + if (!config) + sc->rfb_port = atoi(tmpstr); + else { + sc->rfb_port = atoi(config); + sc->rfb_host = tmpstr; + } } } else if (!strcmp(xopts, "vga")) { if (!strcmp(config, "off")) { @@ -268,7 +289,7 @@ pci_fbuf_parse_opts(struct pci_fbuf_softc *sc, char *opts) sc->vga_enabled = 1; sc->vga_full = 1; } else { - pci_fbuf_usage(opts); + pci_fbuf_usage(xopts); ret = -1; goto done; } diff --git a/usr.sbin/bhyve/rfb.c b/usr.sbin/bhyve/rfb.c index 45491f56f52..0c023dc464c 100644 --- a/usr.sbin/bhyve/rfb.c +++ b/usr.sbin/bhyve/rfb.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -977,8 +978,11 @@ sse42_supported(void) int rfb_init(char *hostname, int port, int wait, char *password) { + int e; + char servname[6]; struct rfb_softc *rc; - struct sockaddr_in sin; + struct addrinfo *ai; + struct addrinfo hints; int on = 1; #ifndef WITHOUT_CAPSICUM cap_rights_t rights; @@ -995,29 +999,43 @@ rfb_init(char *hostname, int port, int wait, char *password) rc->password = password; - rc->sfd = socket(AF_INET, SOCK_STREAM, 0); + snprintf(servname, sizeof(servname), "%d", port ? port : 5900); + + if (!hostname || strlen(hostname) == 0) +#if defined(INET) + hostname = "127.0.0.1"; +#elif defined(INET6) + 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) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(e)); + return(-1); + } + + rc->sfd = socket(ai->ai_family, ai->ai_socktype, 0); if (rc->sfd < 0) { perror("socket"); + freeaddrinfo(ai); return (-1); } setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_port = port ? htons(port) : htons(5900); - if (hostname && strlen(hostname) > 0) - inet_pton(AF_INET, hostname, &(sin.sin_addr)); - else - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - if (bind(rc->sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + if (bind(rc->sfd, ai->ai_addr, ai->ai_addrlen) < 0) { perror("bind"); + freeaddrinfo(ai); return (-1); } if (listen(rc->sfd, 1) < 0) { perror("listen"); + freeaddrinfo(ai); return (-1); } @@ -1045,5 +1063,6 @@ rfb_init(char *hostname, int port, int wait, char *password) pthread_mutex_unlock(&rc->mtx); } + freeaddrinfo(ai); return (0); } -- 2.45.0