tech-net archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[Greg Troxel] Re: Getting "write: address family not supported by protocol family" when using Restic over Tailscale
On netbsd-users@ while discussing a tailscale problem in a VM, Bill
Green spotted the bug. I'd appreciate review and concurrence or telling
me why I'm wrong. Message forwarded because I don't think crossposting
is ok.
From: Greg Troxel <gdt%lexort.com@localhost>
To: Bill Green <bwg%supposedly.org@localhost>
Cc: Matti Andreas Kähäri <andreas.kahari%abc.se@localhost>,
netbsd-users%netbsd.org@localhost
Subject: Re: Getting "write: address family not supported by protocol
family" when using Restic over Tailscale
Date: Sun, 18 Oct 2026 19:03:37 -0400
Bill Green <bwg%supposedly.org@localhost> writes:
> I tracked it down at the time to the packet-queuing logic in
> tun_output() (if_tun.c:590) and have been carrying forward a local
> patch that simply deletes the line that sets `error = EAFNOSUPPORT`
> (at if_tun.c:632 in netbsd-11 and current).
>
> According to the notes that I wrote up then, that assignment ended up
> overwriting the actual error that was happening (ENOBUFS, set by the
> IFQ_ENQUEUE macro, which doesn't occur even for AF_INET and AF_INET6
> until after falling through to the AF_UNSPEC case). That is, the
> actual problem was that the output buffer was filling up (which rsync
> etc. should handle), but because the AF_UNSPEC path (again, which the
> AF_INET(6) paths fall through to as well) unconditionally sets
> EAFNOSUPPORT that ends up getting given to userspace in errno instead,
> confusing rsync (and anyone reading the logs).
>
> Indeed patching that line out solved my rsync issue, but I wasn't
> confident that there weren't other potential paths I didn't
> understand: as I recall from looking into the CVS history it's been
> that way for a very long time (20+ years), so it seemed odd for it
> never to have bitten anyone else before.
That's a great analysis. I read the code and I think you're right, but
error paths are tricky.
This was added by pk@ in 2004. The revisions to look at (side by
side, don't try the diff) are 1.69 (before) and 1.70 (after). This was
in general an improvement in locking.
Look at 1.69 L480 and 1.70 543. This is the switch on address family.
There's no v6, but the fallthrough to af_unspec is there.
This is 1.178 L590.
In 1.69, the error from IFQ_ENQUEUE is just returned.
In 1.70, it's overwritten, and then via "goto out;" (a normal BSD
networking style!). However, 0 is returned, not an error.
In 1.178 (current), the error is returned.
I conclude that the setting to EAFNOSUPPORT in 1.70, that has survived,
was a bug, and tat it didn't used to manifest because the error path
returned 0. Basically the packet is dropped, for some reason.
Now, we have error returns from tun_output. It seems that ENOBUFS,
presumably what IFQ_ENQUEUE returns when the queue is at limit, is a
normal response that the upper layer deals with.
I think we should change:
--- if_tun.c.~1.178.~ 2025-11-15 18:30:51.076488670 -0500
+++ if_tun.c 2026-10-18 19:02:22.920287647 -0400
@@ -629,7 +629,6 @@ tun_output(struct ifnet *ifp, struct mbu
IFQ_ENQUEUE(&ifp->if_snd, m0, error);
if (error) {
if_statinc(ifp, if_collisions);
- error = EAFNOSUPPORT;
m0 = NULL;
goto out;
}
and will raise this on tech-net@ for more review.
Home |
Main Index |
Thread Index |
Old Index