svr4_socket.c revision 71449
143412Snewton/*
243412Snewton * Copyright (c) 1998 Mark Newton
343412Snewton * Copyright (c) 1996 Christos Zoulas.
443412Snewton * All rights reserved.
543412Snewton *
643412Snewton * Redistribution and use in source and binary forms, with or without
743412Snewton * modification, are permitted provided that the following conditions
843412Snewton * are met:
943412Snewton * 1. Redistributions of source code must retain the above copyright
1043412Snewton *    notice, this list of conditions and the following disclaimer.
1143412Snewton * 2. Redistributions in binary form must reproduce the above copyright
1243412Snewton *    notice, this list of conditions and the following disclaimer in the
1343412Snewton *    documentation and/or other materials provided with the distribution.
1443412Snewton * 3. All advertising materials mentioning features or use of this software
1543412Snewton *    must display the following acknowledgement:
1643412Snewton *	This product includes software developed by Christos Zoulas.
1743412Snewton * 4. The name of the author may not be used to endorse or promote products
1843412Snewton *    derived from this software without specific prior written permission.
1943412Snewton *
2043412Snewton * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2143412Snewton * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2243412Snewton * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2343412Snewton * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2443412Snewton * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2543412Snewton * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2643412Snewton * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2743412Snewton * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2843412Snewton * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2943412Snewton * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3049267Snewton *
3150477Speter * $FreeBSD: head/sys/compat/svr4/svr4_socket.c 71449 2001-01-23 21:07:16Z jhb $
3243412Snewton */
3343412Snewton
3443412Snewton/*
3543412Snewton * In SVR4 unix domain sockets are referenced sometimes
3643412Snewton * (in putmsg(2) for example) as a [device, inode] pair instead of a pathname.
3743412Snewton * Since there is no iname() routine in the kernel, and we need access to
3843412Snewton * a mapping from inode to pathname, we keep our own table. This is a simple
3943412Snewton * linked list that contains the pathname, the [device, inode] pair, the
4043412Snewton * file corresponding to that socket and the process. When the
4143412Snewton * socket gets closed we remove the item from the list. The list gets loaded
4243412Snewton * every time a stat(2) call finds a socket.
4343412Snewton */
4443412Snewton
4543412Snewton#include <sys/param.h>
4643412Snewton#include <sys/systm.h>
4743412Snewton#include <sys/queue.h>
4843412Snewton#include <sys/file.h>
4943412Snewton#include <sys/socket.h>
5043412Snewton#include <sys/socketvar.h>
5143412Snewton#include <sys/sysproto.h>
5243412Snewton#include <sys/un.h>
5343412Snewton#include <sys/stat.h>
5443412Snewton#include <sys/proc.h>
5543412Snewton#include <sys/malloc.h>
5643412Snewton
5765302Sobrien#include <compat/svr4/svr4.h>
5865302Sobrien#include <compat/svr4/svr4_types.h>
5965302Sobrien#include <compat/svr4/svr4_util.h>
6065302Sobrien#include <compat/svr4/svr4_socket.h>
6165302Sobrien#include <compat/svr4/svr4_signal.h>
6265302Sobrien#include <compat/svr4/svr4_sockmod.h>
6365302Sobrien#include <compat/svr4/svr4_proto.h>
6443412Snewton
6543412Snewtonstruct svr4_sockcache_entry {
6643412Snewton	struct proc *p;		/* Process for the socket		*/
6743412Snewton	void *cookie;		/* Internal cookie used for matching	*/
6843412Snewton	struct sockaddr_un sock;/* Pathname for the socket		*/
6949267Snewton	udev_t dev;		/* Device where the socket lives on	*/
7043412Snewton	ino_t ino;		/* Inode where the socket lives on	*/
7160938Sjake	TAILQ_ENTRY(svr4_sockcache_entry) entries;
7243412Snewton};
7343412Snewton
7460938Sjakeextern TAILQ_HEAD(svr4_sockcache_head, svr4_sockcache_entry) svr4_head;
7543412Snewtonextern int svr4_str_initialized;
7643412Snewton
7743412Snewtonstruct sockaddr_un *
7843412Snewtonsvr4_find_socket(p, fp, dev, ino)
7943412Snewton	struct proc *p;
8043412Snewton	struct file *fp;
8149267Snewton	udev_t dev;
8243412Snewton	ino_t ino;
8343412Snewton{
8443412Snewton	struct svr4_sockcache_entry *e;
8543412Snewton	void *cookie = ((struct socket *) fp->f_data)->so_emuldata;
8643412Snewton
8771449Sjhb	if (svr4_str_initialized != 2) {
8871449Sjhb		if (atomic_cmpset_acq_int(&svr4_str_initialized, 0, 1)) {
8971449Sjhb			DPRINTF(("svr4_find_socket: uninitialized [%p,%d,%d]\n",
9071449Sjhb			    p, dev, ino));
9171449Sjhb			TAILQ_INIT(&svr4_head);
9271449Sjhb			atomic_store_rel(&svr4_str_initialized, 2);
9371449Sjhb		}
9443412Snewton		return NULL;
9543412Snewton	}
9643412Snewton
9743412Snewton
9843412Snewton	DPRINTF(("svr4_find_socket: [%p,%d,%d]: ", p, dev, ino));
9971449Sjhb	TAILQ_FOREACH(e, &svr4_head, entries)
10043412Snewton		if (e->p == p && e->dev == dev && e->ino == ino) {
10143412Snewton#ifdef DIAGNOSTIC
10243412Snewton			if (e->cookie != NULL && e->cookie != cookie)
10343412Snewton				panic("svr4 socket cookie mismatch");
10443412Snewton#endif
10543412Snewton			e->cookie = cookie;
10643412Snewton			DPRINTF(("%s\n", e->sock.sun_path));
10743412Snewton			return &e->sock;
10843412Snewton		}
10943412Snewton
11043412Snewton	DPRINTF(("not found\n"));
11143412Snewton	return NULL;
11243412Snewton}
11343412Snewton
11443412Snewton
11554305Snewton/*
11654305Snewton * svr4_delete_socket() is in sys/dev/streams.c (because it's called by
11754305Snewton * the streams "soo_close()" routine).
11854305Snewton */
11943412Snewtonint
12043412Snewtonsvr4_add_socket(p, path, st)
12143412Snewton	struct proc *p;
12243412Snewton	const char *path;
12343412Snewton	struct stat *st;
12443412Snewton{
12543412Snewton	struct svr4_sockcache_entry *e;
12643412Snewton	int len, error;
12743412Snewton
12871449Sjhb	/*
12971449Sjhb	 * Wait for the TAILQ to be initialized.  Only the very first CPU
13071449Sjhb	 * will succeed on the atomic_cmpset().  The other CPU's will spin
13171449Sjhb	 * until the first one finishes the initialization.  Once the
13271449Sjhb	 * initialization is complete, the condition will always fail
13371449Sjhb	 * avoiding expensive atomic operations in the common case.
13471449Sjhb	 */
13571449Sjhb	while (svr4_str_initialized != 2)
13671449Sjhb		if (atomic_cmpset_acq_int(&svr4_str_initialized, 0, 1)) {
13771449Sjhb			TAILQ_INIT(&svr4_head);
13871449Sjhb			atomic_store_rel_int(&svr4_str_initialized, 2);
13971449Sjhb		}
14043412Snewton
14143412Snewton	e = malloc(sizeof(*e), M_TEMP, M_WAITOK);
14243412Snewton	e->cookie = NULL;
14343412Snewton	e->dev = st->st_dev;
14443412Snewton	e->ino = st->st_ino;
14543412Snewton	e->p = p;
14643412Snewton
14743412Snewton	if ((error = copyinstr(path, e->sock.sun_path,
14843412Snewton	    sizeof(e->sock.sun_path), &len)) != 0) {
14943412Snewton		DPRINTF(("svr4_add_socket: copyinstr failed %d\n", error));
15043412Snewton		free(e, M_TEMP);
15143412Snewton		return error;
15243412Snewton	}
15343412Snewton
15443412Snewton	e->sock.sun_family = AF_LOCAL;
15543412Snewton	e->sock.sun_len = len;
15643412Snewton
15743412Snewton	TAILQ_INSERT_HEAD(&svr4_head, e, entries);
15843412Snewton	DPRINTF(("svr4_add_socket: %s [%p,%d,%d]\n", e->sock.sun_path,
15943412Snewton		 p, e->dev, e->ino));
16043412Snewton	return 0;
16143412Snewton}
16243412Snewton
16343412Snewton
16443412Snewtonint
16543412Snewtonsvr4_sys_socket(p, uap)
16643412Snewton	struct proc *p;
16743412Snewton	struct svr4_sys_socket_args *uap;
16843412Snewton{
16943412Snewton	switch (SCARG(uap, type)) {
17043412Snewton	case SVR4_SOCK_DGRAM:
17143412Snewton		SCARG(uap, type) = SOCK_DGRAM;
17243412Snewton		break;
17343412Snewton
17443412Snewton	case SVR4_SOCK_STREAM:
17543412Snewton		SCARG(uap, type) = SOCK_STREAM;
17643412Snewton		break;
17743412Snewton
17843412Snewton	case SVR4_SOCK_RAW:
17943412Snewton		SCARG(uap, type) = SOCK_RAW;
18043412Snewton		break;
18143412Snewton
18243412Snewton	case SVR4_SOCK_RDM:
18343412Snewton		SCARG(uap, type) = SOCK_RDM;
18443412Snewton		break;
18543412Snewton
18643412Snewton	case SVR4_SOCK_SEQPACKET:
18743412Snewton		SCARG(uap, type) = SOCK_SEQPACKET;
18843412Snewton		break;
18943412Snewton	default:
19043412Snewton		return EINVAL;
19143412Snewton	}
19243412Snewton	return socket(p, (struct socket_args *)uap);
19343412Snewton}
194