Download presentation
Presentation is loading. Please wait.
Published byRoss Todd Modified over 8 years ago
1
Chapter 14 Unix 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 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) { intsockfd; socklen_tlen; struct sockaddr_un addr1, addr2; if (argc != 2) err_quit("usage: unixbind "); 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 = %d\n", addr2.sun_path, len); exit(0); }
6
socketpair Function Create two sockets that are then connected together(only available in unix domain socket) family must be AF_LOCAL protocol must be 0 #include int socketpair(int family, int type, int protocol, int sockfd[2]); return: nonzero if OK, -1 on error
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) { intlistenfd, connfd; pid_tchildpid; socklen_tclilen; struct sockaddr_uncliaddr, servaddr; voidsig_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) { intsockfd; struct sockaddr_unservaddr; 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" int main(int argc, char **argv) { intsockfd; struct sockaddr_unservaddr, 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) { intsockfd; struct sockaddr_uncliaddr, 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 server's 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 descriptor 3)the sending process build a msghdr structure containing the descriptor to be passed 4)the receiving process calls recvmsg to receive the descriptor on the unix domain socket from step 1)
15
Descriptor passing example [0] [1] mycat Figure 14.7) mycat program after create stream pipe using socketpair
16
fork [1][0] Exec(command-line args) mycat openfile descriptor Figure 14.8) mycat program after invoking openfile program
17
#include"unp.h" intmy_open(const char *, int); int main(int argc, char **argv) { intfd, n; charbuff[BUFFSIZE]; if (argc != 2) err_quit("usage: mycat "); 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" int my_open(const char *pathname, int mode) { intfd, sockfd[2], status; pid_tchildpid; charc, 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 don't 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 child's 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
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.