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)
MFC after:		3 days
This commit is contained in:
Bjoern A. Zeeb 2018-10-24 08:45:33 +00:00
parent 041929aab1
commit 8883128b8e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=339681
4 changed files with 80 additions and 20 deletions

View File

@ -73,6 +73,12 @@ SRCS+= vmm_instruction_emul.c
LIBADD= vmmapi md pthread z util sbuf cam
.if ${MK_INET_SUPPORT} != "no"
CFLAGS+=-DINET
.endif
.if ${MK_INET6_SUPPORT} != "no"
CFLAGS+=-DINET6
.endif
.if ${MK_OPENSSL} == "no"
CFLAGS+=-DNO_OPENSSL
.else

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd Aug 23, 2018
.Dd October 24, 2018
.Dt BHYVE 8
.Os
.Sh NAME
@ -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=[::]: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 ,

View File

@ -251,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")) {

View File

@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpufunc.h>
#include <machine/specialreg.h>
#include <netinet/in.h>
#include <netdb.h>
#include <assert.h>
#include <err.h>
@ -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,29 +982,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);
}
@ -1028,5 +1046,6 @@ rfb_init(char *hostname, int port, int wait, char *password)
pthread_mutex_unlock(&rc->mtx);
}
freeaddrinfo(ai);
return (0);
}