Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!ames!joyce!sri-unix!quintus!sun!pitstop!sundc!seismo!uunet!mcvax!unido!tub!net From: net@tub.UUCP (Oliver Laumann) Newsgroups: comp.unix.wizards Subject: passing access rights Message-ID: <705@tub.UUCP> Date: 20 Oct 88 16:57:23 GMT Reply-To: net@tub.UUCP (Oliver Laumann) Organization: Technical University of Berlin, Germany Lines: 100 Although this article contains a question, I think the matter is `wizardry' enough to justify a posting to comp.unix.wizards. What I would like to do is to pass a file descriptor from one process to another one through a connection based on UNIX domain sockets. Although the demonstration program attached to this article works fine under Integrated Solutions 4.3 BSD and SunOS 4.0, the calls to `sendmsg' and `recvmsg' both return "Bad address" under vanilla 4.3 BSD on a Microvax. I can't find the bug; all fields of the message structures passed to `sendmsg' and `recvmsg' are properly initialized. Unfortunately, the manual entries for these system calls do not indicate under what circumstances EFAULT is returned. Note that the `msg' structures are declared as `static'. And yes, I know, the programming style is sloppy (returning no value from main; return values of sys-calls not checked, etc.); my `real' programs certainly look differently. Here comes the code; first the server which accepts a connection on a UNIX domain socket and then opens /etc/passwd and sends the file descriptor to the client process (note that I don't want to send any data -- just the file descriptor). ------------------------------------------------------------ #include #include #include #include main () { int s, fd; struct sockaddr_un a; static struct msghdr msg; char *name = "foo"; unlink (name); if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) { perror ("socket"); return; } a.sun_family = AF_UNIX; strcpy (a.sun_path, name); if (bind (s, (struct sockaddr *)&a, strlen (name)+2) == -1) { perror ("bind"); return; } listen (s, 1); s = accept (s, (struct sockaddr *)0, (int *)0); if ((fd = open ("/etc/passwd", 0)) == -1) { perror ("passwd"); return; } msg.msg_accrights = (caddr_t)&fd; msg.msg_accrightslen = sizeof (fd); if (sendmsg (s, &msg, 0) == -1) perror ("sendmsg"); } ------------------------------------------------------------ This is the client receiving the file descriptor: ------------------------------------------------------------ #include #include #include #include main () { int s, n, fd; struct sockaddr_un a; static struct msghdr msg; char *name = "foo"; char buf[512]; if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) { perror ("socket"); return; } a.sun_family = AF_UNIX; strcpy (a.sun_path, name); if (connect (s, (struct sockaddr *)&a, strlen (name)+2) == -1) { perror ("connect"); return; } msg.msg_accrights = (caddr_t)&fd; msg.msg_accrightslen = sizeof(fd); if ((n = recvmsg (s, &msg, 0)) == -1) { perror ("recvmsg"); return; } if ((n = read (fd, buf, 512)) == -1) { perror ("read"); return; } write (1, buf, n); } ------------------------------------------------------------ Just compile the programs, start the server in the background, then invoke the client and watch the error messages. -- Regards, Oliver Laumann, Technical University of Berlin, Germany. ...!pyramid!tub!net or net@TUB.BITNET ...!mcvax!unido!tub!net