1 /* $NetBSD: svr4_socket.c,v 1.21 2008/06/18 02:08:36 dogcow Exp $ */
4 * Copyright (c) 1996, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * In SVR4 unix domain sockets are referenced sometimes
34 * (in putmsg(2) for example) as a [device, inode] pair instead of a pathname.
35 * Since there is no iname() routine in the kernel, and we need access to
36 * a mapping from inode to pathname, we keep our own table. This is a simple
37 * linked list that contains the pathname, the [device, inode] pair, the
38 * file corresponding to that socket and the process. When the
39 * socket gets closed we remove the item from the list. The list gets loaded
40 * every time a stat(2) call finds a socket.
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: svr4_socket.c,v 1.21 2008/06/18 02:08:36 dogcow Exp $");
46 #include <sys/param.h>
47 #include <sys/kernel.h>
48 #include <sys/systm.h>
49 #include <sys/queue.h>
52 #include <sys/mount.h>
53 #include <sys/sched.h>
54 #include <sys/socket.h>
55 #include <sys/socketvar.h>
56 #include <sys/syscallargs.h>
60 #include <compat/svr4/svr4_types.h>
61 #include <compat/svr4/svr4_util.h>
62 #include <compat/svr4/svr4_socket.h>
63 #include <compat/svr4/svr4_signal.h>
64 #include <compat/svr4/svr4_sockmod.h>
65 #include <compat/svr4/svr4_lwp.h>
66 #include <compat/svr4/svr4_ucontext.h>
67 #include <compat/svr4/svr4_syscallargs.h>
69 struct svr4_sockcache_entry
{
70 struct proc
*p
; /* Process for the socket */
71 void *cookie
; /* Internal cookie used for matching */
72 struct sockaddr_un sock
;/* Pathname for the socket */
73 dev_t dev
; /* Device where the socket lives on */
74 svr4_ino_t ino
; /* Inode where the socket lives on */
75 TAILQ_ENTRY(svr4_sockcache_entry
) entries
;
78 static TAILQ_HEAD(svr4_sockcache_head
, svr4_sockcache_entry
) svr4_head
;
79 static int initialized
= 0;
82 svr4_find_socket(struct proc
*p
, struct file
*fp
, dev_t dev
, svr4_ino_t ino
)
84 struct svr4_sockcache_entry
*e
;
85 void *cookie
= ((struct socket
*) fp
->f_data
)->so_internal
;
88 DPRINTF(("svr4_find_socket: uninitialized [%p,%"PRId64
",%lu]\n",
90 TAILQ_INIT(&svr4_head
);
96 DPRINTF(("svr4_find_socket: [%p,%"PRId64
",%lu]: ", p
, dev
, ino
));
97 for (e
= svr4_head
.tqh_first
; e
!= NULL
; e
= e
->entries
.tqe_next
)
98 if (e
->p
== p
&& e
->dev
== dev
&& e
->ino
== ino
) {
100 if (e
->cookie
!= NULL
&& e
->cookie
!= cookie
)
101 panic("svr4 socket cookie mismatch");
104 DPRINTF(("%s\n", e
->sock
.sun_path
));
108 DPRINTF(("not found\n"));
114 svr4_delete_socket(struct proc
*p
, struct file
*fp
)
116 struct svr4_sockcache_entry
*e
;
117 void *cookie
= ((struct socket
*) fp
->f_data
)->so_internal
;
119 KERNEL_LOCK(1, NULL
);
122 TAILQ_INIT(&svr4_head
);
124 KERNEL_UNLOCK_ONE(NULL
);
128 for (e
= svr4_head
.tqh_first
; e
!= NULL
; e
= e
->entries
.tqe_next
)
129 if (e
->p
== p
&& e
->cookie
== cookie
) {
130 TAILQ_REMOVE(&svr4_head
, e
, entries
);
131 DPRINTF(("svr4_delete_socket: %s [%p,%"PRId64
",%lu]\n",
132 e
->sock
.sun_path
, p
, e
->dev
, e
->ino
));
137 KERNEL_UNLOCK_ONE(NULL
);
142 svr4_add_socket(struct proc
*p
, const char *path
, struct stat
*st
)
144 struct svr4_sockcache_entry
*e
;
148 KERNEL_LOCK(1, NULL
);
151 TAILQ_INIT(&svr4_head
);
155 e
= malloc(sizeof(*e
), M_TEMP
, M_WAITOK
);
161 if ((error
= copyinstr(path
, e
->sock
.sun_path
,
162 sizeof(e
->sock
.sun_path
), &len
)) != 0) {
163 DPRINTF(("svr4_add_socket: copyinstr failed %d\n", error
));
165 KERNEL_UNLOCK_ONE(NULL
);
169 e
->sock
.sun_family
= AF_LOCAL
;
170 e
->sock
.sun_len
= len
;
172 TAILQ_INSERT_HEAD(&svr4_head
, e
, entries
);
173 DPRINTF(("svr4_add_socket: %s [%p,%"PRId64
",%lu]\n", e
->sock
.sun_path
,
176 KERNEL_UNLOCK_ONE(NULL
);
182 svr4_sys_socket(struct lwp
*l
, const struct svr4_sys_socket_args
*uap
, register_t
*retval
)
184 struct sys___socket30_args bsd_ua
;
186 SCARG(&bsd_ua
, domain
) = SCARG(uap
, domain
);
187 SCARG(&bsd_ua
, protocol
) = SCARG(uap
, protocol
);
189 switch (SCARG(uap
, type
)) {
190 case SVR4_SOCK_DGRAM
:
191 SCARG(&bsd_ua
, type
) = SOCK_DGRAM
;
194 case SVR4_SOCK_STREAM
:
195 SCARG(&bsd_ua
, type
) = SOCK_STREAM
;
199 SCARG(&bsd_ua
, type
) = SOCK_RAW
;
203 SCARG(&bsd_ua
, type
) = SOCK_RDM
;
206 case SVR4_SOCK_SEQPACKET
:
207 SCARG(&bsd_ua
, type
) = SOCK_SEQPACKET
;
212 return sys___socket30(l
, &bsd_ua
, retval
);