Re: vmd(8): fix packet handling for dhcpleased(8)

2021-03-29 Thread Dave Voutila


Dave Voutila writes:

> Dave Voutila writes:
>
>> tech@,
>>
>> While migrating an existing -current vm to use dhcpleased(8), one of the
>> issues discovered was the dhcp/bootp handling built into vmd(8) for
>> local interfaces was improperly missing packets sent to the ethernet
>> address of the host-side tap(4) device. (vmd(8) was only looking for
>> broadcast packets.)
>>
>> The following diff:
>> - includes the host-side tap(4) lladdr in the packet filtering logic for
>>   intercepting vio(4) dhcp/bootp communication
>> - removes a conditional check (dhcpsz == 0) pointed out by deraadt@ that
>>   could contribute to missed packets while iterating through the vionet
>>   tx ring
>
> The conditional check (dhcpsz == 0) was committed. The diff below is
> updated to apply to the latest copy of the src tree.
>
>>
>> Because of vmd(8)'s priv-sep design, the approach taken is to pass a
>> duplicate of the opened tap(4) fd to the "priv" process that is
>> unpledged and responsible for setting up networking. A response imsg
>> travels between processes, being forwarded until it gets to the intended
>> vm process.
>>
>> For those looking to test the diff, some steps to follow are:
>>
>> 0. Don't apply the patch yet.
>> 1. Use an OpenBSD guest running a recent snapshot that has the latest
>> dhcpleased(8)[1] and dhcpleasectl(8)[2] changes committed by florian@.
>> 2. Configure the guest for using dhcpleased(8), ideally via
>> /etc/hostname.vio0 containing:
>>
>>   inet autoconf
>>   up
>>
>> 3. Ensure you get an IP assigned from vmd(8) after boot.
>> 4. Check the lease with `dhcpleasectl show interface vio0`. It should
>>report [Bound] and have a _very_ long lease time.
>> 5. Force a renewal with `dhcpleasectl send request vio0`.
>> 6. Check again like in step 4. It will be "stuck" in a [Renewing] state.
>> 7. Shut down the guest, vmd(8), and apply the patch.
>> 8. Repeat steps 4-6, but the guest should no longer be "stuck" in
>>[Renewing] and should report [Bound] after forced renewal.
>>
>> You can also turn up debug logging for vmd(8) and should see
>> corresponding messages of:
>>
>>   vionet: dhcp request, local response size 342
>>
>> If you do not, the packet was not intercepted by vmd(8).
>>
>> I have tested this diff with a variety of conditions, including multiple
>> emulated nics per guest. Specifically 1 nic using dhcp/bootp resolved by
>> vmd(8) and the other nic connected to a virtual switch using veb(4) and
>> an instance of dhcpd(8) running on the host. Also ran a snapshot upgrade
>> with no issues.
>
> I haven't received any issue reports as of yet.
>

No issue reports. mlarkin@ asked for a change the function signature of
vionet_set_hostmac (change array to pointer).

OK?

>>
>> [1] https://marc.info/?l=openbsd-cvs=161643049815177=2
>> [2] https://marc.info/?l=openbsd-cvs=161652157122736=2
>>


Index: usr.sbin/vmd/config.c
===
RCS file: /cvs/src/usr.sbin/vmd/config.c,v
retrieving revision 1.60
diff -u -p -r1.60 config.c
--- usr.sbin/vmd/config.c   19 Mar 2021 09:29:33 -  1.60
+++ usr.sbin/vmd/config.c   29 Mar 2021 21:19:09 -
@@ -227,6 +227,7 @@ config_setvm(struct privsep *ps, struct
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
proc_compose_imsg(ps, PROC_VMM, -1,
IMSG_VMDOP_START_VM_IF, vm->vm_vmid, tapfds[i],
, sizeof(i));
+
+   memset(, 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]), , sizeof(var));
}

if (!(vm->vm_state & VM_STATE_RECEIVED))
Index: usr.sbin/vmd/dhcp.c
===
RCS file: /cvs/src/usr.sbin/vmd/dhcp.c,v
retrieving revision 1.8
diff -u -p -r1.8 dhcp.c
--- usr.sbin/vmd/dhcp.c 27 Dec 2018 19:51:30 -  1.8
+++ usr.sbin/vmd/dhcp.c 29 Mar 2021 21:19:09 -
@@ -57,8 +57,11 @@ dhcp_request(struct vionet_dev *dev, cha
if ((offset = decode_hw_header(buf, buflen, 0, , 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, )) < 0)
Index: usr.sbin/vmd/priv.c

Re: vmd(8): fix packet handling for dhcpleased(8)

2021-03-26 Thread Dave Voutila


Dave Voutila writes:

> tech@,
>
> While migrating an existing -current vm to use dhcpleased(8), one of the
> issues discovered was the dhcp/bootp handling built into vmd(8) for
> local interfaces was improperly missing packets sent to the ethernet
> address of the host-side tap(4) device. (vmd(8) was only looking for
> broadcast packets.)
>
> The following diff:
> - includes the host-side tap(4) lladdr in the packet filtering logic for
>   intercepting vio(4) dhcp/bootp communication
> - removes a conditional check (dhcpsz == 0) pointed out by deraadt@ that
>   could contribute to missed packets while iterating through the vionet
>   tx ring

The dhcpsz check was committed. The diff below is updated to apply
cleanly to the tree.

On second review, I found I have an off-by-one error in a size
check. Low chance of being an issue but it's now corrected.

>
> Because of vmd(8)'s priv-sep design, the approach taken is to pass a
> duplicate of the opened tap(4) fd to the "priv" process that is
> unpledged and responsible for setting up networking. A response imsg
> travels between processes, being forwarded until it gets to the intended
> vm process.
>
> For those looking to test the diff, some steps to follow are:
>
> 0. Don't apply the patch yet.
> 1. Use an OpenBSD guest running a recent snapshot that has the latest
> dhcpleased(8)[1] and dhcpleasectl(8)[2] changes committed by florian@.
> 2. Configure the guest for using dhcpleased(8), ideally via
> /etc/hostname.vio0 containing:
>
>   inet autoconf
>   up
>
> 3. Ensure you get an IP assigned from vmd(8) after boot.
> 4. Check the lease with `dhcpleasectl show interface vio0`. It should
>report [Bound] and have a _very_ long lease time.
> 5. Force a renewal with `dhcpleasectl send request vio0`.
> 6. Check again like in step 4. It will be "stuck" in a [Renewing] state.
> 7. Shut down the guest, vmd(8), and apply the patch.
> 8. Repeat steps 4-6, but the guest should no longer be "stuck" in
>[Renewing] and should report [Bound] after forced renewal.
>
> You can also turn up debug logging for vmd(8) and should see
> corresponding messages of:
>
>   vionet: dhcp request, local response size 342
>
> If you do not, the packet was not intercepted by vmd(8).
>
> I have tested this diff with a variety of conditions, including multiple
> emulated nics per guest. Specifically 1 nic using dhcp/bootp resolved by
> vmd(8) and the other nic connected to a virtual switch using veb(4) and
> an instance of dhcpd(8) running on the host. Also ran a snapshot upgrade
> with no issues.
>

I haven't received any issue reports. I think it's fair to give another
few days/the weekend for vmd users to validate there are no
regressions.

> So in summary, if this diff works, you shouldn't notice a difference ;-)
>
> Thanks,
> -Dave
>
> [1] https://marc.info/?l=openbsd-cvs=161643049815177=2
> [2] https://marc.info/?l=openbsd-cvs=161652157122736=2
>


Index: config.c
===
RCS file: /cvs/src/usr.sbin/vmd/config.c,v
retrieving revision 1.60
diff -u -p -r1.60 config.c
--- config.c19 Mar 2021 09:29:33 -  1.60
+++ config.c26 Mar 2021 20:23:24 -
@@ -227,6 +227,7 @@ config_setvm(struct privsep *ps, struct
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
proc_compose_imsg(ps, PROC_VMM, -1,
IMSG_VMDOP_START_VM_IF, vm->vm_vmid, tapfds[i],
, sizeof(i));
+
+   memset(, 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]), , sizeof(var));
}

if (!(vm->vm_state & VM_STATE_RECEIVED))
Index: dhcp.c
===
RCS file: /cvs/src/usr.sbin/vmd/dhcp.c,v
retrieving revision 1.8
diff -u -p -r1.8 dhcp.c
--- dhcp.c  27 Dec 2018 19:51:30 -  1.8
+++ dhcp.c  26 Mar 2021 20:23:24 -
@@ -57,8 +57,11 @@ dhcp_request(struct vionet_dev *dev, cha
if ((offset = decode_hw_header(buf, buflen, 0, , 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, )) < 0)
Index: priv.c
===
RCS file: 

Re: vmd(8): fix packet handling for dhcpleased(8)

2021-03-26 Thread Florian Obser
On Thu, Mar 25, 2021 at 04:36:04PM -0400, Dave Voutila wrote:
> 
> Florian Obser writes:
> > Our lease is however still valid, so everything "just works".
> >
> > Maybe the problem is with the send request command. I don't know yet
> > what to do with it. Maybe it should transition to INIT state. This is
> > what dhclient(8) is doing when one re-starts it on an interface.
> >
> > So vmd(8) is not behaving correctly as dhcp server. I don't know if
> > this needs fixing though if it's too complicated.
> 
> I don't feel the change is complicated. It's mostly reyk-ian privsep
> plumbing. I know the built-in dhcp feature of vmd(8) is heavily used so
> I'm concerned that it behave close to whatever is expected of a dhcp
> server to minimize guest software reporting problems.

That is a very valid reason. I guess I wanted to say, don't bend over
backwards just because of dhcpleased.

-- 
I'm not entirely sure you are real.



Re: vmd(8): fix packet handling for dhcpleased(8)

2021-03-25 Thread Dave Voutila


Florian Obser writes:

> This might not be a problem in practice.

Agreed specifically on the renewal issue.

The subtle 1 line change to process all packets in the tx ring is a
different issue that so far nobody has reported observing.

>
> vmd(8) hands us a lease with "infinity" lease time. This is expresed
> as UINT32_MAX, i.e. 2^32-1. dhcpleased(8) does not handle infinity
> explicitly, it's just a very long lease time (136 years).
>
> When we configure the lease we enter the BOUND state. After 0.5 *
> lease time (T1) we transition to RENEWING:
>
> RFC 2131, 4.3.2 DHCPREQUEST message:
>
>o DHCPREQUEST generated during RENEWING state:
>
>   'server identifier' MUST NOT be filled in, 'requested IP address'
>   option MUST NOT be filled in, 'ciaddr' MUST be filled in with
>   client's IP address. In this situation, the client is completely
>   configured, and is trying to extend its lease. *This message will
>   be unicast*, so no relay agents will be involved in its
>   transmission.  Because 'giaddr' is therefore not filled in, the
>   DHCP server will trust the value in 'ciaddr', and use it when
>   replying to the client.
>

I'll have to go through the "poor-man's dhcp server" in vmd(8) and check
against the RFC to see if it's doing any other oddities. There's at
least one superflous thing I can see for another diff.

> This is the only state where we send unicast messages.
>
> After 0.875 * lease_time (T2) we transition to REBINDING which is
> again broadcast.
>
> Now these are very long timeouts. In particular we transition to
> RENEWING after 68 years...
>
> One can trigger a transition from BOUND to renewing via
> dhcpleasectl(8)'s send request command. It will basically do the next
> state transition, in this case to RENEWING and will be stuck there
> because vmd will ignore out request.
>
> Our lease is however still valid, so everything "just works".
>
> Maybe the problem is with the send request command. I don't know yet
> what to do with it. Maybe it should transition to INIT state. This is
> what dhclient(8) is doing when one re-starts it on an interface.
>
> So vmd(8) is not behaving correctly as dhcp server. I don't know if
> this needs fixing though if it's too complicated.

I don't feel the change is complicated. It's mostly reyk-ian privsep
plumbing. I know the built-in dhcp feature of vmd(8) is heavily used so
I'm concerned that it behave close to whatever is expected of a dhcp
server to minimize guest software reporting problems.

>
> On Wed, Mar 24, 2021 at 05:47:36PM -0400, Dave Voutila wrote:
>> tech@,
>>
>> While migrating an existing -current vm to use dhcpleased(8), one of the
>> issues discovered was the dhcp/bootp handling built into vmd(8) for
>> local interfaces was improperly missing packets sent to the ethernet
>> address of the host-side tap(4) device. (vmd(8) was only looking for
>> broadcast packets.)
>>
>> The following diff:
>> - includes the host-side tap(4) lladdr in the packet filtering logic for
>>   intercepting vio(4) dhcp/bootp communication
>> - removes a conditional check (dhcpsz == 0) pointed out by deraadt@ that
>>   could contribute to missed packets while iterating through the vionet
>>   tx ring
>>
>> Because of vmd(8)'s priv-sep design, the approach taken is to pass a
>> duplicate of the opened tap(4) fd to the "priv" process that is
>> unpledged and responsible for setting up networking. A response imsg
>> travels between processes, being forwarded until it gets to the intended
>> vm process.
>>
>> For those looking to test the diff, some steps to follow are:
>>
>> 0. Don't apply the patch yet.
>> 1. Use an OpenBSD guest running a recent snapshot that has the latest
>> dhcpleased(8)[1] and dhcpleasectl(8)[2] changes committed by florian@.
>> 2. Configure the guest for using dhcpleased(8), ideally via
>> /etc/hostname.vio0 containing:
>>
>>   inet autoconf
>>   up
>>
>> 3. Ensure you get an IP assigned from vmd(8) after boot.
>> 4. Check the lease with `dhcpleasectl show interface vio0`. It should
>>report [Bound] and have a _very_ long lease time.
>> 5. Force a renewal with `dhcpleasectl send request vio0`.
>> 6. Check again like in step 4. It will be "stuck" in a [Renewing] state.
>> 7. Shut down the guest, vmd(8), and apply the patch.
>> 8. Repeat steps 4-6, but the guest should no longer be "stuck" in
>>[Renewing] and should report [Bound] after forced renewal.
>>
>> You can also turn up debug logging for vmd(8) and should see
>> corresponding messages of:
>>
>>   vionet: dhcp request, local response size 342
>>
>> If you do not, the packet was not intercepted by vmd(8).
>>
>> I have tested this diff with a variety of conditions, including multiple
>> emulated nics per guest. Specifically 1 nic using dhcp/bootp resolved by
>> vmd(8) and the other nic connected to a virtual switch using veb(4) and
>> an instance of dhcpd(8) running on the host. Also ran a snapshot upgrade
>> with no issues.
>>
>> So in 

Re: vmd(8): fix packet handling for dhcpleased(8)

2021-03-25 Thread Florian Obser
This might not be a problem in practice.

vmd(8) hands us a lease with "infinity" lease time. This is expresed
as UINT32_MAX, i.e. 2^32-1. dhcpleased(8) does not handle infinity
explicitly, it's just a very long lease time (136 years).

When we configure the lease we enter the BOUND state. After 0.5 *
lease time (T1) we transition to RENEWING:

RFC 2131, 4.3.2 DHCPREQUEST message:

   o DHCPREQUEST generated during RENEWING state:

  'server identifier' MUST NOT be filled in, 'requested IP address'
  option MUST NOT be filled in, 'ciaddr' MUST be filled in with
  client's IP address. In this situation, the client is completely
  configured, and is trying to extend its lease. *This message will
  be unicast*, so no relay agents will be involved in its
  transmission.  Because 'giaddr' is therefore not filled in, the
  DHCP server will trust the value in 'ciaddr', and use it when
  replying to the client.

This is the only state where we send unicast messages.

After 0.875 * lease_time (T2) we transition to REBINDING which is
again broadcast.

Now these are very long timeouts. In particular we transition to
RENEWING after 68 years...

One can trigger a transition from BOUND to renewing via
dhcpleasectl(8)'s send request command. It will basically do the next
state transition, in this case to RENEWING and will be stuck there
because vmd will ignore out request.

Our lease is however still valid, so everything "just works".

Maybe the problem is with the send request command. I don't know yet
what to do with it. Maybe it should transition to INIT state. This is
what dhclient(8) is doing when one re-starts it on an interface.

So vmd(8) is not behaving correctly as dhcp server. I don't know if
this needs fixing though if it's too complicated.

On Wed, Mar 24, 2021 at 05:47:36PM -0400, Dave Voutila wrote:
> tech@,
> 
> While migrating an existing -current vm to use dhcpleased(8), one of the
> issues discovered was the dhcp/bootp handling built into vmd(8) for
> local interfaces was improperly missing packets sent to the ethernet
> address of the host-side tap(4) device. (vmd(8) was only looking for
> broadcast packets.)
> 
> The following diff:
> - includes the host-side tap(4) lladdr in the packet filtering logic for
>   intercepting vio(4) dhcp/bootp communication
> - removes a conditional check (dhcpsz == 0) pointed out by deraadt@ that
>   could contribute to missed packets while iterating through the vionet
>   tx ring
> 
> Because of vmd(8)'s priv-sep design, the approach taken is to pass a
> duplicate of the opened tap(4) fd to the "priv" process that is
> unpledged and responsible for setting up networking. A response imsg
> travels between processes, being forwarded until it gets to the intended
> vm process.
> 
> For those looking to test the diff, some steps to follow are:
> 
> 0. Don't apply the patch yet.
> 1. Use an OpenBSD guest running a recent snapshot that has the latest
> dhcpleased(8)[1] and dhcpleasectl(8)[2] changes committed by florian@.
> 2. Configure the guest for using dhcpleased(8), ideally via
> /etc/hostname.vio0 containing:
> 
>   inet autoconf
>   up
> 
> 3. Ensure you get an IP assigned from vmd(8) after boot.
> 4. Check the lease with `dhcpleasectl show interface vio0`. It should
>report [Bound] and have a _very_ long lease time.
> 5. Force a renewal with `dhcpleasectl send request vio0`.
> 6. Check again like in step 4. It will be "stuck" in a [Renewing] state.
> 7. Shut down the guest, vmd(8), and apply the patch.
> 8. Repeat steps 4-6, but the guest should no longer be "stuck" in
>[Renewing] and should report [Bound] after forced renewal.
> 
> You can also turn up debug logging for vmd(8) and should see
> corresponding messages of:
> 
>   vionet: dhcp request, local response size 342
> 
> If you do not, the packet was not intercepted by vmd(8).
> 
> I have tested this diff with a variety of conditions, including multiple
> emulated nics per guest. Specifically 1 nic using dhcp/bootp resolved by
> vmd(8) and the other nic connected to a virtual switch using veb(4) and
> an instance of dhcpd(8) running on the host. Also ran a snapshot upgrade
> with no issues.
> 
> So in summary, if this diff works, you shouldn't notice a difference ;-)
> 
> Thanks,
> -Dave
> 
> [1] https://marc.info/?l=openbsd-cvs=161643049815177=2
> [2] https://marc.info/?l=openbsd-cvs=161652157122736=2
> 
> 
> Index: config.c
> ===
> RCS file: /cvs/src/usr.sbin/vmd/config.c,v
> retrieving revision 1.60
> diff -u -p -r1.60 config.c
> --- config.c  19 Mar 2021 09:29:33 -  1.60
> +++ config.c  24 Mar 2021 15:42:13 -
> @@ -227,6 +227,7 @@ config_setvm(struct privsep *ps, struct
>   char base[PATH_MAX];
>   unsigned int unit;
>   struct timeval   tv, rate, since_last;
> + struct vmop_addr_req var;
> 
>   errno = 0;
> 
> @@ -499,6 

vmd(8): fix packet handling for dhcpleased(8)

2021-03-24 Thread Dave Voutila
tech@,

While migrating an existing -current vm to use dhcpleased(8), one of the
issues discovered was the dhcp/bootp handling built into vmd(8) for
local interfaces was improperly missing packets sent to the ethernet
address of the host-side tap(4) device. (vmd(8) was only looking for
broadcast packets.)

The following diff:
- includes the host-side tap(4) lladdr in the packet filtering logic for
  intercepting vio(4) dhcp/bootp communication
- removes a conditional check (dhcpsz == 0) pointed out by deraadt@ that
  could contribute to missed packets while iterating through the vionet
  tx ring

Because of vmd(8)'s priv-sep design, the approach taken is to pass a
duplicate of the opened tap(4) fd to the "priv" process that is
unpledged and responsible for setting up networking. A response imsg
travels between processes, being forwarded until it gets to the intended
vm process.

For those looking to test the diff, some steps to follow are:

0. Don't apply the patch yet.
1. Use an OpenBSD guest running a recent snapshot that has the latest
dhcpleased(8)[1] and dhcpleasectl(8)[2] changes committed by florian@.
2. Configure the guest for using dhcpleased(8), ideally via
/etc/hostname.vio0 containing:

  inet autoconf
  up

3. Ensure you get an IP assigned from vmd(8) after boot.
4. Check the lease with `dhcpleasectl show interface vio0`. It should
   report [Bound] and have a _very_ long lease time.
5. Force a renewal with `dhcpleasectl send request vio0`.
6. Check again like in step 4. It will be "stuck" in a [Renewing] state.
7. Shut down the guest, vmd(8), and apply the patch.
8. Repeat steps 4-6, but the guest should no longer be "stuck" in
   [Renewing] and should report [Bound] after forced renewal.

You can also turn up debug logging for vmd(8) and should see
corresponding messages of:

  vionet: dhcp request, local response size 342

If you do not, the packet was not intercepted by vmd(8).

I have tested this diff with a variety of conditions, including multiple
emulated nics per guest. Specifically 1 nic using dhcp/bootp resolved by
vmd(8) and the other nic connected to a virtual switch using veb(4) and
an instance of dhcpd(8) running on the host. Also ran a snapshot upgrade
with no issues.

So in summary, if this diff works, you shouldn't notice a difference ;-)

Thanks,
-Dave

[1] https://marc.info/?l=openbsd-cvs=161643049815177=2
[2] https://marc.info/?l=openbsd-cvs=161652157122736=2


Index: config.c
===
RCS file: /cvs/src/usr.sbin/vmd/config.c,v
retrieving revision 1.60
diff -u -p -r1.60 config.c
--- config.c19 Mar 2021 09:29:33 -  1.60
+++ config.c24 Mar 2021 15:42:13 -
@@ -227,6 +227,7 @@ config_setvm(struct privsep *ps, struct
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
proc_compose_imsg(ps, PROC_VMM, -1,
IMSG_VMDOP_START_VM_IF, vm->vm_vmid, tapfds[i],
, sizeof(i));
+
+   memset(, 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]), , sizeof(var));
}

if (!(vm->vm_state & VM_STATE_RECEIVED))
Index: dhcp.c
===
RCS file: /cvs/src/usr.sbin/vmd/dhcp.c,v
retrieving revision 1.8
diff -u -p -r1.8 dhcp.c
--- dhcp.c  27 Dec 2018 19:51:30 -  1.8
+++ dhcp.c  24 Mar 2021 15:42:13 -
@@ -57,8 +57,11 @@ dhcp_request(struct vionet_dev *dev, cha
if ((offset = decode_hw_header(buf, buflen, 0, , 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, )) < 0)
Index: priv.c
===
RCS file: /cvs/src/usr.sbin/vmd/priv.c,v
retrieving revision 1.16
diff -u -p -r1.16 priv.c
--- priv.c  28 Feb 2021 22:56:09 -  1.16
+++ priv.c  24 Mar 2021 15:42:14 -
@@ -92,6 +92,8 @@ priv_dispatch_parent(int fd, struct priv
struct ifaliasreqifra;
struct in6_aliasreq  in6_ifra;
struct if_afreq  ifar;
+   struct vmop_addr_req vareq;
+   struct vmop_addr_result  varesult;
char type[IF_NAMESIZE];