The most distinct feature of Unix Domain protocols is that they use a filesystem path as an address, rather than an IP address and port number.
To handle this, we use a specific socket address structure called sockaddr_un.
1. The Unix Domain Socket Address Structure
Just as TCP/IP uses sockaddr_in, Unix Domain protocols use sockaddr_un. It is defined in the <sys/un.h> header.
struct sockaddr_un {
sa_family_t sun_family; /* AF_LOCAL */
char sun_path[104]; /* null-terminated pathname */
};Key Characteristics:
- sun_family: This is always set to
AF_LOCAL(historicallyAF_UNIX).
- sun_path: This array holds the pathname (e.g.,
/tmp/mysocket).- Length Warning: The POSIX specification does not define the exact size of this array. While the text example shows 104 bytes, it warns not to assume a specific length. It is usually between 92 and 108 bytes.
- Null-Termination: The pathname stored here must be null-terminated.
The SUN_LEN Macro:
Because the path length varies, we don’t just pass sizeof(struct sockaddr_un) to the bind function. Instead, a special macro is provided.
SUN_LEN(ptr) calculates the actual length of the structure based on the string length of the path currently stored in it.
2. Example: Binding a Unix Domain Socket (Figure 15.2)
The text provides a small program called unixbind to demonstrate how to associate a socket with a filepath. Here is the logic broken down:
Step 1: Create the Socket
sockfd = Socket(AF_LOCAL, SOCK_STREAM, 0);We use AF_LOCAL for the domain and SOCK_STREAM for the type (though SOCK_DGRAM works similarly here).
Step 2: Clean Up Previous Files
unlink(argv[1]);Why do we do this? Unlike a TCP port, which “disappears” when the server stops, a Unix domain socket persists in the filesystem as a file. If you try to bind to a path that already exists, the call will fail. Therefore, servers usually try to unlink (delete) the file before binding, just in case a previous instance crashed and left the file behind.
The most common mistake beginners make here is forgetting to unlink the socket file before restarting their server, causing “Address already in use” errors.
Step 3: Initialize and Bind
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));We copy the path into the structure and bind it. Note the use of SUN_LEN to tell the kernel exactly how long our address structure is.
Step 4: Verify with getsockname The example calls getsockname immediately after binding to confirm the system has accepted the address.
3. File Permissions and Persistence
If you run this program (e.g., unixbind /tmp/moose), you can actually verify the socket exists using standard shell commands:
% ls -lF /tmp/moose
srwxr-xr-x 1 user staff 0 Aug 10 13:13 /tmp/moose=- The
sat the start of the permissions string indicates the file type is a socket. - The
=at the end is how some systems (like Solaris) visually tag sockets inls -Foutput.
Note
The socket follows standard Unix file permissions (controlled by
umask). This is a security feature: you can restrict which users on the system can connect to your server by changing the file read/write permissions of the socket file.