[ Team LiB ] |
15.2 Unix Domain Socket Address StructureFigure 15.1 shows the Unix domain socket address structure, which is defined by including the <sys/un.h> header. Figure 15.1 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 pathname stored in the sun_path array must be null-terminated. The macro SUN_LEN is provided and it takes a pointer to a sockaddr_un structure and returns the length of the structure, including the number of non-null bytes in the pathname. The unspecified address is indicated by a null string as the pathname, that is, a structure with sun_path[0] equal to 0. This is the Unix domain equivalent of the IPv4 INADDR_ANY constant and the IPv6 IN6ADDR_ANY_INIT constant.
Example: bind of Unix Domain SocketThe program in Figure 15.2 creates a Unix domain socket, binds a pathname to it, and then calls getsockname and prints the bound pathname. Figure 15.2 bind of a pathname to a Unix domain socket.unixdomain/unixbind.c 1 #include "unp.h" 2 int 3 main(int argc, char **argv) 4 { 5 int sockfd; 6 socklen_t len; 7 struct sockaddr_un addr1, addr2; 8 if (argc != 2) 9 err_quit("usage: unixbind <pathname>"); 10 sockfd = Socket(AF_LOCAL, SOCK_STREAM, 0); 11 unlink(argv[1]); /* OK if this fails */ 12 bzero(&addr1, sizeof(addr1)); 13 addr1.sun_family = AF_LOCAL; 14 strncpy(addr1.sun_path, argv[1], sizeof(addr1.sun_path) - 1); 15 Bind(sockfd, (SA *) &addr1, SUN_LEN(&addr1)); 16 len = sizeof(addr2); 17 Getsockname(sockfd, (SA *) &addr2, &len); 18 printf("bound name = %s, returned len = %d\n", addr2.sun_path, len); 19 exit(0); 20 } Remove pathname first11 The pathname that we bind to the socket is the command-line argument. But the bind will fail if the pathname already exists in the filesystem. Therefore, we call unlink to delete the pathname, in case it already exists. If it does not exist, unlink returns an error, which we ignore. bind and then getsockname12–18 We copy the command-line argument using strncpy, to avoid overflowing the structure if the pathname is too long. Since we initialize the structure to zero and then subtract one from the size of the sun_path array, we know the pathname is null-terminated. bind is called and we use the macro SUN_LEN to calculate the length argument for the function. We then call getsockname to fetch the name that was just bound and print the result. If we run this program under Solaris, we obtain the following results: solaris % umask first print our umask value 022 shells print this value in octal solaris % unixbind /tmp/moose bound name = /tmp/moose, returned len = 13 solaris % unixbind /tmp/moose run it again bound name = /tmp/moose, returned len = 13 solaris % ls -l /tmp/moose srwxr-xr-x 1 andy staff 0 Aug 10 13:13 /tmp/moose solaris %unixbind /tmp/moose srwxr-xr-x 1 andy staff 0 Aug 10 13:13 /tmp/moose We first print our umask value because POSIX specifies that the file access permissions of the resulting pathname should be modified by this value. Our value of 22 turns off the group-write and other-write bits. We then run the program and see that the length returned by getsockname is 13: 2 bytes for the sun_family member and 11 bytes for the actual pathname (excluding the terminating null byte). This is an example of a value-result argument whose result when the function returns differs from its value when the function was called. We can output the pathname using the %s format of printf because the pathname is null-terminated in the sun_path member. We then run the program again, to verify that calling unlink removes the pathname. We run ls -l to see the file permissions and file type. Under Solaris (and most Unix variants), the file type is a socket, which is printed as s. We also notice that the permission bits were modified as appropriate by the umask value. Finally, we run ls again, with the -F option, which causes Solaris to append an equals sign to the pathname.
|
[ Team LiB ] |