diff --git a/docs/gotchas.md b/docs/gotchas.md index c50421be..4c106d3d 100644 --- a/docs/gotchas.md +++ b/docs/gotchas.md @@ -72,6 +72,32 @@ the path entry resolves to `/run/wrappers/bin/bin` instead. hive-c0re restarts. Without it, every restart wipes bind sources and existing containers can't be started. +### `RestrictAddressFamilies` fails as "Address family not supported by protocol" + +A unit whose `RestrictAddressFamilies` omits a family gets `EAFNOSUPPORT` +(errno 97) back from `socket()`. Clients surface that as *"tcp open error: +Address family not supported by protocol"* — the message names the +**protocol** and never the **sandbox**, so it reads like a dead network, a +missing route, or an IPv6 problem. + +⇒ On that error, read the unit before you touch the network. + +Two things to get right when a daemon needs outbound TCP: + +- list `AF_INET` **and** `AF_INET6` — omitting one leaves a client that + works until DNS hands back the other family; +- list `AF_NETLINK` too. glibc's `getaddrinfo` opens a netlink socket to + enumerate local addresses before it returns any, so name resolution + fails without it even when `AF_INET` is allowed. + +**The directive is a claim about what the program does, and nothing +re-checks it when the program changes.** A unit that only served a unix +socket when it was written is correct at `[ "AF_UNIX" ]` and silently wrong +the day someone adds an HTTP client. Check the unit in the same commit as +the client — and when narrowing it, prefer a test that derives the required +families from the code (which fails on the *next* client too) over one that +asserts today's list. + ### `register_agent` is idempotent Drops any prior socket task before rebinding. Required so a