summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/vmd/config.c37
-rw-r--r--usr.sbin/vmd/dhcp.c6
-rw-r--r--usr.sbin/vmd/parse.y30
-rw-r--r--usr.sbin/vmd/priv.c154
-rw-r--r--usr.sbin/vmd/vm.conf.526
-rw-r--r--usr.sbin/vmd/vmd.c21
-rw-r--r--usr.sbin/vmd/vmd.h27
7 files changed, 262 insertions, 39 deletions
diff --git a/usr.sbin/vmd/config.c b/usr.sbin/vmd/config.c
index 6e7ed279d6b..20a16f85442 100644
--- a/usr.sbin/vmd/config.c
+++ b/usr.sbin/vmd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.54 2018/10/26 11:24:45 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.55 2018/11/21 12:31:47 reyk Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -42,17 +42,44 @@
/* Supported bridge types */
const char *vmd_descsw[] = { "switch", "bridge", NULL };
+static int config_init_localprefix(struct vmd_config *);
+
+static int
+config_init_localprefix(struct vmd_config *cfg)
+{
+ struct sockaddr_in6 *sin6;
+
+ if (host(VMD_DHCP_PREFIX, &cfg->cfg_localprefix) == -1)
+ return (-1);
+
+ /* IPv6 is disabled by default */
+ cfg->cfg_flags &= ~VMD_CFG_INET6;
+
+ /* Generate random IPv6 prefix only once */
+ if (cfg->cfg_flags & VMD_CFG_AUTOINET6)
+ return (0);
+ if (host(VMD_ULA_PREFIX, &cfg->cfg_localprefix6) == -1)
+ return (-1);
+ /* Randomize the 56 bits "Global ID" and "Subnet ID" */
+ sin6 = ss2sin6(&cfg->cfg_localprefix6.ss);
+ arc4random_buf(&sin6->sin6_addr.s6_addr[1], 7);
+ cfg->cfg_flags |= VMD_CFG_AUTOINET6;
+
+ return (0);
+}
+
int
config_init(struct vmd *env)
{
- struct privsep *ps = &env->vmd_ps;
- unsigned int what;
+ struct privsep *ps = &env->vmd_ps;
+ unsigned int what;
/* Global configuration */
ps->ps_what[PROC_PARENT] = CONFIG_ALL;
ps->ps_what[PROC_VMM] = CONFIG_VMS;
- if (host(VMD_DHCP_PREFIX, &env->vmd_cfg.cfg_localprefix) == -1)
+ /* Local prefix */
+ if (config_init_localprefix(&env->vmd_cfg) == -1)
return (-1);
/* Other configuration */
@@ -90,7 +117,7 @@ config_purge(struct vmd *env, unsigned int reset)
__func__, ps->ps_title[privsep_process]);
/* Reset global configuration (prefix was verified before) */
- (void)host(VMD_DHCP_PREFIX, &env->vmd_cfg.cfg_localprefix);
+ config_init_localprefix(&env->vmd_cfg);
/* Reset other configuration */
what = ps->ps_what[privsep_process] & reset;
diff --git a/usr.sbin/vmd/dhcp.c b/usr.sbin/vmd/dhcp.c
index 88cb62f4ab5..60016e27759 100644
--- a/usr.sbin/vmd/dhcp.c
+++ b/usr.sbin/vmd/dhcp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcp.c,v 1.5 2018/08/17 07:12:28 martijn Exp $ */
+/* $OpenBSD: dhcp.c,v 1.6 2018/11/21 12:31:47 reyk Exp $ */
/*
* Copyright (c) 2017 Reyk Floeter <reyk@openbsd.org>
@@ -109,7 +109,7 @@ dhcp_request(struct vionet_dev *dev, char *buf, size_t buflen, char **obuf)
resp.xid = req.xid;
if ((client_addr.s_addr =
- vm_priv_addr(&env->vmd_cfg.cfg_localprefix,
+ vm_priv_addr(&env->vmd_cfg,
dev->vm_vmid, dev->idx, 1)) == 0)
return (-1);
memcpy(&resp.yiaddr, &client_addr,
@@ -119,7 +119,7 @@ dhcp_request(struct vionet_dev *dev, char *buf, size_t buflen, char **obuf)
ss2sin(&pc.pc_dst)->sin_port = htons(CLIENT_PORT);
if ((server_addr.s_addr =
- vm_priv_addr(&env->vmd_cfg.cfg_localprefix,
+ vm_priv_addr(&env->vmd_cfg,
dev->vm_vmid, dev->idx, 0)) == 0)
return (-1);
memcpy(&resp.siaddr, &server_addr,
diff --git a/usr.sbin/vmd/parse.y b/usr.sbin/vmd/parse.y
index 6f1544fbea7..308f9d9d571 100644
--- a/usr.sbin/vmd/parse.y
+++ b/usr.sbin/vmd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.48 2018/11/01 00:18:44 sashan Exp $ */
+/* $OpenBSD: parse.y,v 1.49 2018/11/21 12:31:47 reyk Exp $ */
/*
* Copyright (c) 2007-2016 Reyk Floeter <reyk@openbsd.org>
@@ -120,9 +120,9 @@ typedef struct {
%token INCLUDE ERROR
-%token ADD ALLOW BOOT CDROM DISABLE DISK DOWN ENABLE FORMAT GROUP INSTANCE
-%token INTERFACE LLADDR LOCAL LOCKED MEMORY NIFS OWNER PATH PREFIX RDOMAIN
-%token SIZE SOCKET SWITCH UP VM VMID
+%token ADD ALLOW BOOT CDROM DISABLE DISK DOWN ENABLE FORMAT GROUP INET6
+%token INSTANCE INTERFACE LLADDR LOCAL LOCKED MEMORY NIFS OWNER PATH PREFIX
+%token RDOMAIN SIZE SOCKET SWITCH UP VM VMID
%token <v.number> NUMBER
%token <v.string> STRING
%type <v.lladdr> lladdr
@@ -181,10 +181,27 @@ varset : STRING '=' STRING {
}
;
-main : LOCAL PREFIX STRING {
+main : LOCAL INET6 {
+ env->vmd_cfg.cfg_flags |= VMD_CFG_INET6;
+ }
+ | LOCAL INET6 PREFIX STRING {
+ struct address h;
+
+ if (host($4, &h) == -1 ||
+ h.ss.ss_family != AF_INET6 ||
+ h.prefixlen > 64 || h.prefixlen < 0) {
+ yyerror("invalid local inet6 prefix: %s", $4);
+ free($4);
+ YYERROR;
+ }
+
+ env->vmd_cfg.cfg_flags |= VMD_CFG_INET6;
+ env->vmd_cfg.cfg_flags &= ~VMD_CFG_AUTOINET6;
+ memcpy(&env->vmd_cfg.cfg_localprefix6, &h, sizeof(h));
+ }
+ | LOCAL PREFIX STRING {
struct address h;
- /* The local prefix is IPv4-only */
if (host($3, &h) == -1 ||
h.ss.ss_family != AF_INET ||
h.prefixlen > 32 || h.prefixlen < 0) {
@@ -747,6 +764,7 @@ lookup(char *s)
{ "group", GROUP },
{ "id", VMID },
{ "include", INCLUDE },
+ { "inet6", INET6 },
{ "instance", INSTANCE },
{ "interface", INTERFACE },
{ "interfaces", NIFS },
diff --git a/usr.sbin/vmd/priv.c b/usr.sbin/vmd/priv.c
index 0ccf09a7164..54db0b66b63 100644
--- a/usr.sbin/vmd/priv.c
+++ b/usr.sbin/vmd/priv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: priv.c,v 1.13 2017/11/11 02:50:07 mlarkin Exp $ */
+/* $OpenBSD: priv.c,v 1.14 2018/11/21 12:31:47 reyk Exp $ */
/*
* Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
@@ -27,6 +27,8 @@
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
#include <net/if_bridge.h>
#include <arpa/inet.h>
@@ -70,6 +72,10 @@ priv_run(struct privsep *ps, struct privsep_proc *p, void *arg)
/* Open our own socket for generic interface ioctls */
if ((env->vmd_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
fatal("socket");
+
+ /* But we need a different fd for IPv6 */
+ if ((env->vmd_fd6 = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
+ fatal("socket6");
}
int
@@ -83,6 +89,8 @@ priv_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
struct ifbreq ifbr;
struct ifgroupreq ifgr;
struct ifaliasreq ifra;
+ struct in6_aliasreq in6_ifra;
+ struct if_afreq ifar;
char type[IF_NAMESIZE];
switch (imsg->hdr.type) {
@@ -94,6 +102,7 @@ priv_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
case IMSG_VMDOP_PRIV_IFDOWN:
case IMSG_VMDOP_PRIV_IFGROUP:
case IMSG_VMDOP_PRIV_IFADDR:
+ case IMSG_VMDOP_PRIV_IFADDR6:
IMSG_SIZE_CHECK(imsg, &vfr);
memcpy(&vfr, imsg->data, sizeof(vfr));
@@ -177,22 +186,64 @@ priv_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
case IMSG_VMDOP_PRIV_IFADDR:
memset(&ifra, 0, sizeof(ifra));
+ if (vfr.vfr_addr.ss_family != AF_INET ||
+ vfr.vfr_addr.ss_family != vfr.vfr_mask.ss_family)
+ fatalx("%s: invalid address family", __func__);
+
/* Set the interface address */
strlcpy(ifra.ifra_name, vfr.vfr_name, sizeof(ifra.ifra_name));
- memcpy(&ifra.ifra_addr, &vfr.vfr_ifra.ifra_addr,
- sizeof(ifra.ifra_addr));
- ifra.ifra_addr.sa_family = AF_INET;
- ifra.ifra_addr.sa_len = sizeof(struct sockaddr_in);
+ ifra.ifra_addr.sa_len =
+ ifra.ifra_mask.sa_len =
+ sizeof(struct sockaddr_in);
- memcpy(&ifra.ifra_mask, &vfr.vfr_ifra.ifra_mask,
- sizeof(ifra.ifra_mask));
- ifra.ifra_mask.sa_family = AF_INET;
- ifra.ifra_mask.sa_len = sizeof(struct sockaddr_in);
+ memcpy(&ifra.ifra_addr, &vfr.vfr_addr,
+ ifra.ifra_addr.sa_len);
+ memcpy(&ifra.ifra_mask, &vfr.vfr_mask,
+ ifra.ifra_mask.sa_len);
if (ioctl(env->vmd_fd, SIOCAIFADDR, &ifra) < 0)
log_warn("SIOCAIFADDR");
break;
+ case IMSG_VMDOP_PRIV_IFADDR6:
+ memset(&ifar, 0, sizeof(ifar));
+ memset(&in6_ifra, 0, sizeof(in6_ifra));
+
+ if (vfr.vfr_addr.ss_family != AF_INET6 ||
+ vfr.vfr_addr.ss_family != vfr.vfr_mask.ss_family)
+ fatalx("%s: invalid address family", __func__);
+
+ /* First enable IPv6 on this interface */
+ strlcpy(ifar.ifar_name, vfr.vfr_name,
+ sizeof(ifar.ifar_name));
+ ifar.ifar_af = AF_INET6;
+ if (ioctl(env->vmd_fd, SIOCIFAFATTACH, (caddr_t)&ifar) < 0)
+ log_warn("SIOCIFAFATTACH");
+
+ /* Set the interface address */
+ strlcpy(in6_ifra.ifra_name, vfr.vfr_name,
+ sizeof(in6_ifra.ifra_name));
+
+ in6_ifra.ifra_addr.sin6_len =
+ in6_ifra.ifra_prefixmask.sin6_len =
+ sizeof(struct sockaddr_in6);
+
+ memcpy(&in6_ifra.ifra_addr, &vfr.vfr_addr,
+ in6_ifra.ifra_addr.sin6_len);
+ memcpy(&in6_ifra.ifra_prefixmask, &vfr.vfr_mask,
+ in6_ifra.ifra_prefixmask.sin6_len);
+ in6_ifra.ifra_prefixmask.sin6_scope_id = 0;
+
+ in6_ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
+ in6_ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
+
+ if (ioctl(env->vmd_fd6, SIOCDIFADDR_IN6, &in6_ifra) < 0 &&
+ errno != EADDRNOTAVAIL)
+ log_warn("SIOCDIFADDR_IN6");
+
+ if (ioctl(env->vmd_fd6, SIOCAIFADDR_IN6, &in6_ifra) < 0)
+ log_warn("SIOCAIFADDR_IN6");
+ break;
case IMSG_VMDOP_CONFIG:
config_getconfig(env, imsg);
break;
@@ -270,6 +321,7 @@ priv_validgroup(const char *name)
int
vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm)
{
+ char name[64];
struct vmd *env = ps->ps_env;
struct vm_create_params *vcp = &vm->vm_params.vmc_params;
struct vmd_if *vif;
@@ -277,6 +329,7 @@ vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm)
unsigned int i;
struct vmop_ifreq vfr, vfbr;
struct sockaddr_in *sin4;
+ struct sockaddr_in6 *sin6;
for (i = 0; i < VMM_MAX_NICS_PER_VM; i++) {
vif = &vm->vm_ifs[i];
@@ -284,6 +337,7 @@ vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm)
if (vif->vif_name == NULL)
break;
+ memset(&vfr, 0, sizeof(vfr));
if (strlcpy(vfr.vfr_name, vif->vif_name,
sizeof(vfr.vfr_name)) >= sizeof(vfr.vfr_name))
return (-1);
@@ -378,26 +432,58 @@ vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm)
/* Set interface address if it is a local interface */
if (vm->vm_params.vmc_ifflags[i] & VMIFF_LOCAL) {
- sin4 = (struct sockaddr_in *)&vfr.vfr_ifra.ifra_mask;
+ memset(&vfr.vfr_mask, 0, sizeof(vfr.vfr_mask));
+ memset(&vfr.vfr_addr, 0, sizeof(vfr.vfr_addr));
+
+ /* local IPv4 address with a /31 mask */
+ sin4 = (struct sockaddr_in *)&vfr.vfr_mask;
sin4->sin_family = AF_INET;
sin4->sin_len = sizeof(*sin4);
sin4->sin_addr.s_addr = htonl(0xfffffffe);
- sin4 = (struct sockaddr_in *)&vfr.vfr_ifra.ifra_addr;
+ sin4 = (struct sockaddr_in *)&vfr.vfr_addr;
sin4->sin_family = AF_INET;
sin4->sin_len = sizeof(*sin4);
if ((sin4->sin_addr.s_addr =
- vm_priv_addr(&env->vmd_cfg.cfg_localprefix,
+ vm_priv_addr(&env->vmd_cfg,
vm->vm_vmid, i, 0)) == 0)
return (-1);
+ inet_ntop(AF_INET, &sin4->sin_addr,
+ name, sizeof(name));
log_debug("%s: interface %s address %s/31",
- __func__, vfr.vfr_name,
- inet_ntoa(sin4->sin_addr));
+ __func__, vfr.vfr_name, name);
proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFADDR,
&vfr, sizeof(vfr));
}
+ if ((vm->vm_params.vmc_ifflags[i] & VMIFF_LOCAL) &&
+ (env->vmd_cfg.cfg_flags & VMD_CFG_INET6)) {
+ memset(&vfr.vfr_mask, 0, sizeof(vfr.vfr_mask));
+ memset(&vfr.vfr_addr, 0, sizeof(vfr.vfr_addr));
+
+ /* local IPv6 address with a /96 mask */
+ sin6 = ss2sin6(&vfr.vfr_mask);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ memset(&sin6->sin6_addr.s6_addr[0], 0xff, 12);
+ memset(&sin6->sin6_addr.s6_addr[12], 0, 4);
+
+ sin6 = ss2sin6(&vfr.vfr_addr);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ if (vm_priv_addr6(&env->vmd_cfg,
+ vm->vm_vmid, i, 0, &sin6->sin6_addr) == -1)
+ return (-1);
+
+ inet_ntop(AF_INET6, &sin6->sin6_addr,
+ name, sizeof(name));
+ log_debug("%s: interface %s address %s/96",
+ __func__, vfr.vfr_name, name);
+
+ proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFADDR6,
+ &vfr, sizeof(vfr));
+ }
}
return (0);
@@ -458,9 +544,10 @@ vm_priv_brconfig(struct privsep *ps, struct vmd_switch *vsw)
}
uint32_t
-vm_priv_addr(struct address *h, uint32_t vmid, int idx, int isvm)
+vm_priv_addr(struct vmd_config *cfg, uint32_t vmid, int idx, int isvm)
{
- in_addr_t prefix, mask, addr;
+ struct address *h = &cfg->cfg_localprefix;
+ in_addr_t prefix, mask, addr;
/*
* 1. Set the address prefix and mask, 100.64.0.0/10 by default.
@@ -501,3 +588,38 @@ vm_priv_addr(struct address *h, uint32_t vmid, int idx, int isvm)
return (addr);
}
+
+int
+vm_priv_addr6(struct vmd_config *cfg, uint32_t vmid,
+ int idx, int isvm, struct in6_addr *in6_addr)
+{
+ struct address *h = &cfg->cfg_localprefix6;
+ struct in6_addr addr, mask;
+ uint32_t addr4;
+
+ /* 1. Set the address prefix and mask, fd00::/8 by default. */
+ if (h->ss.ss_family != AF_INET6 ||
+ h->prefixlen < 0 || h->prefixlen > 128)
+ fatal("local prefix6");
+ addr = ss2sin6(&h->ss)->sin6_addr;
+ prefixlen2mask6(h->prefixlen, &mask);
+
+ /* 2. Encode the VM IPv4 address as subnet, fd00::NN:NN:0:0/96. */
+ if ((addr4 = vm_priv_addr(cfg, vmid, idx, 1)) == 0)
+ return (0);
+ memcpy(&addr.s6_addr[8], &addr4, sizeof(addr4));
+
+ /*
+ * 3. Set the last octet to 1 (host) or 2 (VM).
+ * The latter is currently not used inside vmd as we don't
+ * answer rtsol requests ourselves.
+ */
+ if (!isvm)
+ addr.s6_addr[15] = 1;
+ else
+ addr.s6_addr[15] = 2;
+
+ memcpy(in6_addr, &addr, sizeof(*in6_addr));
+
+ return (0);
+}
diff --git a/usr.sbin/vmd/vm.conf.5 b/usr.sbin/vmd/vm.conf.5
index f6b37f9efee..74d113b024e 100644
--- a/usr.sbin/vmd/vm.conf.5
+++ b/usr.sbin/vmd/vm.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: vm.conf.5,v 1.39 2018/10/30 17:56:54 anton Exp $
+.\" $OpenBSD: vm.conf.5,v 1.40 2018/11/21 12:31:47 reyk Exp $
.\"
.\" Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
.\" Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: October 30 2018 $
+.Dd $Mdocdate: November 21 2018 $
.Dt VM.CONF 5
.Os
.Sh NAME
@@ -100,6 +100,15 @@ in the
section below.
The default is
.Ar 100.64.0.0/10 .
+.It Ic local inet6 Op Ic prefix Ar address Ns Li / Ns Ar prefix
+Enable IPv6 on local interfaces and allocate routable subnets.
+If the prefix is not specified,
+a random prefix from the
+.Dq unique local
+network range
+.Ar fd00::/8
+will be generated on startup.
+The specified prefix length must be /64 or smaller.
.It Cm socket owner Ar user Ns Op : Ns Ar group
Set the control socket owner to the specified user or group.
Users with access to the control socket will be allowed to use
@@ -217,6 +226,19 @@ interface will auto-generate an IPv4 subnet for the interface,
configure a gateway address on the VM host side,
and run a simple DHCP/BOOTP server for the VM.
This option can be used for layer 3 mode without configuring a switch.
+.Pp
+If the global
+.Cm local inet6
+option is enabled, a routable IPv6 gateway address will be generated
+on the host side.
+Unlike the IPv4 option,
+.Nm vmd
+does not respond to DHCPv6 or router solicitation messages itself.
+Use
+.Xr rad 8
+listening on the interface group, e.g.
+.Ar interface tap
+for auto-configuring the VMs accordingly.
.It Cm interfaces Ar count
Optional minimum number of network interfaces to add to the VM.
If the
diff --git a/usr.sbin/vmd/vmd.c b/usr.sbin/vmd/vmd.c
index 8053b02620f..9423081df1e 100644
--- a/usr.sbin/vmd/vmd.c
+++ b/usr.sbin/vmd/vmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.c,v 1.104 2018/10/15 10:35:41 reyk Exp $ */
+/* $OpenBSD: vmd.c,v 1.105 2018/11/21 12:31:47 reyk Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -1923,6 +1923,25 @@ prefixlen2mask(uint8_t prefixlen)
}
void
+prefixlen2mask6(uint8_t prefixlen, struct in6_addr *mask)
+{
+ struct in6_addr s6;
+ int i;
+
+ if (prefixlen > 128)
+ prefixlen = 128;
+
+ memset(&s6, 0, sizeof(s6));
+ for (i = 0; i < prefixlen / 8; i++)
+ s6.s6_addr[i] = 0xff;
+ i = prefixlen % 8;
+ if (i)
+ s6.s6_addr[prefixlen / 8] = 0xff00 >> i;
+
+ memcpy(mask, &s6, sizeof(s6));
+}
+
+void
getmonotime(struct timeval *tv)
{
struct timespec ts;
diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h
index 7ae4e4bd65e..de87e4337ee 100644
--- a/usr.sbin/vmd/vmd.h
+++ b/usr.sbin/vmd/vmd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.h,v 1.84 2018/10/19 10:12:39 reyk Exp $ */
+/* $OpenBSD: vmd.h,v 1.85 2018/11/21 12:31:47 reyk Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -25,6 +25,7 @@
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
+#include <netinet6/in6_var.h>
#include <limits.h>
#include <stdio.h>
@@ -78,6 +79,9 @@
/* 100.64.0.0/10 from rfc6598 (IPv4 Prefix for Shared Address Space) */
#define VMD_DHCP_PREFIX "100.64.0.0/10"
+/* Unique local address for IPv6 */
+#define VMD_ULA_PREFIX "fd00::/8"
+
enum imsg_type {
IMSG_VMDOP_START_VM_REQUEST = IMSG_PROC_MAX,
IMSG_VMDOP_START_VM_CDROM,
@@ -109,6 +113,7 @@ enum imsg_type {
IMSG_VMDOP_PRIV_IFDOWN,
IMSG_VMDOP_PRIV_IFGROUP,
IMSG_VMDOP_PRIV_IFADDR,
+ IMSG_VMDOP_PRIV_IFADDR6,
IMSG_VMDOP_PRIV_IFRDOMAIN,
IMSG_VMDOP_VM_SHUTDOWN,
IMSG_VMDOP_VM_REBOOT,
@@ -140,10 +145,11 @@ struct vmop_id {
};
struct vmop_ifreq {
- uint32_t vfr_id;
- char vfr_name[IF_NAMESIZE];
- char vfr_value[VM_NAME_MAX];
- struct ifaliasreq vfr_ifra;
+ uint32_t vfr_id;
+ char vfr_name[IF_NAMESIZE];
+ char vfr_value[VM_NAME_MAX];
+ struct sockaddr_storage vfr_addr;
+ struct sockaddr_storage vfr_mask;
};
struct vmop_owner {
@@ -292,7 +298,12 @@ struct address {
TAILQ_HEAD(addresslist, address);
struct vmd_config {
+ unsigned int cfg_flags;
+#define VMD_CFG_INET6 0x01
+#define VMD_CFG_AUTOINET6 0x02
+
struct address cfg_localprefix;
+ struct address cfg_localprefix6;
};
struct vmd {
@@ -313,6 +324,7 @@ struct vmd {
struct userlist *vmd_users;
int vmd_fd;
+ int vmd_fd6;
int vmd_ptmfd;
};
@@ -372,6 +384,7 @@ void user_inc(struct vm_create_params *, struct vmd_user *, int);
int user_checklimit(struct vmd_user *, struct vm_create_params *);
char *get_string(uint8_t *, size_t);
uint32_t prefixlen2mask(uint8_t);
+void prefixlen2mask6(u_int8_t, struct in6_addr *);
void getmonotime(struct timeval *);
/* priv.c */
@@ -381,7 +394,9 @@ int priv_findname(const char *, const char **);
int priv_validgroup(const char *);
int vm_priv_ifconfig(struct privsep *, struct vmd_vm *);
int vm_priv_brconfig(struct privsep *, struct vmd_switch *);
-uint32_t vm_priv_addr(struct address *, uint32_t, int, int);
+uint32_t vm_priv_addr(struct vmd_config *, uint32_t, int, int);
+int vm_priv_addr6(struct vmd_config *, uint32_t, int, int,
+ struct in6_addr *);
/* vmm.c */
struct iovec;