diff options
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/vmd/config.c | 37 | ||||
-rw-r--r-- | usr.sbin/vmd/dhcp.c | 6 | ||||
-rw-r--r-- | usr.sbin/vmd/parse.y | 30 | ||||
-rw-r--r-- | usr.sbin/vmd/priv.c | 154 | ||||
-rw-r--r-- | usr.sbin/vmd/vm.conf.5 | 26 | ||||
-rw-r--r-- | usr.sbin/vmd/vmd.c | 21 | ||||
-rw-r--r-- | usr.sbin/vmd/vmd.h | 27 |
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; |