[net.unix-wizards] UNIX domain addressing for 4.2bsd IPC

knutson@ut-ngp.UUCP (12/08/83)

I can't seem to get this to work.  The problem is that binding a pathname
causes "No such file or directory".  The IPC Primer isn't much help either.
It uses bind(s,"/dev/foo", sizeof("/dev/foo")-1); but that doesn't work
either.  Does anyone know how to properly address AF_UNIX domain sockets?

-- 
Jim Knutson
ARPA: knutson@ut-ngp
UUCP: {ihnp4,seismo,kpno,ctvax}!ut-sally!ut-ngp!knutson

mogul%shasta@sri-unix.UUCP (12/09/83)

From:  Jeff Mogul <mogul@shasta>

The primer lies, but "man 2 bind" is more truthful.  You've
got to #include <sys/un.h> to get the definitions for the Unix
addressing domain, then create an appropriate sockaddr_un (limited
to 108 bytes, not 109 bytes as the declaration would imply, because
the kernel rejects sockaddrs >= MLEN and the sizeof(struct sockaddr_un)
== MLEN because the compiler short-aligns it, so passing
sizeof(struct sockaddr_un) as the length argument to bind() will
get you an error.)

By the way, don't even bother trying SOCK_DGRAM in AF_UNIX.  It won't
work.  If you try to use sendto/recvfrom the receiver gets a totally
blank address in "from".  If you try to use accept() in the receiver
and connect()/send() in the sender, the send() fails because it thinks
you haven't yet supplied a destination address! Following connect()
by sendto() fails because "you've already supplied a destination
address"(!)  Using sendto() by itself fails to wake up the receiver
from its accept().

I spent a few days staring at the kernel sources and I think the problems
with connection-based SOCK_DGRAMs (sort of a contradiction in terms
anyway) might be fixed with about 4 lines of code -- but I haven't been
brave enough to try it.  The problems with unconnected DGRAMs are
deeper, but I think it's possible to provide at least a kludgey
solution. I just gave up and used AF_INET, which works more or less,
but I'm not happy.

-Jeff
P.S.: To top it all off, there's a "man 4 inet" page but no corresponding
page for the Unix domain, at least on our tape.

msc@qubix.UUCP (Mark Callow) (12/09/83)

The "4.2 IPC Primer" is long out of date.  The correct syntax for
binding a name to a socket in the Unix domain is as follows:

struct sockaddr socketname = { AF_UNIX, { "/dev/foo" } };

bind(s, &socketname, sizeof( socketname ));

where struct sockaddr is declared as follows:

struct sockaddr {
	u_short	sa_family;		/* address family */
	char	sa_data[14];		/* up to 14 bytes of direct address */
};
-- 
From the Tardis of Mark Callow
msc@qubix.UUCP,  decwrl!qubix!msc@Berkeley.ARPA
...{decvax,ucbvax,ihnp4}!decwrl!qubix!msc, ...{ittvax,amd70}!qubix!msc

jim@haring.UUCP (Jim McKie) (12/11/83)

Here is a sample fragment of code which does the trick, the
IPC primer is wrong.

....
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SOCKET	"NameOfSomeFile"
....
	struct sockaddr_un socket;
....
	socket.sun_family = AF_UNIX;
	sprintf(socket.sun_path, "%s", SOCKET);
	if((s = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1){
		perror("program: socket");
		exit(1);
	}
	(void) unlink(socket.sun_path);
	if(bind(s, &socket, strlen(socket.sun_path)+2) == -1){
		perror("program: bind");
		exit(1);
	}
....

Jim McKie	Mathematisch Centrum, Amsterdam		....mcvax!jim

sam@ucbvax.UUCP (12/14/83)

I sure would like to see the "4 lines of code" which would fix the UNIX
domain addressing problems.  To be simple, naming in the UNIX domain
needs an extensive overhaul.  Because the sockets are tied to inodes
one can't simply record bound names and expect them to remain constant
across the lifetime of a socket (remember the socket could be be moved
elsewhere in the file system while it's in use).  Also, since socket
names are pathnames, each send requires a call to namei resulting in
abominable performance.  There's an obvious need to be able to "bind"
(not bind(2)) UNIX domain sockets to files in the UNIX file system, but
the way it's done now was as much for expediency as anything else.

P.S. You could probably fix the wandering name problem which
currently exists by putting pwd in the kernel...just kidding Rob.