[comp.protocols.tcp-ip] struct msghdr, passing fds between processes

cjsv@sserve.cc.adfa.oz.au (Christopher JS Vance) (04/22/91)

I note that a BSD struct msghdr (used with sendmsg and recvmsg) allows the
passing of `access rights'.  I seem to remember someone indicating that this
meant open file descriptors, sort of like a call on dup, except to a different
process.

Could someone who knows please point me to some documentation of this feature,
or at least let me know what kinds of stream these can be passed over.  I assume
that the numbers change on the wire and come out as open fds at the other end.

I guess that the stream must probably be a UNIX domain socket or pipe.  Or am
I barking up the wrong tree?

What I'd like to do is start up a process which has access to my login terminal,
have it open a socket-based connection to a server process, and have it pass
access to my login terminal to the server process.

(Subsidiary question - if I can do this, and my server process had no
controlling terminal, does it suddenly inherit one?)

What colour dragons be here?  (i.e., what do I need to be wary of?)

A bit of working code would be a bonus.  If your reference is the BSD book by
Leffler et al., I can borrow a copy, but won't bother unless it helps.  I had
a copy of the Advanced IPC document, but I don't seem to remember seeing it
there, and the person who has my copy hasn't returned it.  I can get it back,
though, if it's worth it.

-- 
Christopher

jik@athena.mit.edu (Jonathan I. Kamens) (04/23/91)

  (Note Followup-To.  This isn't really related to the TCP/IP protocol.)

In article <1991Apr22.123248.8250@sserve.cc.adfa.oz.au>, cjsv@sserve.cc.adfa.oz.au (Christopher JS Vance) writes:
|> I note that a BSD struct msghdr (used with sendmsg and recvmsg) allows the
|> passing of `access rights'.  I seem to remember someone indicating that this
|> meant open file descriptors, sort of like a call on dup, except to a different
|> process.

  Yes.

|> Could someone who knows please point me to some documentation of this feature,
|> or at least let me know what kinds of stream these can be passed over.  I assume
|> that the numbers change on the wire and come out as open fds at the other end.

  The only documentation about it that I know of is the recvmsg(2) man page
(or, at least, that's the only place I've seen it mentioned; it may be
mentioned in other man pages as well).  According to that man page, fd's can
only be passed over sockets (although I suspect that it'll work with pipes
too, since pipes are implemented on top of sockets).  The way you pass a
descriptor is by assigning the address of an int containing the descriptor
number to the msg_accrights member of the msghdr structure and sizeof(int) to
the msg_accrightslen member of the structure, and then sending a message over
a socket to another process using sendmsg().  The other process receives the
mssage using recvmsg(), and the integer found in the msg_accrights member will
be the number of the open file descriptor that was passed (as you point out,
it may be a different number than what it was at the originating end).

  I'm not sure what happens if you send a descriptor from a process to itself;
I suspect it's just like a dup().

  Here's a really simple program, with absolutely no error checking, that
demonstrates how this works.  It works for me, but I make no guarantees :-).

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <stdio.h>

main()
{
     int pair[2];
     struct msghdr msg;
     int fd;
     char buf[BUFSIZ];
     int c;
     
     socketpair(AF_UNIX, SOCK_STREAM, 0, pair);

     msg.msg_name = 0;
     msg.msg_namelen = 0;
     msg.msg_iov = 0;
     msg.msg_iovlen = 0;
     msg.msg_accrights = (char *) &fd;
     msg.msg_accrightslen = sizeof(fd);
     
     if (fork()) {
	  /* Parent */
	  close(pair[1]);
	  fd = open("/etc/passwd", O_RDONLY, 0);
	  sendmsg(pair[0], &msg, 0);
     }
     else {
	  /* Child */
	  close(pair[0]);
	  recvmsg(pair[1], &msg, 0);
	  while ((c = read(fd, buf, sizeof(buf))) > 0)
	       write(1, buf, c);
     }
}

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710