if_wg creates IPv4 and IPv6 listening sockets. sobind() will fail for the IPv6 socket when the vnet has no IPv6 addresses assigned to any interface, see the first check in in6_pcbbind(). So if one creates a fresh vnet and instantiates a wg interface there, the link won't come up. As a workaround one can do something like "ifconfig lo0 up", since that automatically assigns ::1. I'm not sure why that check in in6_pcbbind() is needed in the first place.
I forwarded this secondary report to melifaro, but your workaround pointed out an rtentry leak somewhere. Try this:
# jail -c path=/ vnet=new command=ifconfig lo0 up
Freed UMA keg (rtentry) was not empty (1 items). Lost 1 pages of memory.
(In reply to Kyle Evans from comment #1)
He pointed out that it was already fixed and our upstream base just a bit too old; rebased forward and my secondary nit is gone.
I believe this has now been fixed in the latest wireguard-kmod package, and therefore this bug can be closed?
(In reply to Jason A. Donenfeld from comment #3)
I can't quite see how. The problem is basically that in wg_socket_bind(), the sobind() call for the v6 socket will fail if the VNET does not have a v6 address assigned to some interface. Looking at the sources from the latest version of the port, this failure will cause the v4 socket to be closed.
Woof, I see what you mean now. That problem also applies to v4 sockets too! Basically if there's no interface with an address in the family, then bind fails. We could check for ret==EADDRNOTAVAIL and just let things continue in that case, but the fact that this can happen for both v4 and v6 means the user might find themselves in a very confusing state. Returning a failing rc from the ioctl and maybe even warning in dmesg seems more useful. But I also wish there was a more robust solution for this too. Maybe we should go in the direction of allowing sockets to bind to 0.0.0.0 and ::/0 even in the case in which there's not yet an interface with an address in that addr family? That'd certainly make things easier. Thoughts?
(In reply to Jason A. Donenfeld from comment #5)
Indeed, I'm not really sure why we prohibit bind() if no addresses from the corresponding family are assigned. That behaviour appears to predate FreeBSD even. It might be just a matter of removing the corresponding checks. OTOH, it's perfectly valid to disable the use of either v4 or v6 in system (it's even possible to compile corresponding support out of the kernel), and in that case it seems rather odd to require that both sockets bind successfully. Is it possible to have wg_socket_bind() succeed if it's able to bind at least one of the sockets, assuming that sobind() returns EADDRNOTAVAIL for the other?
> Is it possible to have wg_socket_bind() succeed if it's able to bind at least one of the sockets, assuming that sobind() returns EADDRNOTAVAIL for the other?
Nice idea. That seems like a sensible plan and good compromise of conditions. Implemented here: https://git.zx2c4.com/wireguard-freebsd/commit/?id=2b2bd4ef95c2bbbb0da27005278880b4b1c940e0
(In reply to Jason A. Donenfeld from comment #7)
Thanks. I'll test it out and close the bug if all goes well.
Should now be released with https://cgit.freebsd.org/ports/commit/?id=4933972df03262847a7609001138597495cd72d5
Hey Mark -- wondering if the latest port, v0.0.20210428, solves this for you.
(In reply to Jason A. Donenfeld from comment #10)
It does, thanks. In a vnet jail I have:
USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
? ? ? ? udp4 *:1234 *:*