Unix Domain Protocols
Introduction
The Unix domain protocols are not an actual protocol suite, but a way of performing client/server communication on a single host using the same API that is used for clients and servers on different hosts. The Unix domain protocols are an alternative to the interprocess communication (IPC) methods described in Volume 2 of this series, when the client and server are on the same host. Details on the actual implementation of Unix domain sockets in a Berkeley-derived kernel are provided in part 3 of TCPv3.
Unix domain sockets are used for three reasons:
1.On Berkeley-derived implementations, Unix domain sockets are often twice as fast as a TCP socket when both peers are on the same host (pp. 223–224 of TCPv3). One application takes advantage of this: the X Window System. When an X11 client starts and opens a connection to the X11 server, the client checks the value of the DISPLAY environment variable, which specifies the server’s hostname, window, and screen. If the server is on the same host as the client, the client opens a Unix domain stream connection to the server; otherwise the client opens a TCP connection to the server.
2.Unix domain sockets are used when passing descriptors between processes on the same host.
3.Newer implementations of Unix domain sockets provide the client’s credentials (user ID and group IDs) to the server, which can provide additional security checking.
Unix Domain Socket Address Structure
Figure 15.1 shows the Unix domain socket address structure, which is defined by including the <sys/un.h> header.
Unix domain socket address structure: sockaddr_un.
struct sockaddr_un {
sa_family_t sun_family; /* AF_LOCAL */
char sun_path[104]; /* null-terminated pathname */
};
The POSIX specification does not define the length of the sun_path array and it specifically warns that applications should not assume a particular length. Use the sizeof operator to find the length at run-time and to verify that a pathname fits into the array. The length is likely to be between 92 and 108 rather than a larger value big enough to hold any pathname. The reason for these limits is an implementation artifact dating back to 4.2BSD requiring that this structure fit in a 128-byte mbuf (a kernel memory buffer).
POSIX renames the Unix domain protocols as “local IPC,” to remove the dependence on the Unix OS. The historical constant AF_UNIX becomes AF_LOCAL. Nevertheless, we still use the term “Unix domain” as that has become its de facto name, regardless of the underlying OS. Also, even with POSIX attempting to make these OS-independent, the socket address structure still retains the _un suffix!
#include "unp.h"
int main(int argc, char **argv)
{
int sockfd;
socklen_t len;
struct sockaddr_un addr1,addr2;
if(argc!=2)
err_quit("usage: unixbind <pathname>");
sockfd=Sockete(AF_LOCAL, SOCK_STREAM, 0);
unlink(argv[1]);
bzero(&addr1, sizeof(addr1));
addr1.sun_family=AF_LOCAL;
strncpy(addr1.sun_path, argv[1], sizeof(addr1.sun_path)-1);
Bind(sockfd, (SA *)&addr1, SUN_LEN(&addr1));
len=sizeof(addr2);
Getsockname(sockfd, (SA *)&addr2, &len);
printf("bound name=%s, returned len=%d\n",addr2.sun_path,len);
return 0;
}
bind of a pathname to a Unix domain socket