summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authordv <dv@openbsd.org>2021-03-29 23:37:01 +0000
committerdv <dv@openbsd.org>2021-03-29 23:37:01 +0000
commit97f33f1d96ff4ad5235952e1d2fee5ab905682f6 (patch)
tree5f98db859e14c58bc80df932102f19a273d7d13a /usr.sbin
parentInstall apm(8) and and apmd(8) under MI MANPATH (diff)
downloadwireguard-openbsd-97f33f1d96ff4ad5235952e1d2fee5ab905682f6.tar.xz
wireguard-openbsd-97f33f1d96ff4ad5235952e1d2fee5ab905682f6.zip
Propagate host-side tap(4) lladdr to guest vm process to allow unicast dhcp
and bootp renewals with vmd(8)'s built-in dhcp server. Previous behavior ignored did not intercept these packets and instead transmitted them. This should make vmd(8)'s dhcp behave more as a true dhcp server should and allows it to work properly with the new dhcpleased(8) attempting a renewal. OK mlarkin@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/vmd/config.c9
-rw-r--r--usr.sbin/vmd/dhcp.c9
-rw-r--r--usr.sbin/vmd/priv.c21
-rw-r--r--usr.sbin/vmd/virtio.c27
-rw-r--r--usr.sbin/vmd/virtio.h4
-rw-r--r--usr.sbin/vmd/vm.c13
-rw-r--r--usr.sbin/vmd/vmd.c23
-rw-r--r--usr.sbin/vmd/vmd.h15
-rw-r--r--usr.sbin/vmd/vmm.c15
9 files changed, 124 insertions, 12 deletions
diff --git a/usr.sbin/vmd/config.c b/usr.sbin/vmd/config.c
index 9bcf49b5304..46acf78ce8a 100644
--- a/usr.sbin/vmd/config.c
+++ b/usr.sbin/vmd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.60 2021/03/19 09:29:33 kn Exp $ */
+/* $OpenBSD: config.c,v 1.61 2021/03/29 23:37:01 dv Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -227,6 +227,7 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, uint32_t peerid, uid_t uid)
char base[PATH_MAX];
unsigned int unit;
struct timeval tv, rate, since_last;
+ struct vmop_addr_req var;
errno = 0;
@@ -499,6 +500,12 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, uint32_t peerid, uid_t uid)
proc_compose_imsg(ps, PROC_VMM, -1,
IMSG_VMDOP_START_VM_IF, vm->vm_vmid, tapfds[i],
&i, sizeof(i));
+
+ memset(&var, 0, sizeof(var));
+ var.var_vmid = vm->vm_vmid;
+ var.var_nic_idx = i;
+ proc_compose_imsg(ps, PROC_PRIV, -1, IMSG_VMDOP_PRIV_GET_ADDR,
+ vm->vm_vmid, dup(tapfds[i]), &var, sizeof(var));
}
if (!(vm->vm_state & VM_STATE_RECEIVED))
diff --git a/usr.sbin/vmd/dhcp.c b/usr.sbin/vmd/dhcp.c
index 63d17d0dcc9..987d4386f9f 100644
--- a/usr.sbin/vmd/dhcp.c
+++ b/usr.sbin/vmd/dhcp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcp.c,v 1.8 2018/12/27 19:51:30 anton Exp $ */
+/* $OpenBSD: dhcp.c,v 1.9 2021/03/29 23:37:01 dv Exp $ */
/*
* Copyright (c) 2017 Reyk Floeter <reyk@openbsd.org>
@@ -57,8 +57,11 @@ dhcp_request(struct vionet_dev *dev, char *buf, size_t buflen, char **obuf)
if ((offset = decode_hw_header(buf, buflen, 0, &pc, HTYPE_ETHER)) < 0)
return (-1);
- if (memcmp(pc.pc_smac, dev->mac, ETHER_ADDR_LEN) != 0 ||
- memcmp(pc.pc_dmac, broadcast, ETHER_ADDR_LEN) != 0)
+ if (memcmp(pc.pc_dmac, broadcast, ETHER_ADDR_LEN) != 0 &&
+ memcmp(pc.pc_dmac, dev->hostmac, ETHER_ADDR_LEN) != 0)
+ return (-1);
+
+ if (memcmp(pc.pc_smac, dev->mac, ETHER_ADDR_LEN) != 0)
return (-1);
if ((offset = decode_udp_ip_header(buf, buflen, offset, &pc)) < 0)
diff --git a/usr.sbin/vmd/priv.c b/usr.sbin/vmd/priv.c
index 7335f0c4a89..6718174765a 100644
--- a/usr.sbin/vmd/priv.c
+++ b/usr.sbin/vmd/priv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: priv.c,v 1.16 2021/02/28 22:56:09 dlg Exp $ */
+/* $OpenBSD: priv.c,v 1.17 2021/03/29 23:37:01 dv Exp $ */
/*
* Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
@@ -92,6 +92,8 @@ priv_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
struct ifaliasreq ifra;
struct in6_aliasreq in6_ifra;
struct if_afreq ifar;
+ struct vmop_addr_req vareq;
+ struct vmop_addr_result varesult;
char type[IF_NAMESIZE];
switch (imsg->hdr.type) {
@@ -115,6 +117,7 @@ priv_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
break;
case IMSG_VMDOP_CONFIG:
case IMSG_CTL_RESET:
+ case IMSG_VMDOP_PRIV_GET_ADDR:
break;
default:
return (-1);
@@ -245,6 +248,22 @@ priv_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
if (ioctl(env->vmd_fd6, SIOCAIFADDR_IN6, &in6_ifra) == -1)
log_warn("SIOCAIFADDR_IN6");
break;
+ case IMSG_VMDOP_PRIV_GET_ADDR:
+ IMSG_SIZE_CHECK(imsg, &vareq);
+ memcpy(&vareq, imsg->data, sizeof(vareq));
+
+ varesult.var_vmid = vareq.var_vmid;
+ varesult.var_nic_idx = vareq.var_nic_idx;
+
+ /* resolve lladdr for the tap(4) and send back to parent */
+ if (ioctl(imsg->fd, SIOCGIFADDR, &varesult.var_addr) != 0)
+ log_warn("SIOCGIFADDR");
+ else
+ proc_compose_imsg(ps, PROC_PARENT, -1,
+ IMSG_VMDOP_PRIV_GET_ADDR_RESPONSE, imsg->hdr.peerid,
+ -1, &varesult, sizeof(varesult));
+ close(imsg->fd);
+ break;
case IMSG_VMDOP_CONFIG:
config_getconfig(env, imsg);
break;
diff --git a/usr.sbin/vmd/virtio.c b/usr.sbin/vmd/virtio.c
index 1d269ed65ff..f937bf602f6 100644
--- a/usr.sbin/vmd/virtio.c
+++ b/usr.sbin/vmd/virtio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: virtio.c,v 1.83 2021/03/26 17:40:03 deraadt Exp $ */
+/* $OpenBSD: virtio.c,v 1.84 2021/03/29 23:37:01 dv Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -2034,6 +2034,31 @@ virtio_init(struct vmd_vm *vm, int child_cdrom,
evtimer_set(&vmmci.timeout, vmmci_timeout, NULL);
}
+/*
+ * vionet_set_hostmac
+ *
+ * Sets the hardware address for the host-side tap(4) on a vionet_dev.
+ *
+ * This should only be called from the event-loop thread
+ *
+ * vm: pointer to the current vmd_vm instance
+ * idx: index into the array of vionet_dev's for the target vionet_dev
+ * addr: ethernet address to set
+ */
+void
+vionet_set_hostmac(struct vmd_vm *vm, unsigned int idx, uint8_t *addr)
+{
+ struct vmop_create_params *vmc = &vm->vm_params;
+ struct vm_create_params *vcp = &vmc->vmc_params;
+ struct vionet_dev *dev;
+
+ if (idx > vcp->vcp_nnics)
+ fatalx("vionet_set_hostmac");
+
+ dev = &vionet[idx];
+ memcpy(dev->hostmac, addr, sizeof(dev->hostmac));
+}
+
void
virtio_shutdown(struct vmd_vm *vm)
{
diff --git a/usr.sbin/vmd/virtio.h b/usr.sbin/vmd/virtio.h
index 1672cca267c..9d7ef81831d 100644
--- a/usr.sbin/vmd/virtio.h
+++ b/usr.sbin/vmd/virtio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: virtio.h,v 1.36 2021/01/07 17:11:38 tracey Exp $ */
+/* $OpenBSD: virtio.h,v 1.37 2021/03/29 23:37:01 dv Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -208,6 +208,7 @@ struct vionet_dev {
uint32_t vm_vmid;
int irq;
uint8_t mac[6];
+ uint8_t hostmac[6];
int idx;
int lockedmac;
@@ -298,6 +299,7 @@ void vionet_notify_rx(struct vionet_dev *);
int vionet_notify_tx(struct vionet_dev *);
void vionet_process_rx(uint32_t);
int vionet_enq_rx(struct vionet_dev *, char *, ssize_t, int *);
+void vionet_set_hostmac(struct vmd_vm *, unsigned int, uint8_t *);
int vmmci_io(int, uint16_t, uint32_t *, uint8_t *, void *, uint8_t);
int vmmci_dump(int);
diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c
index bf515eb3778..9ffd1598b21 100644
--- a/usr.sbin/vmd/vm.c
+++ b/usr.sbin/vmd/vm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm.c,v 1.60 2021/03/19 09:29:33 kn Exp $ */
+/* $OpenBSD: vm.c,v 1.61 2021/03/29 23:37:01 dv Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -394,6 +394,7 @@ vm_dispatch_vmm(int fd, short event, void *arg)
{
struct vmd_vm *vm = arg;
struct vmop_result vmr;
+ struct vmop_addr_result var;
struct imsgev *iev = &vm->vm_iev;
struct imsgbuf *ibuf = &iev->ibuf;
struct imsg imsg;
@@ -471,6 +472,16 @@ vm_dispatch_vmm(int fd, short event, void *arg)
_exit(0);
}
break;
+ case IMSG_VMDOP_PRIV_GET_ADDR_RESPONSE:
+ IMSG_SIZE_CHECK(&imsg, &var);
+ memcpy(&var, imsg.data, sizeof(var));
+
+ log_debug("%s: received tap addr %s for nic %d",
+ vm->vm_params.vmc_params.vcp_name,
+ ether_ntoa((void *)var.var_addr), var.var_nic_idx);
+
+ vionet_set_hostmac(vm, var.var_nic_idx, var.var_addr);
+ break;
default:
fatalx("%s: got invalid imsg %d from %s",
__func__, imsg.hdr.type,
diff --git a/usr.sbin/vmd/vmd.c b/usr.sbin/vmd/vmd.c
index 3bceb5c0593..cd585d5a197 100644
--- a/usr.sbin/vmd/vmd.c
+++ b/usr.sbin/vmd/vmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.c,v 1.120 2021/01/27 07:21:54 deraadt Exp $ */
+/* $OpenBSD: vmd.c,v 1.121 2021/03/29 23:37:01 dv Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -58,6 +58,7 @@ void vmd_shutdown(void);
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_priv(int, struct privsep_proc *, struct imsg *);
int vmd_check_vmh(struct vm_dump_header *);
int vm_instance(struct privsep *, struct vmd_vm **,
@@ -70,7 +71,7 @@ struct vmd *env;
static struct privsep_proc procs[] = {
/* Keep "priv" on top as procs[0] */
- { "priv", PROC_PRIV, NULL, priv },
+ { "priv", PROC_PRIV, vmd_dispatch_priv, priv },
{ "control", PROC_CONTROL, vmd_dispatch_control, control },
{ "vmm", PROC_VMM, vmd_dispatch_vmm, vmm, vmm_shutdown },
};
@@ -551,6 +552,24 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struct imsg *imsg)
}
int
+vmd_dispatch_priv(int fd, struct privsep_proc *p, struct imsg *imsg)
+{
+ struct vmop_addr_result var;
+
+ switch (imsg->hdr.type) {
+ case IMSG_VMDOP_PRIV_GET_ADDR_RESPONSE:
+ IMSG_SIZE_CHECK(imsg, &var);
+ memcpy(&var, imsg->data, sizeof(var));
+ proc_forward_imsg(p->p_ps, imsg, PROC_VMM, -1);
+ break;
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
vmd_check_vmh(struct vm_dump_header *vmh)
{
int i;
diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h
index a2d80eb2181..a9d752a2c2a 100644
--- a/usr.sbin/vmd/vmd.h
+++ b/usr.sbin/vmd/vmd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.h,v 1.102 2021/03/19 09:29:33 kn Exp $ */
+/* $OpenBSD: vmd.h,v 1.103 2021/03/29 23:37:01 dv Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -120,6 +120,8 @@ enum imsg_type {
IMSG_VMDOP_PRIV_IFADDR,
IMSG_VMDOP_PRIV_IFADDR6,
IMSG_VMDOP_PRIV_IFRDOMAIN,
+ IMSG_VMDOP_PRIV_GET_ADDR,
+ IMSG_VMDOP_PRIV_GET_ADDR_RESPONSE,
IMSG_VMDOP_VM_SHUTDOWN,
IMSG_VMDOP_VM_REBOOT,
IMSG_VMDOP_CONFIG,
@@ -158,6 +160,17 @@ struct vmop_ifreq {
struct sockaddr_storage vfr_mask;
};
+struct vmop_addr_req {
+ uint32_t var_vmid;
+ unsigned int var_nic_idx;
+};
+
+struct vmop_addr_result {
+ uint32_t var_vmid;
+ unsigned int var_nic_idx;
+ uint8_t var_addr[ETHER_ADDR_LEN];
+};
+
struct vmop_owner {
uid_t uid;
int64_t gid;
diff --git a/usr.sbin/vmd/vmm.c b/usr.sbin/vmd/vmm.c
index 19964a86f80..faebf670dee 100644
--- a/usr.sbin/vmd/vmm.c
+++ b/usr.sbin/vmd/vmm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmm.c,v 1.97 2021/03/02 02:56:22 jsg Exp $ */
+/* $OpenBSD: vmm.c,v 1.98 2021/03/29 23:37:01 dv Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -109,6 +109,7 @@ vmm_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
struct vmop_id vid;
struct vmop_result vmr;
struct vmop_create_params vmc;
+ struct vmop_addr_result var;
uint32_t id = 0, peerid = imsg->hdr.peerid;
pid_t pid = 0;
unsigned int mode, flags;
@@ -332,6 +333,18 @@ vmm_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
res = ENOENT;
cmd = IMSG_VMDOP_START_VM_RESPONSE;
break;
+ case IMSG_VMDOP_PRIV_GET_ADDR_RESPONSE:
+ IMSG_SIZE_CHECK(imsg, &var);
+ memcpy(&var, imsg->data, sizeof(var));
+ if ((vm = vm_getbyvmid(var.var_vmid)) == NULL) {
+ res = ENOENT;
+ break;
+ }
+ /* Forward hardware address details to the guest vm */
+ imsg_compose_event(&vm->vm_iev,
+ imsg->hdr.type, imsg->hdr.peerid, imsg->hdr.pid,
+ imsg->fd, &var, sizeof(var));
+ break;
default:
return (-1);
}