net@tub.UUCP (Oliver Laumann) (10/20/88)
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 <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/uio.h> 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 <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/uio.h> 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
chris@mimsy.UUCP (Chris Torek) (10/22/88)
In article <705@tub.UUCP> net@tub.UUCP (Oliver Laumann) writes: >... 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. As it turns out, the problem is that copyin() may not do what was intended if it is given a zero length. In this case, it still probes one page. You can get the program to work by giving the address of some object as `msg.msg_iov': msg.msg_iovlen can still be zero, but msg.msg_iov must point to something. Probably copyin() and copyout() should return zero (no error) when asked to copy no bytes (as should bcopy()), and useracc and kernacc should grant access to no bytes; then a number of tests for zero lengths could be dropped elsewhere. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
tchrist@convex.UUCP (Tom Christiansen) (10/22/88)
To make this stuff work, you need to fill in the iovec part of the message, setting the iovlen to 1. Odd that Suns don't care about this; 4.3 Vaxen and Convexen do. --tom Tom Christiansen {uiucdcs,ut-sally,sun}!convex!tchrist Convex Computer Corporation tchrist@convex.COM UNIX Support, Training, and System Administration "That's not a bug -- it's a feature!"