Closed
Description
The SockaddrStorage
type "forgets" the address length, which causes incorrect and unexpected behaviour. I think this is a more fundamental issue with how nix represents socket addresses.
Example:
use std::os::unix::io::AsRawFd;
use std::os::unix::net::UnixListener;
use nix::sys::socket::{connect, getsockname, socket};
use nix::sys::socket::{AddressFamily, SockFlag, SockType, SockaddrStorage};
let listener = UnixListener::bind("/tmp/example.sock").unwrap();
let listener_fd = listener.as_raw_fd();
let listener_addr: SockaddrStorage = getsockname(listener_fd).unwrap();
let peer_fd = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None).unwrap();
// this panics
connect(peer_fd, &listener_addr).unwrap();
If we look at the strace, we can see that nix is proving the wrong sockaddr length to connect()
, which represents an incorrect address. This is equally important for abstract named and unnamed unix sockets.
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0) = 3
bind(3, {sa_family=AF_UNIX, sun_path="/tmp/example.sock"}, 20) = 0
listen(3, 4294967295) = 0
getsockname(3, {sa_family=AF_UNIX, sun_path="/tmp/example.sock"}, [128->20]) = 0
write(1, "SockaddrStorage { ss: sockaddr_s"..., 91SockaddrStorage { ss: sockaddr_storage { ss_family: 1, __ss_align: 8299682679707492728 } }
) = 91
socket(AF_UNIX, SOCK_STREAM, 0) = 4
connect(4, {sa_family=AF_UNIX, sun_path="/tmp/example.sock"}, 128) = -1 EINVAL (Invalid argument)
When you're writing code that has to support many different socket address types, this means that SockaddrStorage
is unusable. We're currently sticking with the deprecated nix::sys::socket::SockAddr
for now as it doesn't have this issue.