From: reyk Date: Fri, 21 Apr 2017 07:03:26 +0000 (+0000) Subject: Add global configuration option "local prefix" to change prefix for -L. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=c48cfcf432506f3d98df7bc4b9bc82cf96064fb3;p=openbsd Add global configuration option "local prefix" to change prefix for -L. The default prefix is 100.64.0.0/10 from RFC6598. Requested by sthen@ chris@ OK mlarkin@ --- diff --git a/usr.sbin/vmd/config.c b/usr.sbin/vmd/config.c index 05c3bfc1dab..f100c7b8aa5 100644 --- a/usr.sbin/vmd/config.c +++ b/usr.sbin/vmd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.29 2017/03/26 18:32:39 reyk Exp $ */ +/* $OpenBSD: config.c,v 1.30 2017/04/21 07:03:26 reyk Exp $ */ /* * Copyright (c) 2015 Reyk Floeter @@ -50,7 +50,9 @@ config_init(struct vmd *env) /* Global configuration */ ps->ps_what[PROC_PARENT] = CONFIG_ALL; ps->ps_what[PROC_VMM] = CONFIG_VMS; - ps->ps_what[PROC_PRIV] = 0; + + if (host(VMD_DHCP_PREFIX, &env->vmd_cfg.cfg_localprefix) == -1) + return (-1); /* Other configuration */ what = ps->ps_what[privsep_process]; @@ -77,6 +79,10 @@ config_purge(struct vmd *env, unsigned int reset) struct vmd_switch *vsw; unsigned int what; + /* Reset global configuration (prefix was verified before) */ + (void)host(VMD_DHCP_PREFIX, &env->vmd_cfg.cfg_localprefix); + + /* Reset other configuration */ what = ps->ps_what[privsep_process] & reset; if (what & CONFIG_VMS && env->vmd_vms != NULL) { while ((vm = TAILQ_FIRST(env->vmd_vms)) != NULL) @@ -90,6 +96,31 @@ config_purge(struct vmd *env, unsigned int reset) } } +int +config_setconfig(struct vmd *env) +{ + struct privsep *ps = &env->vmd_ps; + unsigned int id; + + for (id = 0; id < PROC_MAX; id++) { + if (id == privsep_process) + continue; + proc_compose(ps, id, IMSG_VMDOP_CONFIG, &env->vmd_cfg, + sizeof(env->vmd_cfg)); + } + + return (0); +} + +int +config_getconfig(struct vmd *env, struct imsg *imsg) +{ + IMSG_SIZE_CHECK(imsg, &env->vmd_cfg); + memcpy(&env->vmd_cfg, imsg->data, sizeof(env->vmd_cfg)); + + return (0); +} + int config_setreset(struct vmd *env, unsigned int reset) { diff --git a/usr.sbin/vmd/control.c b/usr.sbin/vmd/control.c index 2f3d0d9e74b..cb890ca6826 100644 --- a/usr.sbin/vmd/control.c +++ b/usr.sbin/vmd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.16 2017/03/15 12:42:12 reyk Exp $ */ +/* $OpenBSD: control.c,v 1.17 2017/04/21 07:03:26 reyk Exp $ */ /* * Copyright (c) 2010-2015 Reyk Floeter @@ -79,6 +79,7 @@ int control_dispatch_vmd(int fd, struct privsep_proc *p, struct imsg *imsg) { struct ctl_conn *c; + struct privsep *ps = p->p_ps; switch (imsg->hdr.type) { case IMSG_VMDOP_START_VM_RESPONSE: @@ -93,6 +94,12 @@ control_dispatch_vmd(int fd, struct privsep_proc *p, struct imsg *imsg) imsg_compose_event(&c->iev, imsg->hdr.type, 0, 0, -1, imsg->data, IMSG_DATA_SIZE(imsg)); break; + case IMSG_VMDOP_CONFIG: + config_getconfig(ps->ps_env, imsg); + break; + case IMSG_CTL_RESET: + config_getreset(ps->ps_env, imsg); + break; default: return (-1); } diff --git a/usr.sbin/vmd/dhcp.c b/usr.sbin/vmd/dhcp.c index b8b05000e3a..65ea4ffae33 100644 --- a/usr.sbin/vmd/dhcp.c +++ b/usr.sbin/vmd/dhcp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcp.c,v 1.1 2017/04/19 15:38:32 reyk Exp $ */ +/* $OpenBSD: dhcp.c,v 1.2 2017/04/21 07:03:26 reyk Exp $ */ /* * Copyright (c) 2017 Reyk Floeter @@ -33,6 +33,7 @@ #include "virtio.h" static const uint8_t broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +extern struct vmd *env; ssize_t dhcp_request(struct vionet_dev *dev, char *buf, size_t buflen, char **obuf) @@ -81,13 +82,15 @@ dhcp_request(struct vionet_dev *dev, char *buf, size_t buflen, char **obuf) resp.hlen = req.hlen; resp.xid = req.xid; - if ((in.s_addr = vm_priv_addr(dev->vm_vmid, dev->idx, 1)) == 0) + if ((in.s_addr = vm_priv_addr(&env->vmd_cfg.cfg_localprefix, + dev->vm_vmid, dev->idx, 1)) == 0) return (-1); memcpy(&resp.yiaddr, &in, sizeof(in)); memcpy(&ss2sin(&pc.pc_dst)->sin_addr, &in, sizeof(in)); ss2sin(&pc.pc_dst)->sin_port = htons(CLIENT_PORT); - if ((in.s_addr = vm_priv_addr(dev->vm_vmid, dev->idx, 0)) == 0) + if ((in.s_addr = vm_priv_addr(&env->vmd_cfg.cfg_localprefix, + dev->vm_vmid, dev->idx, 0)) == 0) return (-1); memcpy(&resp.siaddr, &in, sizeof(in)); memcpy(&ss2sin(&pc.pc_src)->sin_addr, &in, sizeof(in)); diff --git a/usr.sbin/vmd/parse.y b/usr.sbin/vmd/parse.y index cf181701ada..6b35f95a37c 100644 --- a/usr.sbin/vmd/parse.y +++ b/usr.sbin/vmd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.25 2017/04/19 15:38:32 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.26 2017/04/21 07:03:26 reyk Exp $ */ /* * Copyright (c) 2007-2016 Reyk Floeter @@ -116,7 +116,7 @@ typedef struct { %token INCLUDE ERROR %token ADD DISK DOWN GROUP INTERFACE NIFS PATH SIZE SWITCH UP VMID -%token ENABLE DISABLE VM BOOT LLADDR MEMORY OWNER LOCKED LOCAL +%token ENABLE DISABLE VM BOOT LLADDR MEMORY OWNER LOCKED LOCAL PREFIX %token STRING %token NUMBER %type disable @@ -134,6 +134,7 @@ grammar : /* empty */ | grammar include '\n' | grammar '\n' | grammar varset '\n' + | grammar main '\n' | grammar switch '\n' | grammar vm '\n' | grammar error '\n' { file->errors++; } @@ -170,6 +171,22 @@ varset : STRING '=' STRING { } ; +main : 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) { + yyerror("invalid local prefix: %s", $3); + free($3); + YYERROR; + } + + memcpy(&env->vmd_cfg.cfg_localprefix, &h, sizeof(h)); + } + ; + switch : SWITCH string { if ((vsw = calloc(1, sizeof(*vsw))) == NULL) fatal("could not allocate switch"); @@ -627,6 +644,7 @@ lookup(char *s) { "locked", LOCKED }, { "memory", MEMORY }, { "owner", OWNER }, + { "prefix", PREFIX }, { "size", SIZE }, { "switch", SWITCH }, { "up", UP }, @@ -1094,3 +1112,43 @@ parse_disk(char *word) return (0); } + +int +host(const char *str, struct address *h) +{ + struct addrinfo hints, *res; + int prefixlen; + char *s, *p; + const char *errstr; + + if ((s = strdup(str)) == NULL) { + log_warn("strdup"); + goto fail; + } + + if ((p = strrchr(s, '/')) != NULL) { + *p++ = '\0'; + prefixlen = strtonum(p, 0, 128, &errstr); + if (errstr) { + log_warnx("prefixlen is %s: %s", errstr, p); + goto fail; + } + } else + prefixlen = 128; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(s, NULL, &hints, &res) == 0) { + memset(h, 0, sizeof(*h)); + memcpy(&h->ss, res->ai_addr, res->ai_addrlen); + h->prefixlen = prefixlen; + freeaddrinfo(res); + free(s); + return (0); + } + + fail: + free(s); + return (-1); +} diff --git a/usr.sbin/vmd/priv.c b/usr.sbin/vmd/priv.c index c0f1c36fd25..a1e6414cf6b 100644 --- a/usr.sbin/vmd/priv.c +++ b/usr.sbin/vmd/priv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: priv.c,v 1.7 2017/04/19 15:38:32 reyk Exp $ */ +/* $OpenBSD: priv.c,v 1.8 2017/04/21 07:03:26 reyk Exp $ */ /* * Copyright (c) 2016 Reyk Floeter @@ -102,6 +102,9 @@ priv_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) fatalx("%s: rejected priv operation on interface: %s", __func__, vfr.vfr_name); break; + case IMSG_VMDOP_CONFIG: + case IMSG_CTL_RESET: + break; default: return (-1); } @@ -183,6 +186,12 @@ priv_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) if (ioctl(env->vmd_fd, SIOCAIFADDR, &ifra) < 0) log_warn("SIOCAIFADDR"); break; + case IMSG_VMDOP_CONFIG: + config_getconfig(env, imsg); + break; + case IMSG_CTL_RESET: + config_getreset(env, imsg); + break; default: return (-1); } @@ -245,6 +254,7 @@ priv_validgroup(const char *name) int vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm) { + struct vmd *env = ps->ps_env; struct vm_create_params *vcp = &vm->vm_params.vmc_params; struct vmd_if *vif; struct vmd_switch *vsw; @@ -333,7 +343,8 @@ vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm) sin4->sin_family = AF_INET; sin4->sin_len = sizeof(*sin4); if ((sin4->sin_addr.s_addr = - vm_priv_addr(vm->vm_vmid, i, 0)) == 0) + vm_priv_addr(&env->vmd_cfg.cfg_localprefix, + vm->vm_vmid, i, 0)) == 0) return (-1); log_debug("%s: interface %s address %s/31", @@ -393,16 +404,18 @@ vm_priv_brconfig(struct privsep *ps, struct vmd_switch *vsw) } uint32_t -vm_priv_addr(uint32_t vmid, int idx, int isvm) +vm_priv_addr(struct address *h, uint32_t vmid, int idx, int isvm) { - in_addr_t prefix, mask, addr; + in_addr_t prefix, mask, addr; /* * 1. Set the address prefix and mask, 100.64.0.0/10 by default. - * XXX make the global prefix configurable. */ - prefix = inet_addr(VMD_DHCP_PREFIX); - mask = prefixlen2mask(VMD_DHCP_PREFIXLEN); + if (h->ss.ss_family != AF_INET || + h->prefixlen < 0 || h->prefixlen > 32) + fatal("local prefix"); + prefix = ss2sin(&h->ss)->sin_addr.s_addr; + mask = prefixlen2mask(h->prefixlen); /* 2. Encode the VM ID as a per-VM subnet range N, 10.64.N.0/24. */ addr = vmid << 8; diff --git a/usr.sbin/vmd/vm.conf.5 b/usr.sbin/vmd/vm.conf.5 index ad610b30b8a..e1dd3997005 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.18 2017/04/19 15:38:32 reyk Exp $ +.\" $OpenBSD: vm.conf.5,v 1.19 2017/04/21 07:03:26 reyk Exp $ .\" .\" Copyright (c) 2015 Mike Larkin .\" Copyright (c) 2015 Reyk Floeter @@ -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: April 19 2017 $ +.Dd $Mdocdate: April 21 2017 $ .Dt VM.CONF 5 .Os .Sh NAME @@ -31,11 +31,14 @@ The VMM subsystem is responsible for creating, destroying, and executing VMs. .Sh SECTIONS .Nm -is divided into three main sections: +is divided into four main sections: .Bl -tag -width xxxx .It Sy Macros User-defined variables may be defined and used later, simplifying the configuration file. +.It Sy Global Configuration +Global settings for +.Xr vmd 8 . .It Sy VM Configuration Configuration for each individual virtual machine. .It Sy Switch Configuration @@ -85,6 +88,19 @@ vm "vm1.example.com" { boot $ramdisk } .Ed +.Sh GLOBAL CONFIGURATION +The following setting can be configured globally: +.Bl -tag -width Ds +.It Ic local prefix Ar address Ns Li / Ns Ar prefix +Set the network prefix that is used to allocate subnets for +local interfaces, see +.Ic local interface +in the +.Sx VM CONFIGURATION +section below. +The default is +.Ar 100.64.0.0/10 . +.El .Sh VM CONFIGURATION Each .Ic vm diff --git a/usr.sbin/vmd/vmd.c b/usr.sbin/vmd/vmd.c index fcd2c3696b9..65918419b3b 100644 --- a/usr.sbin/vmd/vmd.c +++ b/usr.sbin/vmd/vmd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmd.c,v 1.57 2017/04/19 15:38:32 reyk Exp $ */ +/* $OpenBSD: vmd.c,v 1.58 2017/04/21 07:03:26 reyk Exp $ */ /* * Copyright (c) 2015 Reyk Floeter @@ -562,6 +562,10 @@ vmd_configure(void) return (-1); } + /* Send shared global configuration to all children */ + if (config_setconfig(env) == -1) + return (-1); + return (0); } @@ -598,6 +602,10 @@ vmd_reload(unsigned int reset, const char *filename) if (vm->vm_running == 0) vm_remove(vm); } + + /* Update shared global configuration in all children */ + if (config_setconfig(env) == -1) + return; } if (parse_config(filename) == -1) { diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h index 5dc0bb4d81d..0846dbb6436 100644 --- a/usr.sbin/vmd/vmd.h +++ b/usr.sbin/vmd/vmd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmd.h,v 1.51 2017/04/19 15:38:32 reyk Exp $ */ +/* $OpenBSD: vmd.h,v 1.52 2017/04/21 07:03:26 reyk Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -51,8 +51,7 @@ #define VM_DEFAULT_MEMORY 512 /* 100.64.0.0/10 from rfc6598 (IPv4 Prefix for Shared Address Space) */ -#define VMD_DHCP_PREFIX "100.64.0.0" -#define VMD_DHCP_PREFIXLEN 10 +#define VMD_DHCP_PREFIX "100.64.0.0/10" #ifdef VMD_DEBUG #define dprintf(x...) do { log_debug(x); } while(0) @@ -82,7 +81,8 @@ enum imsg_type { IMSG_VMDOP_PRIV_IFGROUP, IMSG_VMDOP_PRIV_IFADDR, IMSG_VMDOP_VM_SHUTDOWN, - IMSG_VMDOP_VM_REBOOT + IMSG_VMDOP_VM_REBOOT, + IMSG_VMDOP_CONFIG }; struct vmop_result { @@ -189,17 +189,30 @@ struct vmd_vm { }; TAILQ_HEAD(vmlist, vmd_vm); +struct address { + struct sockaddr_storage ss; + int prefixlen; + TAILQ_ENTRY(address) entry; +}; +TAILQ_HEAD(addresslist, address); + +struct vmd_config { + struct address cfg_localprefix; +}; + struct vmd { struct privsep vmd_ps; const char *vmd_conffile; + /* global configuration that is sent to the children */ + struct vmd_config vmd_cfg; + int vmd_debug; int vmd_verbose; int vmd_noaction; uint32_t vmd_nvm; struct vmlist *vmd_vms; - uint32_t vmd_nswitches; struct switchlist *vmd_switches; @@ -266,7 +279,7 @@ 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(uint32_t, int, int); +uint32_t vm_priv_addr(struct address *, uint32_t, int, int); /* vmm.c */ void vmm(struct privsep *, struct privsep_proc *); @@ -286,6 +299,8 @@ __dead void vm_shutdown(unsigned int); /* control.c */ int config_init(struct vmd *); void config_purge(struct vmd *, unsigned int); +int config_setconfig(struct vmd *); +int config_getconfig(struct vmd *, struct imsg *); int config_setreset(struct vmd *, unsigned int); int config_getreset(struct vmd *, struct imsg *); int config_setvm(struct privsep *, struct vmd_vm *, uint32_t, uid_t); @@ -300,5 +315,6 @@ void vmboot_close(FILE *, struct vmboot_params *); /* parse.y */ int parse_config(const char *); int cmdline_symset(char *); +int host(const char *, struct address *); #endif /* VMD_H */ diff --git a/usr.sbin/vmd/vmm.c b/usr.sbin/vmd/vmm.c index f0ba6d9ac3e..3b0a453032b 100644 --- a/usr.sbin/vmd/vmm.c +++ b/usr.sbin/vmd/vmm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm.c,v 1.68 2017/04/06 18:07:13 reyk Exp $ */ +/* $OpenBSD: vmm.c,v 1.69 2017/04/21 07:03:26 reyk Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -175,6 +175,9 @@ vmm_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) res = get_info_vm(ps, imsg, 0); cmd = IMSG_VMDOP_GET_INFO_VM_END_DATA; break; + case IMSG_VMDOP_CONFIG: + config_getconfig(env, imsg); + break; case IMSG_CTL_RESET: IMSG_SIZE_CHECK(imsg, &mode); memcpy(&mode, imsg->data, sizeof(mode));