I'm implementing a simple service using datagrams over unix local sockets (AF_UNIX address family, i.e. not UDP). The server is bound to a public address, and it receives requests just fine. Unfortunately, when it comes to answering back, sendto
fails unless the client is bound too. (the common error is Transport endpoint is not connected
).
Binding to some random name (filesystem-based or abstract) works. But I'd like to avoid that: who am I to guarantee the names I picked won't collide?
The unix sockets' stream mode documentation tell us that an abstract name will be assigned to them at connect
time if they don't have one already. Is such a feature available for datagram oriented sockets?
The AF_UNIX (also known as AF_LOCAL) socket family is used to communicate between processes on the same machine efficiently. Traditionally, UNIX domain sockets can be either unnamed, or bound to a filesystem pathname (marked as being of type socket).
The difference is that an INET socket is bound to an IP address-port tuple, while a UNIX socket is "bound" to a special file on your filesystem. Generally, only processes running on the same machine can communicate through the latter.
They are to be stored in /run/ according to the Filesystem Hierarchy Standard (FHS).
Unix sockets are bidirectional. This means that every side can perform both read and write operations. While, FIFOs are unidirectional: it has a writer peer and a reader peer. Unix sockets create less overhead and communication is faster, than by localhost IP sockets.
The unix(7) man page I referenced had this information about autobind UNIX sockets:
If a bind(2) call specifies addrlen as sizeof(sa_family_t), or the SO_PASSCRED socket option was specified for a socket that was not explicitly bound to an address, then the socket is autobound to an abstract address.
This is why the Linux kernel checks the address length is equal to sizeof(short) because sa_family_t is a short. The other unix(7) man page referenced by Rob's great answer says that client sockets are always autobound on connect, but because SOCK_DGRAM sockets are connectionless (despite calling connect on them) I believe this only applies to SOCK_STREAM sockets.
Also note that when supplying your own abstract namespace socket names, the socket's address in this namespace is given by the additional bytes in sun_path that are covered by the specified length of the address structure.
struct sockaddr_un me;
const char name[] = "\0myabstractsocket";
me.sun_family = AF_UNIX;
// size-1 because abstract socket names are not null terminated
memcpy(me.sun_path, name, sizeof(name) - 1);
int result = bind(fd, (void*)&me, sizeof(me.sun_family) + sizeof(name) - 1);
sendto() should likewise limit the address length, and not pass sizeof(sockaddr_un).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With