nix
nix copied to clipboard
No longer able to create an unnamed `UnixAddr` as of nix 23.0
It seems that the UnixAddr type no longer provides a way to generate an unnamed unix address (a unix address with an addrlen of 2, or UnixAddrKind::Unnamed). This used to be possible in nix 22.0 when the internal struct fields were public.
Do you mean an abstract socket? What about https://docs.rs/nix/0.23.0/nix/sys/socket/struct.UnixAddr.html#method.new_abstract ?
No, an abstract socket implies that it is bound in the abstract namespace, and has a length >= 3. The new_abstract method always adds at least one empty byte to the address name, so new_abstract(&[]) returns an address with a length of 3. An unnamed unix socket is not bound to any address and should have a length of 2 for the 2 bytes of the u16 address family.
unix(7) can probably explain it better than me:
unnamed: A stream socket that has not been bound to a pathname using bind(2) has no name. Likewise, the two sockets created by socketpair(2) are unnamed. When the address of an unnamed socket is returned, its length is
sizeof(sa_family_t), andsun_pathshould not be inspected.
Ok, I get it. And what do you normally do with unnamed UnixAddrs?
We have code that intercepts syscalls, so we need to work with libc::sockaddr types. Within the internals of our application, it's nice to convert these to nix SockAddr types to work with them, and then convert them back to libc::sockaddr types when needed. For example when we intercept socketpair(), we create a custom socket object within our application and set its socket address to a nix UnixAddr which represents an unnamed unix socket, so that later if we intercept getsockname(), we can convert that UnixAddr to a libc::sockaddr using SockAddr::as_ffi_pair() and return it as the result to getsockname(). Calling getsockname() on an unnamed unix socket should return an addrlen of 2, so if UnixSocket supported unnamed sockets, SockAddr::as_ffi_pair() would return an addrlen of 2 and everything would work seamlessly.
Edit: A simpler example, an unnamed socket address can also be passed to bind() to auto-bind the socket to an abstract address.
For a unix socket:
If a bind(2) call specifies addrlen as
sizeof(sa_family_t), or theSO_PASSCREDsocket option was specified for a socket that was not explicitly bound to an address, then the socket is autobound to an abstract address.
I think maybe this could be implemented with something like:
impl UnixAddr {
pub fn new_unnamed() -> Result<UnixAddr> {
unsafe {
let mut ret = libc::sockaddr_un {
sun_family: AddressFamily::Unix as sa_family_t,
.. mem::zeroed()
};
Ok(UnixAddr::from_raw_parts(ret, 2))
}
}
}
If you're interested in a PR, let me know. But from #1544 it looks like you might be rewriting the SockAddr code anyways.