--- /dev/null
+/* $OpenBSD: vm_agentx.c,v 1.1 2022/09/13 10:28:19 martijn Exp $ */
+
+/*
+ * Copyright (c) 2022 Martijn van Duren <martijn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/un.h>
+
+#include <agentx.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "proc.h"
+#include "vmd.h"
+
+struct conn {
+ struct event ev;
+ struct agentx *agentx;
+};
+
+void vm_agentx_run(struct privsep *, struct privsep_proc *, void *);
+int vm_agentx_dispatch_parent(int, struct privsep_proc *, struct imsg *);
+void vm_agentx_configure(struct vmd_agentx *);
+static void vm_agentx_nofd(struct agentx *, void *, int);
+static void vm_agentx_tryconnect(int, short, void *);
+static void vm_agentx_read(int, short, void *);
+static void vm_agentx_flush_pending(void);
+static int vm_agentx_sortvir(const void *, const void *);
+static int vm_agentx_adminstate(int);
+static int vm_agentx_operstate(int);
+static void vm_agentx_vmHvSoftware(struct agentx_varbind *);
+static void vm_agentx_vmHvVersion(struct agentx_varbind *);
+static void vm_agentx_vmHvObjectID(struct agentx_varbind *);
+static void vm_agentx_vminfo(struct agentx_varbind *);
+
+static struct agentx_index *vmIndex;
+static struct agentx_object *vmNumber, *vmName, *vmUUID, *vmOSType;
+static struct agentx_object *vmAdminState, *vmOperState, *vmAutoStart;
+static struct agentx_object *vmPersistent, *vmCurCpuNumber, *vmMinCpuNumber;
+static struct agentx_object *vmMaxCpuNumber, *vmMemUnit, *vmCurMem, *vmMinMem;
+static struct agentx_object *vmMaxMem;
+
+static struct vmd_agentx *vmd_agentx;
+
+static struct agentx_varbind **vminfo = NULL;
+static size_t vminfolen = 0;
+static size_t vminfosize = 0;
+static int vmcollecting = 0;
+
+#define VMMIB AGENTX_MIB2, 236
+#define VMOBJECTS VMMIB, 1
+#define VMHVSOFTWARE VMOBJECTS, 1, 1
+#define VMHVVERSION VMOBJECTS, 1, 2
+#define VMHVOBJECTID VMOBJECTS, 1, 3
+#define VMNUMBER VMOBJECTS, 2
+#define VMENTRY VMOBJECTS, 4, 1
+#define VMINDEX VMENTRY, 1
+#define VMNAME VMENTRY, 2
+#define VMUUID VMENTRY, 3
+#define VMOSTYPE VMENTRY, 4
+#define VMADMINSTATE VMENTRY, 5
+#define VMOPERSTATE VMENTRY, 6
+#define VMAUTOSTART VMENTRY, 7
+#define VMPERSISTENT VMENTRY, 8
+#define VMCURCPUNUMBER VMENTRY, 9
+#define VMMINCPUNUMBER VMENTRY, 10
+#define VMMAXCPUNUMBER VMENTRY, 11
+#define VMMEMUNIT VMENTRY, 12
+#define VMCURMEM VMENTRY, 13
+#define VMMINMEM VMENTRY, 14
+#define VMMAXMEM VMENTRY, 15
+
+#define AGENTX_GROUP "_agentx"
+#define MEM_SCALE (1024 * 1024)
+
+static struct privsep_proc procs[] = {
+ { "parent", PROC_PARENT, vm_agentx_dispatch_parent },
+};
+
+void
+vm_agentx(struct privsep *ps, struct privsep_proc *p)
+{
+ struct group *grp;
+
+ /*
+ * Make sure we can connect to /var/agentx/master with the correct
+ * group permissions.
+ */
+ if ((grp = getgrnam(AGENTX_GROUP)) == NULL)
+ fatal("getgrnam");
+ ps->ps_pw->pw_gid = grp->gr_gid;
+
+ proc_run(ps, p, procs, nitems(procs), vm_agentx_run, NULL);
+}
+
+void
+vm_agentx_shutdown(void)
+{
+}
+
+void
+vm_agentx_run(struct privsep *ps, struct privsep_proc *p, void *arg)
+{
+ /*
+ * pledge in agentx process
+ * stdio - for malloc and basic I/O including events.
+ * recvfd - for the proc fd exchange.
+ * unix - for access to the agentx master socket.
+ */
+ if (pledge("stdio recvfd unix", NULL) == -1)
+ fatal("pledge");
+}
+
+int
+vm_agentx_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
+{
+ static struct vmop_info_result *vir = NULL;
+ static struct vmop_info_result *mvir = NULL;
+ struct vmd *env = p->p_ps->ps_env;
+ struct vmop_info_result *tvir;
+ struct agentx_object *reqObject;
+ static size_t nvir = 0;
+ static size_t virlen = 0;
+ static int error = 0;
+ size_t i, j, index;
+ enum agentx_request_type rtype;
+
+ switch (imsg->hdr.type) {
+ case IMSG_VMDOP_GET_INFO_VM_DATA:
+ if (error)
+ break;
+ if (nvir + 1 > virlen) {
+ tvir = reallocarray(vir, virlen + 10, sizeof(*vir));
+ if (tvir == NULL) {
+ log_warn("%s: Couldn't dispatch vm information",
+ __func__);
+ error = 1;
+ break;
+ }
+ virlen += 10;
+ vir = tvir;
+ }
+ memcpy(&(vir[nvir++]), imsg->data, sizeof(vir[nvir]));
+ break;
+ case IMSG_VMDOP_GET_INFO_VM_END_DATA:
+ vmcollecting = 0;
+ if (error) {
+ for (i = 0; i < vminfolen; i++)
+ agentx_varbind_error(vminfo[i]);
+ vminfolen = 0;
+ error = 0;
+ nvir = 0;
+ return (0);
+ }
+
+ qsort(vir, nvir, sizeof(*vir), vm_agentx_sortvir);
+ for (i = 0; i < vminfolen; i++) {
+ reqObject = agentx_varbind_get_object(vminfo[i]);
+ if (reqObject == vmNumber) {
+ agentx_varbind_integer(vminfo[i],
+ (int32_t)nvir);
+ continue;
+ }
+ index = agentx_varbind_get_index_integer(vminfo[i],
+ vmIndex);
+ rtype = agentx_varbind_request(vminfo[i]);
+ for (j = 0; j < nvir; j++) {
+ if (vir[j].vir_info.vir_id < index)
+ continue;
+ if (vir[j].vir_info.vir_id == index &&
+ (rtype == AGENTX_REQUEST_TYPE_GET ||
+ rtype ==
+ AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE))
+ break;
+ if (vir[j].vir_info.vir_id > index &&
+ (rtype == AGENTX_REQUEST_TYPE_GETNEXT ||
+ rtype ==
+ AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE))
+ break;
+ }
+ if (j == nvir) {
+ agentx_varbind_notfound(vminfo[i]);
+ continue;
+ }
+ mvir = &(vir[j]);
+ agentx_varbind_set_index_integer(vminfo[i], vmIndex,
+ mvir->vir_info.vir_id);
+ if (reqObject == vmName)
+ agentx_varbind_string(vminfo[i],
+ mvir->vir_info.vir_name);
+ else if (reqObject == vmUUID)
+ agentx_varbind_string(vminfo[i], "");
+ else if (reqObject == vmOSType)
+ agentx_varbind_string(vminfo[i], "");
+ else if (reqObject == vmAdminState)
+ agentx_varbind_integer(vminfo[i],
+ vm_agentx_adminstate(mvir->vir_state));
+ else if (reqObject == vmOperState)
+ agentx_varbind_integer(vminfo[i],
+ vm_agentx_operstate(mvir->vir_state));
+ else if (reqObject == vmAutoStart)
+ agentx_varbind_integer(vminfo[i],
+ mvir->vir_state & VM_STATE_DISABLED ?
+ 3 : 2);
+/* XXX We can dynamically create vm's but I don't know how to differentiate */
+ else if (reqObject == vmPersistent)
+ agentx_varbind_integer(vminfo[i], 1);
+/* We currently only support a single CPU */
+ else if (reqObject == vmCurCpuNumber ||
+ reqObject == vmMinCpuNumber ||
+ reqObject == vmMaxCpuNumber)
+ agentx_varbind_integer(vminfo[i],
+ mvir->vir_info.vir_ncpus);
+ else if (reqObject == vmMemUnit)
+ agentx_varbind_integer(vminfo[i], MEM_SCALE);
+ else if (reqObject == vmCurMem)
+ agentx_varbind_integer(vminfo[i],
+ mvir->vir_info.vir_used_size / MEM_SCALE);
+ else if (reqObject == vmMinMem)
+ agentx_varbind_integer(vminfo[i], -1);
+ else if (reqObject == vmMaxMem)
+ agentx_varbind_integer(vminfo[i],
+ mvir->vir_info.vir_memory_size / MEM_SCALE);
+/* We probably had a reload */
+ else
+ agentx_varbind_notfound(vminfo[i]);
+ }
+ vminfolen = 0;
+ nvir = 0;
+ break;
+ case IMSG_VMDOP_CONFIG:
+ config_getconfig(env, imsg);
+ vm_agentx_configure(&env->vmd_cfg.cfg_agentx);
+ break;
+ default:
+ return (-1);
+ }
+ return (0);
+}
+
+void
+vm_agentx_configure(struct vmd_agentx *env)
+{
+ static char curpath[sizeof(env->ax_path)];
+ static char curcontext[sizeof(env->ax_context)];
+ static struct conn *conn;
+ static struct agentx_session *sess;
+ static struct agentx_context *ctx;
+ struct agentx_region *vmMIB;
+ char *context = env->ax_context[0] == '\0' ? NULL : env->ax_context;
+ int changed = 0;
+
+ vmd_agentx = env;
+
+ agentx_log_fatal = fatalx;
+ agentx_log_warn = log_warnx;
+ agentx_log_info = log_info;
+ agentx_log_debug = log_debug;
+
+ if (!vmd_agentx->ax_enabled) {
+ if (conn != NULL) {
+ agentx_free(conn->agentx);
+ conn = NULL;
+ sess = NULL;
+ ctx = NULL;
+ vm_agentx_flush_pending();
+ }
+ return;
+ }
+
+ if (strcmp(curpath, vmd_agentx->ax_path) != 0 || conn == NULL) {
+ if (conn != NULL) {
+ agentx_free(conn->agentx);
+ conn = NULL;
+ sess = NULL;
+ ctx = NULL;
+ vm_agentx_flush_pending();
+ }
+
+ if ((conn = malloc(sizeof(*conn))) == NULL)
+ fatal(NULL);
+ /* Set to something so we can safely event_del */
+ evtimer_set(&conn->ev, vm_agentx_tryconnect, conn);
+ /* result assigned in vm_agentx_nofd */
+ if (agentx(vm_agentx_nofd, conn) == NULL)
+ fatal("Can't setup agentx");
+ sess = agentx_session(conn->agentx, NULL, 0, "vmd", 0);
+ if (sess == NULL)
+ fatal("Can't setup agentx session");
+ (void) strlcpy(curpath, vmd_agentx->ax_path, sizeof(curpath));
+ changed = 1;
+ }
+
+ if (strcmp(curcontext, vmd_agentx->ax_context) != 0 || changed) {
+ if (!changed) {
+ agentx_context_free(ctx);
+ vm_agentx_flush_pending();
+ }
+ if ((ctx = agentx_context(sess, context)) == NULL)
+ fatal("Can't setup agentx context");
+ strlcpy(curcontext, vmd_agentx->ax_context, sizeof(curcontext));
+ changed = 1;
+ }
+
+ if (!changed)
+ return;
+
+ if ((vmMIB = agentx_region(ctx, AGENTX_OID(VMMIB), 1)) == NULL)
+ fatal("agentx_region vmMIB");
+
+ if ((vmIndex = agentx_index_integer_dynamic(vmMIB,
+ AGENTX_OID(VMINDEX))) == NULL)
+ fatal("agentx_index_integer_dynamic");
+ if ((agentx_object(vmMIB, AGENTX_OID(VMHVSOFTWARE), NULL, 0, 0,
+ vm_agentx_vmHvSoftware)) == NULL ||
+ (agentx_object(vmMIB, AGENTX_OID(VMHVVERSION), NULL, 0, 0,
+ vm_agentx_vmHvVersion)) == NULL ||
+ (agentx_object(vmMIB, AGENTX_OID(VMHVOBJECTID), NULL, 0, 0,
+ vm_agentx_vmHvObjectID)) == NULL ||
+ (vmNumber = agentx_object(vmMIB, AGENTX_OID(VMNUMBER), NULL, 0, 0,
+ vm_agentx_vminfo)) == NULL ||
+ (vmName = agentx_object(vmMIB, AGENTX_OID(VMNAME), &vmIndex, 1, 0,
+ vm_agentx_vminfo)) == NULL ||
+ (vmUUID = agentx_object(vmMIB, AGENTX_OID(VMUUID), &vmIndex, 1, 0,
+ vm_agentx_vminfo)) == NULL ||
+ (vmOSType = agentx_object(vmMIB, AGENTX_OID(VMOSTYPE), &vmIndex, 1,
+ 0, vm_agentx_vminfo)) == NULL ||
+ (vmAdminState = agentx_object(vmMIB, AGENTX_OID(VMADMINSTATE),
+ &vmIndex, 1, 0, vm_agentx_vminfo)) == NULL ||
+ (vmOperState = agentx_object(vmMIB, AGENTX_OID(VMOPERSTATE),
+ &vmIndex, 1, 0, vm_agentx_vminfo)) == NULL ||
+ (vmAutoStart = agentx_object(vmMIB, AGENTX_OID(VMAUTOSTART),
+ &vmIndex, 1, 0, vm_agentx_vminfo)) == NULL ||
+ (vmPersistent = agentx_object(vmMIB, AGENTX_OID(VMPERSISTENT),
+ &vmIndex, 1, 0, vm_agentx_vminfo)) == NULL ||
+ (vmCurCpuNumber = agentx_object(vmMIB, AGENTX_OID(VMCURCPUNUMBER),
+ &vmIndex, 1, 0, vm_agentx_vminfo)) == NULL ||
+ (vmMinCpuNumber = agentx_object(vmMIB, AGENTX_OID(VMMINCPUNUMBER),
+ &vmIndex, 1, 0, vm_agentx_vminfo)) == NULL ||
+ (vmMaxCpuNumber = agentx_object(vmMIB, AGENTX_OID(VMMAXCPUNUMBER),
+ &vmIndex, 1, 0, vm_agentx_vminfo)) == NULL ||
+ (vmMemUnit = agentx_object(vmMIB, AGENTX_OID(VMMEMUNIT),
+ &vmIndex, 1, 0, vm_agentx_vminfo)) == NULL ||
+ (vmCurMem = agentx_object(vmMIB, AGENTX_OID(VMCURMEM),
+ &vmIndex, 1, 0, vm_agentx_vminfo)) == NULL ||
+ (vmMinMem = agentx_object(vmMIB, AGENTX_OID(VMMINMEM),
+ &vmIndex, 1, 0, vm_agentx_vminfo)) == NULL ||
+ (vmMaxMem = agentx_object(vmMIB, AGENTX_OID(VMMAXMEM),
+ &vmIndex, 1, 0, vm_agentx_vminfo)) == NULL)
+ fatal("agentx_object_ro");
+}
+
+static void
+vm_agentx_nofd(struct agentx *agentx, void *cookie, int close)
+{
+ struct conn *conn = cookie;
+
+ conn->agentx = agentx;
+ event_del(&conn->ev);
+ if (close)
+ free(conn);
+ else
+ vm_agentx_tryconnect(-1, 0, conn);
+}
+
+static void
+vm_agentx_tryconnect(int fd, short event, void *cookie)
+{
+ struct sockaddr_un sun;
+ struct timeval timeout = {3, 0};
+ struct conn *conn = cookie;
+
+ sun.sun_len = sizeof(sun);
+ sun.sun_family = AF_UNIX;
+ strlcpy(sun.sun_path, vmd_agentx->ax_path, sizeof(sun.sun_path));
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ log_warn("socket");
+ goto fail;
+ } else if (connect(fd, (struct sockaddr *)&sun, sun.sun_len) == -1) {
+ log_warn("connect");
+ close(fd);
+ goto fail;
+ }
+ agentx_connect(conn->agentx, fd);
+
+ event_set(&conn->ev, fd, EV_READ|EV_PERSIST, vm_agentx_read, conn);
+ event_add(&conn->ev, NULL);
+
+ return;
+fail:
+ evtimer_set(&conn->ev, vm_agentx_tryconnect, conn);
+ evtimer_add(&conn->ev, &timeout);
+}
+
+static void
+vm_agentx_read(int fd, short event, void *cookie)
+{
+ struct conn *conn = cookie;
+
+ agentx_read(conn->agentx);
+}
+
+static void
+vm_agentx_flush_pending(void)
+{
+ size_t i;
+
+ for (i = 0; i < vminfolen; i++)
+ agentx_varbind_notfound(vminfo[i]);
+ vminfolen = 0;
+}
+
+static int
+vm_agentx_sortvir(const void *c1, const void *c2)
+{
+ const struct vmop_info_result *v1 = c1, *v2 = c2;
+
+ return (v1->vir_info.vir_id < v2->vir_info.vir_id ? -1 :
+ v1->vir_info.vir_id > v2->vir_info.vir_id);
+}
+
+static int
+vm_agentx_adminstate(int mask)
+{
+ if (mask & VM_STATE_PAUSED)
+ return (3);
+ else if (mask & VM_STATE_RUNNING)
+ return (1);
+ else if (mask & VM_STATE_SHUTDOWN)
+ return (4);
+ /* Presence of absence of other flags */
+ else if (!mask || (mask & VM_STATE_DISABLED))
+ return (4);
+
+ return 4;
+}
+
+static int
+vm_agentx_operstate(int mask)
+{
+ if (mask & VM_STATE_PAUSED)
+ return (8);
+ else if (mask & VM_STATE_RUNNING)
+ return (4);
+ else if (mask & VM_STATE_SHUTDOWN)
+ return (11);
+ /* Presence of absence of other flags */
+ else if (!mask || (mask & VM_STATE_DISABLED))
+ return (11);
+
+ return (11);
+}
+
+static void
+vm_agentx_vmHvSoftware(struct agentx_varbind *vb)
+{
+ agentx_varbind_string(vb, "OpenBSD VMM");
+}
+
+static void
+vm_agentx_vmHvVersion(struct agentx_varbind *vb)
+{
+ int osversid[] = {CTL_KERN, KERN_OSRELEASE};
+ static char osvers[10] = "";
+ size_t osverslen;
+
+ if (osvers[0] == '\0') {
+ osverslen = sizeof(osvers);
+ if (sysctl(osversid, 2, osvers, &osverslen, NULL,
+ 0) == -1) {
+ log_warn("Failed vmHvVersion sysctl");
+ agentx_varbind_string(vb, "unknown");
+ return;
+ }
+ if (osverslen >= sizeof(osvers))
+ osverslen = sizeof(osvers) - 1;
+ osvers[osverslen] = '\0';
+ }
+ agentx_varbind_string(vb, osvers);
+}
+
+static void
+vm_agentx_vmHvObjectID(struct agentx_varbind *vb)
+{
+ agentx_varbind_oid(vb, AGENTX_OID(0, 0));
+}
+
+static void
+vm_agentx_vminfo(struct agentx_varbind *vb)
+{
+ extern struct vmd *env;
+ struct agentx_varbind **tvminfo;
+
+ if (vminfolen >= vminfosize) {
+ if ((tvminfo = reallocarray(vminfo, vminfosize + 10,
+ sizeof(*vminfo))) == NULL) {
+ log_warn("%s: Couldn't retrieve vm information",
+ __func__);
+ agentx_varbind_error(vb);
+ return;
+ }
+ vminfo = tvminfo;
+ vminfosize += 10;
+ }
+
+ if (!vmcollecting) {
+ if (proc_compose_imsg(&(env->vmd_ps), PROC_PARENT, -1,
+ IMSG_VMDOP_GET_INFO_VM_REQUEST, IMSG_AGENTX_PEERID,
+ -1, NULL, 0) == -1) {
+ log_warn("%s: Couldn't retrieve vm information",
+ __func__);
+ agentx_varbind_error(vb);
+ return;
+ }
+ vmcollecting = 1;
+ }
+
+ vminfo[vminfolen++] = vb;
+}
-/* $OpenBSD: vmd.c,v 1.131 2022/05/08 14:44:54 dv Exp $ */
+/* $OpenBSD: vmd.c,v 1.132 2022/09/13 10:28:19 martijn Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
int vmd_control_run(void);
int vmd_dispatch_control(int, struct privsep_proc *, struct imsg *);
int vmd_dispatch_vmm(int, struct privsep_proc *, struct imsg *);
+int vmd_dispatch_agentx(int, struct privsep_proc *, struct imsg *);
int vmd_dispatch_priv(int, struct privsep_proc *, struct imsg *);
int vmd_check_vmh(struct vm_dump_header *);
{ "priv", PROC_PRIV, vmd_dispatch_priv, priv },
{ "control", PROC_CONTROL, vmd_dispatch_control, control },
{ "vmm", PROC_VMM, vmd_dispatch_vmm, vmm, vmm_shutdown },
+ { "agentx", PROC_AGENTX, vmd_dispatch_agentx, vm_agentx, vm_agentx_shutdown, "/" }
};
enum privsep_procid privsep_process;
vir.vir_uid = vm->vm_uid;
vir.vir_gid = vm->vm_params.vmc_owner.gid;
}
- if (proc_compose_imsg(ps, PROC_CONTROL, -1, imsg->hdr.type,
+ if (proc_compose_imsg(ps,
+ imsg->hdr.peerid == IMSG_AGENTX_PEERID ?
+ PROC_AGENTX : PROC_CONTROL, -1, imsg->hdr.type,
imsg->hdr.peerid, -1, &vir, sizeof(vir)) == -1) {
log_debug("%s: GET_INFO_VM failed for vm %d, removing",
__func__, vm->vm_vmid);
log_debug("%s: vm: %d, vm_state: 0x%x",
__func__, vm->vm_vmid, vm->vm_state);
vir.vir_state = vm->vm_state;
- if (proc_compose_imsg(ps, PROC_CONTROL, -1,
+ if (proc_compose_imsg(ps,
+ imsg->hdr.peerid == IMSG_AGENTX_PEERID ?
+ PROC_AGENTX : PROC_CONTROL, -1,
IMSG_VMDOP_GET_INFO_VM_DATA,
imsg->hdr.peerid, -1, &vir,
sizeof(vir)) == -1) {
}
}
IMSG_SIZE_CHECK(imsg, &res);
- proc_forward_imsg(ps, imsg, PROC_CONTROL, -1);
+ proc_forward_imsg(ps, imsg,
+ imsg->hdr.peerid == IMSG_AGENTX_PEERID ?
+ PROC_AGENTX : PROC_CONTROL, -1);
break;
default:
return (-1);
return (0);
}
+int
+vmd_dispatch_agentx(int fd, struct privsep_proc *p, struct imsg *imsg)
+{
+ struct privsep *ps = p->p_ps;
+
+ switch (imsg->hdr.type) {
+ case IMSG_VMDOP_GET_INFO_VM_REQUEST:
+ proc_forward_imsg(ps, imsg, PROC_VMM, -1);
+ return (0);
+ default:
+ break;
+ }
+ return (-1);
+}
+
int
vmd_dispatch_priv(int fd, struct privsep_proc *p, struct imsg *imsg)
{
if (++env->vmd_nvm == 0) {
log_warnx("too many vms");
- return -1;
+ return (-1);
}
if ((n2i = calloc(1, sizeof(struct name2id))) == NULL) {
log_warnx("could not alloc vm name");
- return -1;
+ return (-1);
}
n2i->id = env->vmd_nvm;
n2i->uid = uid;
if (strlcpy(n2i->name, name, sizeof(n2i->name)) >= sizeof(n2i->name)) {
log_warnx("vm name too long");
free(n2i);
- return -1;
+ return (-1);
}
TAILQ_INSERT_TAIL(env->vmd_known, n2i, entry);
out:
*id = n2i->id;
- return 0;
+ return (0);
}
int