"pid" is not "process id" in netlink, but rather, "port id". If you bind to a
sockaddr == 0 then Linux automatically assigns your socket a port id - which
happens to be the same as the process ID for the first one concurrently open.
For the second and subsequent concurrently-open sockets, binding 0 (as most
users of this library will do) gets you back a random high-numbered port id.
This change preserves the existing use case (one port open in the process,
binding to 0) while fixing multiple-ports-open-in-the-same-process, socket-is-
passed-in-and-pid-is-not-specified, and specific-pid-is-requested-but-could-
not-bind-to-it.
We're probably still not thread-safe - the seq handling looks dodgy - but at
least now we can use multiple sockets in separate threads and have them all
work.
Using the same socket from multiple threads is a slightly niche use case, and
it's tempting to say "don't do this" instead...
FFI::Struct handles nested structs and nested arrays much better, and avoids
duplicating logic about structure alignment (which it probably does more
correctly that CStruct)
However it's awkward to use in other ways. e.g. no accessor methods;
no proper #inspect; no ntohl for in_addr; no zero-sized arrays at end
of struct; no hooks to convert int32 <-> IPAddr as far as I can see.