Upcoming SlideShare
Loading in...5

Like this? Share it with your network

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads


Total Views
On Slideshare
From Embeds
Number of Embeds



Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

    No notes for slide


  • 1. Chapter 14Unix domain protocol
  • 2. contents• Introduction• unix domain socket address structure• socketpair• socket function• unix domain stream client-server• unix domain datagram client-server• passing descriptors• receiving sender credentials
  • 3. Introduction• Unix domain protocol – perform client-server communication on a single host using same API that is used for client-server model on the different hosts.
  • 4. unix domain socket address structure• <sys/un.h>struct sockaddr_un{ uint8_t sun_len; sa_family_t sun_family; /*AF_LOCAL*/ char sun_path[104]; /*null terminated pathname*/};• sun_path => must null terminated
  • 5. #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 = Socket(AF_LOCAL, SOCK_STREAM, 0); unlink(argv[1]); /* OK if this fails */ 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 = %dn", addr2.sun_path, len); exit(0);}
  • 6. socketpair Function• Create two sockets that are then connected together(only available in unix domain socket)#include<sys/socket.h>int socketpair(int family, int type, int protocol, int sockfd[2]); return: nonzero if OK, -1 on error• family must be AF_LOCAL• protocol must be 0
  • 7. socket function(restriction)• Default file access permition created by bind shiuld be 0777, modified by the current umask value• path name must be absolute pathname not a relative path name• the path name in the connect must be a pathname that is currently bound to an open unix domain socket of the same type.• Unix domain stream socket are similar to TCP socket• unix domain datagram are similar to UDP socket• unlike UDP socket, sending a datagram on an unbound unix domain datagram does not bind a pathname to the socket
  • 8. unix domain stream client-server#include "unp.h"int main(int argc, char **argv){ int listenfd, connfd; pid_t childpid; socklen_t clilen; struct sockaddr_un cliaddr, servaddr; void sig_chld(int); listenfd = Socket(AF_LOCAL, SOCK_STREAM, 0); unlink(UNIXSTR_PATH); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, UNIXSTR_PATH); Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); Listen(listenfd, LISTENQ); Signal(SIGCHLD, sig_chld);
  • 9. unix domain stream client-server(2)for ( ; ; ) { clilen = sizeof(cliaddr); if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) { if (errno == EINTR) continue; /* back to for() */ else err_sys("accept error"); } if ( (childpid = Fork()) == 0) { /* child process */ Close(listenfd); /* close listening socket */ str_echo(connfd); /* process the request */ exit(0); } Close(connfd); /* parent closes connected socket */ }}
  • 10. unix domain datagram client-server#include "unp.h"int main(int argc, char **argv){ int sockfd; struct sockaddr_un servaddr; sockfd = Socket(AF_LOCAL, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, UNIXSTR_PATH); Connect(sockfd, (SA *) &servaddr, sizeof(servaddr)); str_cli(stdin, sockfd); /* do it all */ exit(0);} /* unix domain stream protocol echo client */
  • 11. unix domain datagram client-server(2)#include "unp.h"intmain(int argc, char **argv){ int sockfd; struct sockaddr_un servaddr, cliaddr; sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0); unlink(UNIXDG_PATH); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, UNIXDG_PATH); Bind(sockfd, (SA *) &servaddr, sizeof(servaddr)); dg_echo(sockfd, (SA *) &cliaddr, sizeof(cliaddr));}/* unix domain datagram protocol echo server */
  • 12. unix domain datagram client-server(3)#include "unp.h"int main(int argc, char **argv){ int sockfd; struct sockaddr_un cliaddr, servaddr; sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0); bzero(&cliaddr, sizeof(cliaddr)); /* bind an address for us */ cliaddr.sun_family = AF_LOCAL; strcpy(cliaddr.sun_path, tmpnam(NULL)); Bind(sockfd, (SA *) &cliaddr, sizeof(cliaddr)); bzero(&servaddr, sizeof(servaddr)); /* fill in servers address */ servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, UNIXDG_PATH); dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr)); exit(0);} /* unix domain datagram protocol echo client */
  • 13. passing descriptors• Current unix system provide a way to pass any open descriptor from one process to any other process.(using sendmsg)
  • 14. passing descriptors(2)1)Create a unix domain socket(stream or datagram)2)one process opens a descriptor by calling any of the unix function that returns a descriptor3)the sending process build a msghdr structure containing the descriptor to be passed4)the receiving process calls recvmsg to receive the descriptor on the unix domain socket from step 1)
  • 15. Descriptor passing example mycat [0] [1] Figure 14.7) mycat program after create stream pipe using socketpair
  • 16. mycat openfile fork Exec(command-line args)[0] [1] descriptor Figure 14.8) mycat program after invoking openfile program
  • 17. #include "unp.h"int my_open(const char *, int);int main(int argc, char **argv){ int fd, n; char buff[BUFFSIZE]; if (argc != 2) err_quit("usage: mycat <pathname>"); if ( (fd = my_open(argv[1], O_RDONLY)) < 0) err_sys("cannot open %s", argv[1]); while ( (n = Read(fd, buff, BUFFSIZE)) > 0) Write(STDOUT_FILENO, buff, n); exit(0);} mycat program show in Figure 14.7)
  • 18. #include "unp.h"intmy_open(const char *pathname, int mode){ int fd, sockfd[2], status; pid_t childpid; char c, argsockfd[10], argmode[10]; Socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd); if ( (childpid = Fork()) == 0) { /* child process */ Close(sockfd[0]); snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]); snprintf(argmode, sizeof(argmode), "%d", mode); execl("./openfile", "openfile", argsockfd, pathname, argmode, (char *) NULL); err_sys("execl error"); } myopen function(1) : open a file and return a descriptor
  • 19. /* parent process - wait for the child to terminate */ Close(sockfd[1]); /* close the end we dont use */ Waitpid(childpid, &status, 0); if (WIFEXITED(status) == 0) err_quit("child did not terminate"); if ( (status = WEXITSTATUS(status)) == 0) Read_fd(sockfd[0], &c, 1, &fd); else { errno = status; /* set errno value from childs status */ fd = -1; } Close(sockfd[0]); return(fd);} myopen function(2) : open a file and return a descriptor
  • 20. receiving sender credentials• User credentials via fcred structure Struct fcred{ uid_t fc_ruid; /*real user ID*/ gid_t fc_rgid; /*real group ID*/ char fc_login[MAXLOGNAME];/*setlogin() name*/ uid_t fc_uid; /*effectivr user ID*/ short fc_ngroups; /*number of groups*/ gid_t fc_groups[NGROUPS]; /*supplemenary group IDs*/ }; #define fc_gid fc_groups[0] /* effective group ID */
  • 21. receiving sender credentials(2)• Usally MAXLOGNAME is 16• NGROUP is 16• fc_ngroups is at least 1• the credentials are sent as ancillary data when data is sent on unix domain socket.(only if receiver of data has enabled the LOCAL_CREDS socket option)• on a datagram socket , the credentials accompany every datagram.• Credentials cannot be sent along with a descriptor• user are not able to forge credentials