diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8 index b5e40ddfb..0f72b2d7b 100644 --- a/usr.sbin/bhyve/bhyve.8 +++ b/usr.sbin/bhyve/bhyve.8 @@ -369,14 +369,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. @@ -587,6 +588,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=[::0]: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 052e071bf..d9ee3d7ba 100644 --- a/usr.sbin/bhyve/pci_fbuf.c +++ b/usr.sbin/bhyve/pci_fbuf.c @@ -250,13 +250,27 @@ 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 + */ + tmpstr = strsep(&config, "]"); + if (config) { + if (tmpstr[0] == '[') + tmpstr++; sc->rfb_host = tmpstr; + if (config[0] == ':') + config++; + 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")) { diff --git a/usr.sbin/bhyve/rfb.c b/usr.sbin/bhyve/rfb.c index 7244a289e..cf84928fc 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 @@ -960,8 +961,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; @@ -978,7 +982,22 @@ 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) + hostname = "127.0.0.1"; + + 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"); return (-1); @@ -986,15 +1005,7 @@ rfb_init(char *hostname, int port, int wait, char *password) 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"); return (-1); } @@ -1028,5 +1039,6 @@ rfb_init(char *hostname, int port, int wait, char *password) pthread_mutex_unlock(&rc->mtx); } + freeaddrinfo(ai); return (0); }