Unix Domain Protocols • Unix domain socket address structure • Unix domain socket client-server • Descriptor passing with Unix domain socket • Readings – UNP Sections 14.4 and 14.5, Ch15 1 Unix Domain Protocols • Used for client-server communication on a single machine – Use same API as with regular client-server – Both stream and datagram sockets are supported – Local IPC (inter-process communication) • Why do we need this? – Efficiency (faster than TCP/UDP socket on same machine) – Passing (file) descriptors – More security checks (passing credentials such as pid) 2 Address Structure • Open a socket using UNIX domain socket socket(AF_LOCAL, SOCK_STREAM, 0) socket(AF_LOCAL, SOCK_DGRAM, 0) – AF_LOCAL, AF_UNIX (historical) • UNIX domain socket address structure #include <sys/un.h> struct sockaddr_un { sa_family_t sun_family; /*AF_LOCAL or AF_UNIX */ char sun_path[104]; /* null-terminated path name */ } 3 A Few Notes • sun_path is null-terminated file pathname – Must not exist in file system – Should be absolute pathname – connect: access permission of sun_path is verified like open with write-only access • Unix domain stream socket similar to TCP • Unix domain datagram socket similar to UDP • For Unix domain datagram client – connect and sendto will not automatically bind socket to local address – Server cannot return datagram to client without bind 4 Binding a Unix Domain Socket • example1.c – – – – Use absolute path for path name bind will fail if the file exists Pathname can potentially overrun the sun_path buffer Otherwise, it is very similar to a TCP socket 5 Client-Server Using Unix Domain Protocols • example2.c and example3.c – Echo server and client – connect needs a pathname that is currently bound to an open UNIX domain socket of the same type – Permission test for connect is the same as that for open with write-only access – connect will fail if the listening queue is full • UNIX domain datagram sockets are similar to UDP sockets – Sender must bind first for the receiver to reply 6 Full-Duplex Stream Pipe • #include <sys/socket.h> • int socketpair(int family, int type, int protocol, int sockfd[2]); – – – – – Create two sockets connected together Family: AF_LOCAL Type: SOCK_STREAM or SOCK_DGRAM Protocol: 0 Full-duplex stream pipe. Both can be used for read and write – Example example4.c 7 Passing Descriptors • What we have learned – Parent open files and pass to child processes • What if child wants to pass back file descriptors to parent? • What if two unrelated processes want to pass file descriptors? • Unix domain socket can handle all these 8 Passing Descriptors • Involves creating a new descriptor in receiving process – referring to the same system open file table entry – It is normal that we see different descriptor numbers in sending and receiving processes – It is OK for the sending process to close the file after calling sendmsg 9 recvmsg and sendmsg Functions #include <sys/socket.h> ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags); struct msghdr { void socklen_t struct iovec int void socklen_t int *msg_name; //protocol address msg_namelen; *msg_iov; // array to hold data msg_iovlen; *msg_control; // ancillary data // link to cmsghdr struct msg_controllen; msg_flags; }; struct iovec { void *iov_base; // starting address of buffer size_t iov_len; // size of buffer }; 10 Control Message Header struct cmsghdr { socklen_t cmsg_len; // length in bytes int cmsg_level; // socket option level int cmsg_type; // socket option type // followed by unsigned char cmsg_data[] }; • A number of macros provided to access cmsghdr from msghdr – struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *) – struct cmsghdr *CMSG_NXTHDR(struct msghdr *, struct cmsghdr*) – unsigned char *CMSG_DATA(struct cmsghdr *) – etc 11 Passing Descriptor • Goal: passing open file descriptor in the kernel (process file descriptor entries are used to reference to the kernel entry). – Create a UNIX domain socket – Send open the descriptor with open, pipe etc (get the reference) – Send process build msghdr structure containing the descriptor to pass (using the reference), and call sendmsg – Receiving process call recvmsg to receive the descriptor on the domain socket (the reference can be different, but the kernel open file entry would be the same). 12 Passing Descriptor Example • Example5.c – Waiting for incoming request to open a specified file – After opening the file, send back the file descriptor • Example6.c – Send specified file to server – After receiving file descriptor returned from server, print the content of the file 13 Passing Credentials • cmsg_level: SOL_SOCKET • cmsg_type: SCM_CREDS struct cmsgcred { pid_t cmcred_pid; // PID of sending process uid_t cmcred_uid; // real UID uid_t cmcred_euid; // effective UID gid_t cmcred_gid; // real GID short cmcred_ngroups; // num of grps gid_t cmcred_groups[CMGROUP_MAX]; }; 14