Add global configuration option "local prefix" to change prefix for -L.
authorreyk <reyk@openbsd.org>
Fri, 21 Apr 2017 07:03:26 +0000 (07:03 +0000)
committerreyk <reyk@openbsd.org>
Fri, 21 Apr 2017 07:03:26 +0000 (07:03 +0000)
The default prefix is 100.64.0.0/10 from RFC6598.

Requested by sthen@ chris@
OK mlarkin@

usr.sbin/vmd/config.c
usr.sbin/vmd/control.c
usr.sbin/vmd/dhcp.c
usr.sbin/vmd/parse.y
usr.sbin/vmd/priv.c
usr.sbin/vmd/vm.conf.5
usr.sbin/vmd/vmd.c
usr.sbin/vmd/vmd.h
usr.sbin/vmd/vmm.c

index 05c3bfc..f100c7b 100644 (file)
@@ -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 <reyk@openbsd.org>
@@ -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)
 {
index 2f3d0d9..cb890ca 100644 (file)
@@ -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 <reyk@openbsd.org>
@@ -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);
        }
index b8b0500..65ea4ff 100644 (file)
@@ -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 <reyk@openbsd.org>
@@ -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));
index cf18170..6b35f95 100644 (file)
@@ -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 <reyk@openbsd.org>
@@ -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 <v.string>      STRING
 %token  <v.number>     NUMBER
 %type  <v.number>      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);
+}
index c0f1c36..a1e6414 100644 (file)
@@ -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 <reyk@openbsd.org>
@@ -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;
index ad610b3..e1dd399 100644 (file)
@@ -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 <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: 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
index fcd2c36..6591841 100644 (file)
@@ -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 <reyk@openbsd.org>
@@ -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) {
index 5dc0bb4..0846dbb 100644 (file)
@@ -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 <mlarkin@openbsd.org>
@@ -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 */
index f0ba6d9..3b0a453 100644 (file)
@@ -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 <mlarkin@openbsd.org>
@@ -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));