Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 28 Aug 1998 21:14:46 -0400 (EDT)
From:      Bill Paul <wpaul@skynet.ctr.columbia.edu>
To:        chanders@timing.com (Craig Anderson)
Cc:        freebsd-hackers@FreeBSD.ORG
Subject:   Re: Help with passing fd on FreeBSD
Message-ID:  <199808290114.VAA28236@skynet.ctr.columbia.edu>
In-Reply-To: <199808281426.IAA10588@count.timing.com> from "Craig Anderson" at Aug 28, 98 08:26:25 am

next in thread | previous in thread | raw e-mail | index | archive | help
Of all the gin joints in all the towns in all the world, Craig Anderson 
had to walk into mine and say:

> 
> Can someone give me pointers on passing open file descriptors on FreeBSD?
> This is covered in W. Richard Stevens Advanced programming book, but
> the structs in FreeBSD are slightly different, and I've never done this.
> 
> Thanks,
> Craig

Sure. Appended to this message are two small programs: r.c and s.c.
s.c sends a descriptor and r.c receives it. Last time I used this
was on FreeBSD 2.1.0 but it should still work. The descriptor being
sent is actually the AF_LOCAL socket that s.c creates to talk to
r.c, which is kind of pointless but you can use any other descriptor
index you want (as long as it refers to a valid open descriptor).

-Bill

-- 
=============================================================================
-Bill Paul            (212) 854-6020 | System Manager, Master of Unix-Fu
Work:         wpaul@ctr.columbia.edu | Center for Telecommunications Research
Home:  wpaul@skynet.ctr.columbia.edu | Columbia University, New York City
=============================================================================
 "It is not I who am crazy; it is I who am mad!" - Ren Hoek, "Space Madness"
=============================================================================

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <err.h>
#include <sys/types.h>
#include <sys/time.h>
#include <string.h>
#include <sys/uio.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>

#ifndef lint
static const char rcsid[] = "$Id: r.c,v 1.4 1998/08/29 01:03:52 wpaul Exp $";
#endif

struct cmessage {
	struct cmsghdr cmsg;
	int fd;
};

int
main()
{
	struct iovec iov[1];
	struct msghdr msg;
	struct cmessage cm;
	struct sockaddr_un sun;
	int s;
	int sock;
	int len;
	fd_set readfds;
	char recbuf[1024];

	if (unlink("/tmp/testsock") == -1)
		warn("couldn't remove old socket");

	strcpy(sun.sun_path, "/tmp/testsock");
	sun.sun_family = AF_UNIX;
	len = sun.sun_len = sizeof(sun.sun_len) + sizeof(sun.sun_family) +
			strlen(sun.sun_path) + 1;

	if  ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
		err(1, "socket creation failed");

	iov[0].iov_base = (char *)&recbuf;
	iov[0].iov_len = sizeof(recbuf);

	bzero((char *)&cm, sizeof(cm));
	bzero((char *)&msg, sizeof(msg));

	msg.msg_iov = iov;
	msg.msg_iovlen = 1;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = (caddr_t)&cm;
	msg.msg_controllen = sizeof(struct cmessage);
	msg.msg_flags = 0;

	if (bind(s, (struct sockaddr *)&sun, len) == -1)
		err(1, "couldn't bind socket");

	listen(s, 2);

	if ((sock = accept(s, (struct sockaddr *)&sun, &len)) == -1)
		err(1, "accept failed");

	FD_ZERO(&readfds);
	FD_SET(sock, &readfds);

	select(FD_SETSIZE, &readfds, NULL, NULL, NULL);

	if ((len = recvmsg(sock, &msg, 0)) == -1)
		err(1, "recvmsg failed");

	printf ("read %d bytes\n", len);
	printf ("data: %s\n", iov[0].iov_base);

	if (cm.cmsg.cmsg_type != SCM_RIGHTS)
		warnx("message didn't contain SCM_RIGHTS");

	printf ("FD: %d\n", cm.fd);

	close(sock);
	close(s);

	exit(0);
}



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <err.h>
#include <sys/types.h>
#include <sys/time.h>
#include <string.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/fcntl.h>
#include <sys/stat.h>

#ifndef lint
static const char rcsid[] = "$Id: s.c,v 1.4 1998/08/29 01:05:28 wpaul Exp $";
#endif

struct cmessage {
	struct cmsghdr cmsg;
	int fd;
};

int
main()
{
	struct iovec iov[1];
	struct msghdr msg;
	struct cmessage cm;
	struct sockaddr_un sun;
	int s;
	int len;
	char sendbuf[] = "This is a test buffer.";

	strcpy(sun.sun_path, "/tmp/testsock");
	sun.sun_family = AF_UNIX;
	len = sun.sun_len = sizeof(sun.sun_len) + sizeof(sun.sun_family) +
			strlen(sun.sun_path) + 1;

	if  ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
		err(1, "socket creation failed");

	if (connect(s, (struct sockaddr *)&sun, len) == -1)
		err(1, "couldn't connect socket");

	iov[0].iov_base = (char *)&sendbuf;
	iov[0].iov_len = sizeof(sendbuf);

	cm.cmsg.cmsg_type = SCM_RIGHTS;
	cm.cmsg.cmsg_level = SOL_SOCKET;
	cm.cmsg.cmsg_len = sizeof(struct cmessage);
	cm.fd = s;	/* file descriptor to be transfered */

	msg.msg_iov = iov;
	msg.msg_iovlen = 1;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = (caddr_t)&cm;
	msg.msg_controllen = sizeof(struct cmessage);
	msg.msg_flags = 0;

	if ((len = sendmsg(s, &msg, 0)) == -1)
		err(1, "sendmsg failed");
	printf ("sent message (%d bytes), sending data...\n", len);

	close(s);

	exit(0);
}

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199808290114.VAA28236>