uipc_usrreq.c revision 127652
1/*
2 * Copyright (c) 1982, 1986, 1989, 1991, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *	From: @(#)uipc_usrreq.c	8.3 (Berkeley) 1/4/94
34 */
35
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD: head/sys/kern/uipc_usrreq.c 127652 2004-03-31 01:41:30Z rwatson $");
38
39#include "opt_mac.h"
40
41#include <sys/param.h>
42#include <sys/domain.h>
43#include <sys/fcntl.h>
44#include <sys/malloc.h>		/* XXX must be before <sys/file.h> */
45#include <sys/file.h>
46#include <sys/filedesc.h>
47#include <sys/jail.h>
48#include <sys/kernel.h>
49#include <sys/lock.h>
50#include <sys/mac.h>
51#include <sys/mbuf.h>
52#include <sys/mutex.h>
53#include <sys/namei.h>
54#include <sys/proc.h>
55#include <sys/protosw.h>
56#include <sys/resourcevar.h>
57#include <sys/socket.h>
58#include <sys/socketvar.h>
59#include <sys/signalvar.h>
60#include <sys/stat.h>
61#include <sys/sx.h>
62#include <sys/sysctl.h>
63#include <sys/systm.h>
64#include <sys/un.h>
65#include <sys/unpcb.h>
66#include <sys/vnode.h>
67
68#include <vm/uma.h>
69
70static uma_zone_t unp_zone;
71static	unp_gen_t unp_gencnt;
72static	u_int unp_count;
73
74static	struct unp_head unp_shead, unp_dhead;
75
76/*
77 * Unix communications domain.
78 *
79 * TODO:
80 *	SEQPACKET, RDM
81 *	rethink name space problems
82 *	need a proper out-of-band
83 *	lock pushdown
84 */
85static struct	sockaddr sun_noname = { sizeof(sun_noname), AF_LOCAL };
86static ino_t	unp_ino;		/* prototype for fake inode numbers */
87
88static int     unp_attach(struct socket *);
89static void    unp_detach(struct unpcb *);
90static int     unp_bind(struct unpcb *,struct sockaddr *, struct thread *);
91static int     unp_connect(struct socket *,struct sockaddr *, struct thread *);
92static int     unp_connect2(struct socket *so, struct socket *so2);
93static void    unp_disconnect(struct unpcb *);
94static void    unp_shutdown(struct unpcb *);
95static void    unp_drop(struct unpcb *, int);
96static void    unp_gc(void);
97static void    unp_scan(struct mbuf *, void (*)(struct file *));
98static void    unp_mark(struct file *);
99static void    unp_discard(struct file *);
100static void    unp_freerights(struct file **, int);
101static int     unp_internalize(struct mbuf **, struct thread *);
102static int     unp_listen(struct unpcb *, struct thread *);
103
104static int
105uipc_abort(struct socket *so)
106{
107	struct unpcb *unp = sotounpcb(so);
108
109	if (unp == NULL)
110		return (EINVAL);
111	unp_drop(unp, ECONNABORTED);
112	unp_detach(unp);
113	sotryfree(so);
114	return (0);
115}
116
117static int
118uipc_accept(struct socket *so, struct sockaddr **nam)
119{
120	struct unpcb *unp = sotounpcb(so);
121
122	if (unp == NULL)
123		return (EINVAL);
124
125	/*
126	 * Pass back name of connected socket,
127	 * if it was bound and we are still connected
128	 * (our peer may have closed already!).
129	 */
130	if (unp->unp_conn != NULL && unp->unp_conn->unp_addr != NULL) {
131		*nam = sodupsockaddr(
132		    (struct sockaddr *)unp->unp_conn->unp_addr, M_WAITOK);
133	} else {
134		*nam = sodupsockaddr((struct sockaddr *)&sun_noname,
135		    M_WAITOK);
136	}
137	return (0);
138}
139
140static int
141uipc_attach(struct socket *so, int proto, struct thread *td)
142{
143	struct unpcb *unp = sotounpcb(so);
144
145	if (unp != NULL)
146		return (EISCONN);
147	return (unp_attach(so));
148}
149
150static int
151uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
152{
153	struct unpcb *unp = sotounpcb(so);
154
155	if (unp == NULL)
156		return (EINVAL);
157
158	return (unp_bind(unp, nam, td));
159}
160
161static int
162uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
163{
164	struct unpcb *unp = sotounpcb(so);
165
166	if (unp == NULL)
167		return (EINVAL);
168	return (unp_connect(so, nam, curthread));
169}
170
171int
172uipc_connect2(struct socket *so1, struct socket *so2)
173{
174	struct unpcb *unp = sotounpcb(so1);
175
176	if (unp == NULL)
177		return (EINVAL);
178
179	return (unp_connect2(so1, so2));
180}
181
182/* control is EOPNOTSUPP */
183
184static int
185uipc_detach(struct socket *so)
186{
187	struct unpcb *unp = sotounpcb(so);
188
189	if (unp == NULL)
190		return (EINVAL);
191
192	unp_detach(unp);
193	return (0);
194}
195
196static int
197uipc_disconnect(struct socket *so)
198{
199	struct unpcb *unp = sotounpcb(so);
200
201	if (unp == NULL)
202		return (EINVAL);
203	unp_disconnect(unp);
204	return (0);
205}
206
207static int
208uipc_listen(struct socket *so, struct thread *td)
209{
210	struct unpcb *unp = sotounpcb(so);
211
212	if (unp == NULL || unp->unp_vnode == NULL)
213		return (EINVAL);
214	return (unp_listen(unp, td));
215}
216
217static int
218uipc_peeraddr(struct socket *so, struct sockaddr **nam)
219{
220	struct unpcb *unp = sotounpcb(so);
221
222	if (unp == NULL)
223		return (EINVAL);
224	if (unp->unp_conn != NULL && unp->unp_conn->unp_addr != NULL)
225		*nam = sodupsockaddr(
226		    (struct sockaddr *)unp->unp_conn->unp_addr, M_WAITOK);
227	else {
228		/*
229		 * XXX: It seems that this test always fails even when
230		 * connection is established.  So, this else clause is
231		 * added as workaround to return PF_LOCAL sockaddr.
232		 */
233		*nam = sodupsockaddr((struct sockaddr *)&sun_noname,
234		    M_WAITOK);
235	}
236	return (0);
237}
238
239static int
240uipc_rcvd(struct socket *so, int flags)
241{
242	struct unpcb *unp = sotounpcb(so);
243	struct socket *so2;
244	u_long newhiwat;
245
246	if (unp == NULL)
247		return (EINVAL);
248	switch (so->so_type) {
249	case SOCK_DGRAM:
250		panic("uipc_rcvd DGRAM?");
251		/*NOTREACHED*/
252
253	case SOCK_STREAM:
254		if (unp->unp_conn == NULL)
255			break;
256		so2 = unp->unp_conn->unp_socket;
257		/*
258		 * Adjust backpressure on sender
259		 * and wakeup any waiting to write.
260		 */
261		so2->so_snd.sb_mbmax += unp->unp_mbcnt - so->so_rcv.sb_mbcnt;
262		unp->unp_mbcnt = so->so_rcv.sb_mbcnt;
263		newhiwat = so2->so_snd.sb_hiwat + unp->unp_cc -
264		    so->so_rcv.sb_cc;
265		(void)chgsbsize(so2->so_cred->cr_uidinfo, &so2->so_snd.sb_hiwat,
266		    newhiwat, RLIM_INFINITY);
267		unp->unp_cc = so->so_rcv.sb_cc;
268		sowwakeup(so2);
269		break;
270
271	default:
272		panic("uipc_rcvd unknown socktype");
273	}
274	return (0);
275}
276
277/* pru_rcvoob is EOPNOTSUPP */
278
279static int
280uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
281	  struct mbuf *control, struct thread *td)
282{
283	int error = 0;
284	struct unpcb *unp = sotounpcb(so);
285	struct socket *so2;
286	u_long newhiwat;
287
288	if (unp == NULL) {
289		error = EINVAL;
290		goto release;
291	}
292	if (flags & PRUS_OOB) {
293		error = EOPNOTSUPP;
294		goto release;
295	}
296
297	if (control != NULL && (error = unp_internalize(&control, td)))
298		goto release;
299
300	switch (so->so_type) {
301	case SOCK_DGRAM:
302	{
303		struct sockaddr *from;
304
305		if (nam != NULL) {
306			if (unp->unp_conn != NULL) {
307				error = EISCONN;
308				break;
309			}
310			error = unp_connect(so, nam, td);
311			if (error)
312				break;
313		} else {
314			if (unp->unp_conn == NULL) {
315				error = ENOTCONN;
316				break;
317			}
318		}
319		so2 = unp->unp_conn->unp_socket;
320		if (unp->unp_addr != NULL)
321			from = (struct sockaddr *)unp->unp_addr;
322		else
323			from = &sun_noname;
324		if (sbappendaddr(&so2->so_rcv, from, m, control)) {
325			sorwakeup(so2);
326			m = NULL;
327			control = NULL;
328		} else {
329			error = ENOBUFS;
330		}
331		if (nam != NULL)
332			unp_disconnect(unp);
333		break;
334	}
335
336	case SOCK_STREAM:
337		/* Connect if not connected yet. */
338		/*
339		 * Note: A better implementation would complain
340		 * if not equal to the peer's address.
341		 */
342		if ((so->so_state & SS_ISCONNECTED) == 0) {
343			if (nam != NULL) {
344				error = unp_connect(so, nam, td);
345				if (error)
346					break;	/* XXX */
347			} else {
348				error = ENOTCONN;
349				break;
350			}
351		}
352
353		if (so->so_state & SS_CANTSENDMORE) {
354			error = EPIPE;
355			break;
356		}
357		if (unp->unp_conn == NULL)
358			panic("uipc_send connected but no connection?");
359		so2 = unp->unp_conn->unp_socket;
360		/*
361		 * Send to paired receive port, and then reduce
362		 * send buffer hiwater marks to maintain backpressure.
363		 * Wake up readers.
364		 */
365		if (control != NULL) {
366			if (sbappendcontrol(&so2->so_rcv, m, control))
367				control = NULL;
368		} else {
369			sbappend(&so2->so_rcv, m);
370		}
371		so->so_snd.sb_mbmax -=
372			so2->so_rcv.sb_mbcnt - unp->unp_conn->unp_mbcnt;
373		unp->unp_conn->unp_mbcnt = so2->so_rcv.sb_mbcnt;
374		newhiwat = so->so_snd.sb_hiwat -
375		    (so2->so_rcv.sb_cc - unp->unp_conn->unp_cc);
376		(void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat,
377		    newhiwat, RLIM_INFINITY);
378		unp->unp_conn->unp_cc = so2->so_rcv.sb_cc;
379		sorwakeup(so2);
380		m = NULL;
381		break;
382
383	default:
384		panic("uipc_send unknown socktype");
385	}
386
387	/*
388	 * SEND_EOF is equivalent to a SEND followed by
389	 * a SHUTDOWN.
390	 */
391	if (flags & PRUS_EOF) {
392		socantsendmore(so);
393		unp_shutdown(unp);
394	}
395
396	if (control != NULL && error != 0)
397		unp_dispose(control);
398
399release:
400	if (control != NULL)
401		m_freem(control);
402	if (m != NULL)
403		m_freem(m);
404	return (error);
405}
406
407static int
408uipc_sense(struct socket *so, struct stat *sb)
409{
410	struct unpcb *unp = sotounpcb(so);
411	struct socket *so2;
412
413	if (unp == NULL)
414		return (EINVAL);
415	sb->st_blksize = so->so_snd.sb_hiwat;
416	if (so->so_type == SOCK_STREAM && unp->unp_conn != NULL) {
417		so2 = unp->unp_conn->unp_socket;
418		sb->st_blksize += so2->so_rcv.sb_cc;
419	}
420	sb->st_dev = NOUDEV;
421	if (unp->unp_ino == 0)
422		unp->unp_ino = (++unp_ino == 0) ? ++unp_ino : unp_ino;
423	sb->st_ino = unp->unp_ino;
424	return (0);
425}
426
427static int
428uipc_shutdown(struct socket *so)
429{
430	struct unpcb *unp = sotounpcb(so);
431
432	if (unp == NULL)
433		return (EINVAL);
434	socantsendmore(so);
435	unp_shutdown(unp);
436	return (0);
437}
438
439static int
440uipc_sockaddr(struct socket *so, struct sockaddr **nam)
441{
442	struct unpcb *unp = sotounpcb(so);
443
444	if (unp == NULL)
445		return (EINVAL);
446	if (unp->unp_addr != NULL)
447		*nam = sodupsockaddr((struct sockaddr *)unp->unp_addr,
448		    M_WAITOK);
449	else
450		*nam = sodupsockaddr((struct sockaddr *)&sun_noname,
451		    M_WAITOK);
452	return (0);
453}
454
455struct pr_usrreqs uipc_usrreqs = {
456	uipc_abort, uipc_accept, uipc_attach, uipc_bind, uipc_connect,
457	uipc_connect2, pru_control_notsupp, uipc_detach, uipc_disconnect,
458	uipc_listen, uipc_peeraddr, uipc_rcvd, pru_rcvoob_notsupp,
459	uipc_send, uipc_sense, uipc_shutdown, uipc_sockaddr,
460	sosend, soreceive, sopoll, pru_sosetlabel_null
461};
462
463int
464uipc_ctloutput(so, sopt)
465	struct socket *so;
466	struct sockopt *sopt;
467{
468	struct unpcb *unp = sotounpcb(so);
469	int error;
470
471	switch (sopt->sopt_dir) {
472	case SOPT_GET:
473		switch (sopt->sopt_name) {
474		case LOCAL_PEERCRED:
475			if (unp->unp_flags & UNP_HAVEPC)
476				error = sooptcopyout(sopt, &unp->unp_peercred,
477				    sizeof(unp->unp_peercred));
478			else {
479				if (so->so_type == SOCK_STREAM)
480					error = ENOTCONN;
481				else
482					error = EINVAL;
483			}
484			break;
485		default:
486			error = EOPNOTSUPP;
487			break;
488		}
489		break;
490	case SOPT_SET:
491	default:
492		error = EOPNOTSUPP;
493		break;
494	}
495	return (error);
496}
497
498/*
499 * Both send and receive buffers are allocated PIPSIZ bytes of buffering
500 * for stream sockets, although the total for sender and receiver is
501 * actually only PIPSIZ.
502 * Datagram sockets really use the sendspace as the maximum datagram size,
503 * and don't really want to reserve the sendspace.  Their recvspace should
504 * be large enough for at least one max-size datagram plus address.
505 */
506#ifndef PIPSIZ
507#define	PIPSIZ	8192
508#endif
509static u_long	unpst_sendspace = PIPSIZ;
510static u_long	unpst_recvspace = PIPSIZ;
511static u_long	unpdg_sendspace = 2*1024;	/* really max datagram size */
512static u_long	unpdg_recvspace = 4*1024;
513
514static int	unp_rights;			/* file descriptors in flight */
515
516SYSCTL_DECL(_net_local_stream);
517SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW,
518	   &unpst_sendspace, 0, "");
519SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW,
520	   &unpst_recvspace, 0, "");
521SYSCTL_DECL(_net_local_dgram);
522SYSCTL_INT(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW,
523	   &unpdg_sendspace, 0, "");
524SYSCTL_INT(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW,
525	   &unpdg_recvspace, 0, "");
526SYSCTL_DECL(_net_local);
527SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, "");
528
529static int
530unp_attach(so)
531	struct socket *so;
532{
533	register struct unpcb *unp;
534	int error;
535
536	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
537		switch (so->so_type) {
538
539		case SOCK_STREAM:
540			error = soreserve(so, unpst_sendspace, unpst_recvspace);
541			break;
542
543		case SOCK_DGRAM:
544			error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
545			break;
546
547		default:
548			panic("unp_attach");
549		}
550		if (error)
551			return (error);
552	}
553	unp = uma_zalloc(unp_zone, M_WAITOK);
554	if (unp == NULL)
555		return (ENOBUFS);
556	bzero(unp, sizeof *unp);
557	unp->unp_gencnt = ++unp_gencnt;
558	unp_count++;
559	LIST_INIT(&unp->unp_refs);
560	unp->unp_socket = so;
561	LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead
562			 : &unp_shead, unp, unp_link);
563	so->so_pcb = unp;
564	return (0);
565}
566
567static void
568unp_detach(unp)
569	register struct unpcb *unp;
570{
571	LIST_REMOVE(unp, unp_link);
572	unp->unp_gencnt = ++unp_gencnt;
573	--unp_count;
574	if (unp->unp_vnode != NULL) {
575		unp->unp_vnode->v_socket = NULL;
576		vrele(unp->unp_vnode);
577		unp->unp_vnode = NULL;
578	}
579	if (unp->unp_conn != NULL)
580		unp_disconnect(unp);
581	while (!LIST_EMPTY(&unp->unp_refs))
582		unp_drop(LIST_FIRST(&unp->unp_refs), ECONNRESET);
583	soisdisconnected(unp->unp_socket);
584	unp->unp_socket->so_pcb = NULL;
585	if (unp_rights) {
586		/*
587		 * Normally the receive buffer is flushed later,
588		 * in sofree, but if our receive buffer holds references
589		 * to descriptors that are now garbage, we will dispose
590		 * of those descriptor references after the garbage collector
591		 * gets them (resulting in a "panic: closef: count < 0").
592		 */
593		sorflush(unp->unp_socket);
594		unp_gc();
595	}
596	if (unp->unp_addr != NULL)
597		FREE(unp->unp_addr, M_SONAME);
598	uma_zfree(unp_zone, unp);
599}
600
601static int
602unp_bind(unp, nam, td)
603	struct unpcb *unp;
604	struct sockaddr *nam;
605	struct thread *td;
606{
607	struct sockaddr_un *soun = (struct sockaddr_un *)nam;
608	struct vnode *vp;
609	struct mount *mp;
610	struct vattr vattr;
611	int error, namelen;
612	struct nameidata nd;
613	char *buf;
614
615	if (unp->unp_vnode != NULL)
616		return (EINVAL);
617
618	namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
619	if (namelen <= 0)
620		return (EINVAL);
621
622	buf = malloc(namelen + 1, M_TEMP, M_WAITOK);
623	strlcpy(buf, soun->sun_path, namelen + 1);
624
625restart:
626	NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, UIO_SYSSPACE,
627	    buf, td);
628/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
629	error = namei(&nd);
630	if (error) {
631		free(buf, M_TEMP);
632		return (error);
633	}
634	vp = nd.ni_vp;
635	if (vp != NULL || vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
636		NDFREE(&nd, NDF_ONLY_PNBUF);
637		if (nd.ni_dvp == vp)
638			vrele(nd.ni_dvp);
639		else
640			vput(nd.ni_dvp);
641		if (vp != NULL) {
642			vrele(vp);
643			free(buf, M_TEMP);
644			return (EADDRINUSE);
645		}
646		error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH);
647		if (error) {
648			free(buf, M_TEMP);
649			return (error);
650		}
651		goto restart;
652	}
653	VATTR_NULL(&vattr);
654	vattr.va_type = VSOCK;
655	vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask);
656#ifdef MAC
657	error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
658	    &vattr);
659#endif
660	if (error == 0) {
661		VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
662		error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
663	}
664	NDFREE(&nd, NDF_ONLY_PNBUF);
665	vput(nd.ni_dvp);
666	if (error) {
667		free(buf, M_TEMP);
668		return (error);
669	}
670	vp = nd.ni_vp;
671	vp->v_socket = unp->unp_socket;
672	unp->unp_vnode = vp;
673	unp->unp_addr = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK);
674	VOP_UNLOCK(vp, 0, td);
675	vn_finished_write(mp);
676	free(buf, M_TEMP);
677	return (0);
678}
679
680static int
681unp_connect(so, nam, td)
682	struct socket *so;
683	struct sockaddr *nam;
684	struct thread *td;
685{
686	register struct sockaddr_un *soun = (struct sockaddr_un *)nam;
687	register struct vnode *vp;
688	register struct socket *so2, *so3;
689	struct unpcb *unp, *unp2, *unp3;
690	int error, len;
691	struct nameidata nd;
692	char buf[SOCK_MAXADDRLEN];
693
694	len = nam->sa_len - offsetof(struct sockaddr_un, sun_path);
695	if (len <= 0)
696		return (EINVAL);
697	strlcpy(buf, soun->sun_path, len + 1);
698
699	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, buf, td);
700	error = namei(&nd);
701	if (error)
702		return (error);
703	vp = nd.ni_vp;
704	NDFREE(&nd, NDF_ONLY_PNBUF);
705	if (vp->v_type != VSOCK) {
706		error = ENOTSOCK;
707		goto bad;
708	}
709	error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td);
710	if (error)
711		goto bad;
712	so2 = vp->v_socket;
713	if (so2 == NULL) {
714		error = ECONNREFUSED;
715		goto bad;
716	}
717	if (so->so_type != so2->so_type) {
718		error = EPROTOTYPE;
719		goto bad;
720	}
721	if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
722		if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
723		    (so3 = sonewconn(so2, 0)) == NULL) {
724			error = ECONNREFUSED;
725			goto bad;
726		}
727		unp = sotounpcb(so);
728		unp2 = sotounpcb(so2);
729		unp3 = sotounpcb(so3);
730		if (unp2->unp_addr != NULL)
731			unp3->unp_addr = (struct sockaddr_un *)
732			    sodupsockaddr((struct sockaddr *)unp2->unp_addr,
733			    M_WAITOK);
734
735		/*
736		 * unp_peercred management:
737		 *
738		 * The connecter's (client's) credentials are copied
739		 * from its process structure at the time of connect()
740		 * (which is now).
741		 */
742		cru2x(td->td_ucred, &unp3->unp_peercred);
743		unp3->unp_flags |= UNP_HAVEPC;
744		/*
745		 * The receiver's (server's) credentials are copied
746		 * from the unp_peercred member of socket on which the
747		 * former called listen(); unp_listen() cached that
748		 * process's credentials at that time so we can use
749		 * them now.
750		 */
751		KASSERT(unp2->unp_flags & UNP_HAVEPCCACHED,
752		    ("unp_connect: listener without cached peercred"));
753		memcpy(&unp->unp_peercred, &unp2->unp_peercred,
754		    sizeof(unp->unp_peercred));
755		unp->unp_flags |= UNP_HAVEPC;
756#ifdef MAC
757		mac_set_socket_peer_from_socket(so, so3);
758		mac_set_socket_peer_from_socket(so3, so);
759#endif
760
761		so2 = so3;
762	}
763	error = unp_connect2(so, so2);
764bad:
765	vput(vp);
766	return (error);
767}
768
769static int
770unp_connect2(so, so2)
771	register struct socket *so;
772	register struct socket *so2;
773{
774	register struct unpcb *unp = sotounpcb(so);
775	register struct unpcb *unp2;
776
777	if (so2->so_type != so->so_type)
778		return (EPROTOTYPE);
779	unp2 = sotounpcb(so2);
780	unp->unp_conn = unp2;
781	switch (so->so_type) {
782
783	case SOCK_DGRAM:
784		LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink);
785		soisconnected(so);
786		break;
787
788	case SOCK_STREAM:
789		unp2->unp_conn = unp;
790		soisconnected(so);
791		soisconnected(so2);
792		break;
793
794	default:
795		panic("unp_connect2");
796	}
797	return (0);
798}
799
800static void
801unp_disconnect(unp)
802	struct unpcb *unp;
803{
804	register struct unpcb *unp2 = unp->unp_conn;
805
806	if (unp2 == NULL)
807		return;
808	unp->unp_conn = NULL;
809	switch (unp->unp_socket->so_type) {
810
811	case SOCK_DGRAM:
812		LIST_REMOVE(unp, unp_reflink);
813		unp->unp_socket->so_state &= ~SS_ISCONNECTED;
814		break;
815
816	case SOCK_STREAM:
817		soisdisconnected(unp->unp_socket);
818		unp2->unp_conn = NULL;
819		soisdisconnected(unp2->unp_socket);
820		break;
821	}
822}
823
824#ifdef notdef
825void
826unp_abort(unp)
827	struct unpcb *unp;
828{
829
830	unp_detach(unp);
831}
832#endif
833
834static int
835unp_pcblist(SYSCTL_HANDLER_ARGS)
836{
837	int error, i, n;
838	struct unpcb *unp, **unp_list;
839	unp_gen_t gencnt;
840	struct xunpgen *xug;
841	struct unp_head *head;
842	struct xunpcb *xu;
843
844	head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead);
845
846	/*
847	 * The process of preparing the PCB list is too time-consuming and
848	 * resource-intensive to repeat twice on every request.
849	 */
850	if (req->oldptr == NULL) {
851		n = unp_count;
852		req->oldidx = 2 * (sizeof *xug)
853			+ (n + n/8) * sizeof(struct xunpcb);
854		return (0);
855	}
856
857	if (req->newptr != NULL)
858		return (EPERM);
859
860	/*
861	 * OK, now we're committed to doing something.
862	 */
863	xug = malloc(sizeof(*xug), M_TEMP, M_WAITOK);
864	gencnt = unp_gencnt;
865	n = unp_count;
866
867	xug->xug_len = sizeof *xug;
868	xug->xug_count = n;
869	xug->xug_gen = gencnt;
870	xug->xug_sogen = so_gencnt;
871	error = SYSCTL_OUT(req, xug, sizeof *xug);
872	if (error) {
873		free(xug, M_TEMP);
874		return (error);
875	}
876
877	unp_list = malloc(n * sizeof *unp_list, M_TEMP, M_WAITOK);
878
879	for (unp = LIST_FIRST(head), i = 0; unp && i < n;
880	     unp = LIST_NEXT(unp, unp_link)) {
881		if (unp->unp_gencnt <= gencnt) {
882			if (cr_cansee(req->td->td_ucred,
883			    unp->unp_socket->so_cred))
884				continue;
885			unp_list[i++] = unp;
886		}
887	}
888	n = i;			/* in case we lost some during malloc */
889
890	error = 0;
891	xu = malloc(sizeof(*xu), M_TEMP, M_WAITOK);
892	for (i = 0; i < n; i++) {
893		unp = unp_list[i];
894		if (unp->unp_gencnt <= gencnt) {
895			xu->xu_len = sizeof *xu;
896			xu->xu_unpp = unp;
897			/*
898			 * XXX - need more locking here to protect against
899			 * connect/disconnect races for SMP.
900			 */
901			if (unp->unp_addr != NULL)
902				bcopy(unp->unp_addr, &xu->xu_addr,
903				      unp->unp_addr->sun_len);
904			if (unp->unp_conn != NULL &&
905			    unp->unp_conn->unp_addr != NULL)
906				bcopy(unp->unp_conn->unp_addr,
907				      &xu->xu_caddr,
908				      unp->unp_conn->unp_addr->sun_len);
909			bcopy(unp, &xu->xu_unp, sizeof *unp);
910			sotoxsocket(unp->unp_socket, &xu->xu_socket);
911			error = SYSCTL_OUT(req, xu, sizeof *xu);
912		}
913	}
914	free(xu, M_TEMP);
915	if (!error) {
916		/*
917		 * Give the user an updated idea of our state.
918		 * If the generation differs from what we told
919		 * her before, she knows that something happened
920		 * while we were processing this request, and it
921		 * might be necessary to retry.
922		 */
923		xug->xug_gen = unp_gencnt;
924		xug->xug_sogen = so_gencnt;
925		xug->xug_count = unp_count;
926		error = SYSCTL_OUT(req, xug, sizeof *xug);
927	}
928	free(unp_list, M_TEMP);
929	free(xug, M_TEMP);
930	return (error);
931}
932
933SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist, CTLFLAG_RD,
934	    (caddr_t)(long)SOCK_DGRAM, 0, unp_pcblist, "S,xunpcb",
935	    "List of active local datagram sockets");
936SYSCTL_PROC(_net_local_stream, OID_AUTO, pcblist, CTLFLAG_RD,
937	    (caddr_t)(long)SOCK_STREAM, 0, unp_pcblist, "S,xunpcb",
938	    "List of active local stream sockets");
939
940static void
941unp_shutdown(unp)
942	struct unpcb *unp;
943{
944	struct socket *so;
945
946	if (unp->unp_socket->so_type == SOCK_STREAM && unp->unp_conn &&
947	    (so = unp->unp_conn->unp_socket))
948		socantrcvmore(so);
949}
950
951static void
952unp_drop(unp, errno)
953	struct unpcb *unp;
954	int errno;
955{
956	struct socket *so = unp->unp_socket;
957
958	so->so_error = errno;
959	unp_disconnect(unp);
960}
961
962#ifdef notdef
963void
964unp_drain()
965{
966
967}
968#endif
969
970static void
971unp_freerights(rp, fdcount)
972	struct file **rp;
973	int fdcount;
974{
975	int i;
976	struct file *fp;
977
978	for (i = 0; i < fdcount; i++) {
979		fp = *rp;
980		/*
981		 * zero the pointer before calling
982		 * unp_discard since it may end up
983		 * in unp_gc()..
984		 */
985		*rp++ = 0;
986		unp_discard(fp);
987	}
988}
989
990int
991unp_externalize(control, controlp)
992	struct mbuf *control, **controlp;
993{
994	struct thread *td = curthread;		/* XXX */
995	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
996	int i;
997	int *fdp;
998	struct file **rp;
999	struct file *fp;
1000	void *data;
1001	socklen_t clen = control->m_len, datalen;
1002	int error, newfds;
1003	int f;
1004	u_int newlen;
1005
1006	error = 0;
1007	if (controlp != NULL) /* controlp == NULL => free control messages */
1008		*controlp = NULL;
1009
1010	while (cm != NULL) {
1011		if (sizeof(*cm) > clen || cm->cmsg_len > clen) {
1012			error = EINVAL;
1013			break;
1014		}
1015
1016		data = CMSG_DATA(cm);
1017		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1018
1019		if (cm->cmsg_level == SOL_SOCKET
1020		    && cm->cmsg_type == SCM_RIGHTS) {
1021			newfds = datalen / sizeof(struct file *);
1022			rp = data;
1023
1024			/* If we're not outputting the descriptors free them. */
1025			if (error || controlp == NULL) {
1026				unp_freerights(rp, newfds);
1027				goto next;
1028			}
1029			FILEDESC_LOCK(td->td_proc->p_fd);
1030			/* if the new FD's will not fit free them.  */
1031			if (!fdavail(td, newfds)) {
1032				FILEDESC_UNLOCK(td->td_proc->p_fd);
1033				error = EMSGSIZE;
1034				unp_freerights(rp, newfds);
1035				goto next;
1036			}
1037			/*
1038			 * now change each pointer to an fd in the global
1039			 * table to an integer that is the index to the
1040			 * local fd table entry that we set up to point
1041			 * to the global one we are transferring.
1042			 */
1043			newlen = newfds * sizeof(int);
1044			*controlp = sbcreatecontrol(NULL, newlen,
1045			    SCM_RIGHTS, SOL_SOCKET);
1046			if (*controlp == NULL) {
1047				FILEDESC_UNLOCK(td->td_proc->p_fd);
1048				error = E2BIG;
1049				unp_freerights(rp, newfds);
1050				goto next;
1051			}
1052
1053			fdp = (int *)
1054			    CMSG_DATA(mtod(*controlp, struct cmsghdr *));
1055			for (i = 0; i < newfds; i++) {
1056				if (fdalloc(td, 0, &f))
1057					panic("unp_externalize fdalloc failed");
1058				fp = *rp++;
1059				td->td_proc->p_fd->fd_ofiles[f] = fp;
1060				FILE_LOCK(fp);
1061				fp->f_msgcount--;
1062				FILE_UNLOCK(fp);
1063				unp_rights--;
1064				*fdp++ = f;
1065			}
1066			FILEDESC_UNLOCK(td->td_proc->p_fd);
1067		} else { /* We can just copy anything else across */
1068			if (error || controlp == NULL)
1069				goto next;
1070			*controlp = sbcreatecontrol(NULL, datalen,
1071			    cm->cmsg_type, cm->cmsg_level);
1072			if (*controlp == NULL) {
1073				error = ENOBUFS;
1074				goto next;
1075			}
1076			bcopy(data,
1077			    CMSG_DATA(mtod(*controlp, struct cmsghdr *)),
1078			    datalen);
1079		}
1080
1081		controlp = &(*controlp)->m_next;
1082
1083next:
1084		if (CMSG_SPACE(datalen) < clen) {
1085			clen -= CMSG_SPACE(datalen);
1086			cm = (struct cmsghdr *)
1087			    ((caddr_t)cm + CMSG_SPACE(datalen));
1088		} else {
1089			clen = 0;
1090			cm = NULL;
1091		}
1092	}
1093
1094	m_freem(control);
1095
1096	return (error);
1097}
1098
1099void
1100unp_init(void)
1101{
1102	unp_zone = uma_zcreate("unpcb", sizeof(struct unpcb), NULL, NULL,
1103	    NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
1104	if (unp_zone == NULL)
1105		panic("unp_init");
1106	uma_zone_set_max(unp_zone, nmbclusters);
1107	LIST_INIT(&unp_dhead);
1108	LIST_INIT(&unp_shead);
1109}
1110
1111static int
1112unp_internalize(controlp, td)
1113	struct mbuf **controlp;
1114	struct thread *td;
1115{
1116	struct mbuf *control = *controlp;
1117	struct proc *p = td->td_proc;
1118	struct filedesc *fdescp = p->p_fd;
1119	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1120	struct cmsgcred *cmcred;
1121	struct file **rp;
1122	struct file *fp;
1123	struct timeval *tv;
1124	int i, fd, *fdp;
1125	void *data;
1126	socklen_t clen = control->m_len, datalen;
1127	int error, oldfds;
1128	u_int newlen;
1129
1130	error = 0;
1131	*controlp = NULL;
1132
1133	while (cm != NULL) {
1134		if (sizeof(*cm) > clen || cm->cmsg_level != SOL_SOCKET
1135		    || cm->cmsg_len > clen) {
1136			error = EINVAL;
1137			goto out;
1138		}
1139
1140		data = CMSG_DATA(cm);
1141		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1142
1143		switch (cm->cmsg_type) {
1144		/*
1145		 * Fill in credential information.
1146		 */
1147		case SCM_CREDS:
1148			*controlp = sbcreatecontrol(NULL, sizeof(*cmcred),
1149			    SCM_CREDS, SOL_SOCKET);
1150			if (*controlp == NULL) {
1151				error = ENOBUFS;
1152				goto out;
1153			}
1154
1155			cmcred = (struct cmsgcred *)
1156			    CMSG_DATA(mtod(*controlp, struct cmsghdr *));
1157			cmcred->cmcred_pid = p->p_pid;
1158			cmcred->cmcred_uid = td->td_ucred->cr_ruid;
1159			cmcred->cmcred_gid = td->td_ucred->cr_rgid;
1160			cmcred->cmcred_euid = td->td_ucred->cr_uid;
1161			cmcred->cmcred_ngroups = MIN(td->td_ucred->cr_ngroups,
1162							CMGROUP_MAX);
1163			for (i = 0; i < cmcred->cmcred_ngroups; i++)
1164				cmcred->cmcred_groups[i] =
1165				    td->td_ucred->cr_groups[i];
1166			break;
1167
1168		case SCM_RIGHTS:
1169			oldfds = datalen / sizeof (int);
1170			/*
1171			 * check that all the FDs passed in refer to legal files
1172			 * If not, reject the entire operation.
1173			 */
1174			fdp = data;
1175			FILEDESC_LOCK(fdescp);
1176			for (i = 0; i < oldfds; i++) {
1177				fd = *fdp++;
1178				if ((unsigned)fd >= fdescp->fd_nfiles ||
1179				    fdescp->fd_ofiles[fd] == NULL) {
1180					FILEDESC_UNLOCK(fdescp);
1181					error = EBADF;
1182					goto out;
1183				}
1184				fp = fdescp->fd_ofiles[fd];
1185				if (!(fp->f_ops->fo_flags & DFLAG_PASSABLE)) {
1186					FILEDESC_UNLOCK(fdescp);
1187					error = EOPNOTSUPP;
1188					goto out;
1189				}
1190
1191			}
1192			/*
1193			 * Now replace the integer FDs with pointers to
1194			 * the associated global file table entry..
1195			 */
1196			newlen = oldfds * sizeof(struct file *);
1197			*controlp = sbcreatecontrol(NULL, newlen,
1198			    SCM_RIGHTS, SOL_SOCKET);
1199			if (*controlp == NULL) {
1200				FILEDESC_UNLOCK(fdescp);
1201				error = E2BIG;
1202				goto out;
1203			}
1204
1205			fdp = data;
1206			rp = (struct file **)
1207			    CMSG_DATA(mtod(*controlp, struct cmsghdr *));
1208			for (i = 0; i < oldfds; i++) {
1209				fp = fdescp->fd_ofiles[*fdp++];
1210				*rp++ = fp;
1211				FILE_LOCK(fp);
1212				fp->f_count++;
1213				fp->f_msgcount++;
1214				FILE_UNLOCK(fp);
1215				unp_rights++;
1216			}
1217			FILEDESC_UNLOCK(fdescp);
1218			break;
1219
1220		case SCM_TIMESTAMP:
1221			*controlp = sbcreatecontrol(NULL, sizeof(*tv),
1222			    SCM_TIMESTAMP, SOL_SOCKET);
1223			if (*controlp == NULL) {
1224				error = ENOBUFS;
1225				goto out;
1226			}
1227			tv = (struct timeval *)
1228			    CMSG_DATA(mtod(*controlp, struct cmsghdr *));
1229			microtime(tv);
1230			break;
1231
1232		default:
1233			error = EINVAL;
1234			goto out;
1235		}
1236
1237		controlp = &(*controlp)->m_next;
1238
1239		if (CMSG_SPACE(datalen) < clen) {
1240			clen -= CMSG_SPACE(datalen);
1241			cm = (struct cmsghdr *)
1242			    ((caddr_t)cm + CMSG_SPACE(datalen));
1243		} else {
1244			clen = 0;
1245			cm = NULL;
1246		}
1247	}
1248
1249out:
1250	m_freem(control);
1251
1252	return (error);
1253}
1254
1255static int	unp_defer, unp_gcing;
1256
1257static void
1258unp_gc()
1259{
1260	register struct file *fp, *nextfp;
1261	register struct socket *so;
1262	struct file **extra_ref, **fpp;
1263	int nunref, i;
1264
1265	if (unp_gcing)
1266		return;
1267	unp_gcing = 1;
1268	unp_defer = 0;
1269	/*
1270	 * before going through all this, set all FDs to
1271	 * be NOT defered and NOT externally accessible
1272	 */
1273	sx_slock(&filelist_lock);
1274	LIST_FOREACH(fp, &filehead, f_list)
1275		fp->f_gcflag &= ~(FMARK|FDEFER);
1276	do {
1277		LIST_FOREACH(fp, &filehead, f_list) {
1278			FILE_LOCK(fp);
1279			/*
1280			 * If the file is not open, skip it
1281			 */
1282			if (fp->f_count == 0) {
1283				FILE_UNLOCK(fp);
1284				continue;
1285			}
1286			/*
1287			 * If we already marked it as 'defer'  in a
1288			 * previous pass, then try process it this time
1289			 * and un-mark it
1290			 */
1291			if (fp->f_gcflag & FDEFER) {
1292				fp->f_gcflag &= ~FDEFER;
1293				unp_defer--;
1294			} else {
1295				/*
1296				 * if it's not defered, then check if it's
1297				 * already marked.. if so skip it
1298				 */
1299				if (fp->f_gcflag & FMARK) {
1300					FILE_UNLOCK(fp);
1301					continue;
1302				}
1303				/*
1304				 * If all references are from messages
1305				 * in transit, then skip it. it's not
1306				 * externally accessible.
1307				 */
1308				if (fp->f_count == fp->f_msgcount) {
1309					FILE_UNLOCK(fp);
1310					continue;
1311				}
1312				/*
1313				 * If it got this far then it must be
1314				 * externally accessible.
1315				 */
1316				fp->f_gcflag |= FMARK;
1317			}
1318			/*
1319			 * either it was defered, or it is externally
1320			 * accessible and not already marked so.
1321			 * Now check if it is possibly one of OUR sockets.
1322			 */
1323			if (fp->f_type != DTYPE_SOCKET ||
1324			    (so = fp->f_data) == NULL) {
1325				FILE_UNLOCK(fp);
1326				continue;
1327			}
1328			FILE_UNLOCK(fp);
1329			if (so->so_proto->pr_domain != &localdomain ||
1330			    (so->so_proto->pr_flags&PR_RIGHTS) == 0)
1331				continue;
1332#ifdef notdef
1333			if (so->so_rcv.sb_flags & SB_LOCK) {
1334				/*
1335				 * This is problematical; it's not clear
1336				 * we need to wait for the sockbuf to be
1337				 * unlocked (on a uniprocessor, at least),
1338				 * and it's also not clear what to do
1339				 * if sbwait returns an error due to receipt
1340				 * of a signal.  If sbwait does return
1341				 * an error, we'll go into an infinite
1342				 * loop.  Delete all of this for now.
1343				 */
1344				(void) sbwait(&so->so_rcv);
1345				goto restart;
1346			}
1347#endif
1348			/*
1349			 * So, Ok, it's one of our sockets and it IS externally
1350			 * accessible (or was defered). Now we look
1351			 * to see if we hold any file descriptors in its
1352			 * message buffers. Follow those links and mark them
1353			 * as accessible too.
1354			 */
1355			unp_scan(so->so_rcv.sb_mb, unp_mark);
1356		}
1357	} while (unp_defer);
1358	sx_sunlock(&filelist_lock);
1359	/*
1360	 * We grab an extra reference to each of the file table entries
1361	 * that are not otherwise accessible and then free the rights
1362	 * that are stored in messages on them.
1363	 *
1364	 * The bug in the orginal code is a little tricky, so I'll describe
1365	 * what's wrong with it here.
1366	 *
1367	 * It is incorrect to simply unp_discard each entry for f_msgcount
1368	 * times -- consider the case of sockets A and B that contain
1369	 * references to each other.  On a last close of some other socket,
1370	 * we trigger a gc since the number of outstanding rights (unp_rights)
1371	 * is non-zero.  If during the sweep phase the gc code un_discards,
1372	 * we end up doing a (full) closef on the descriptor.  A closef on A
1373	 * results in the following chain.  Closef calls soo_close, which
1374	 * calls soclose.   Soclose calls first (through the switch
1375	 * uipc_usrreq) unp_detach, which re-invokes unp_gc.  Unp_gc simply
1376	 * returns because the previous instance had set unp_gcing, and
1377	 * we return all the way back to soclose, which marks the socket
1378	 * with SS_NOFDREF, and then calls sofree.  Sofree calls sorflush
1379	 * to free up the rights that are queued in messages on the socket A,
1380	 * i.e., the reference on B.  The sorflush calls via the dom_dispose
1381	 * switch unp_dispose, which unp_scans with unp_discard.  This second
1382	 * instance of unp_discard just calls closef on B.
1383	 *
1384	 * Well, a similar chain occurs on B, resulting in a sorflush on B,
1385	 * which results in another closef on A.  Unfortunately, A is already
1386	 * being closed, and the descriptor has already been marked with
1387	 * SS_NOFDREF, and soclose panics at this point.
1388	 *
1389	 * Here, we first take an extra reference to each inaccessible
1390	 * descriptor.  Then, we call sorflush ourself, since we know
1391	 * it is a Unix domain socket anyhow.  After we destroy all the
1392	 * rights carried in messages, we do a last closef to get rid
1393	 * of our extra reference.  This is the last close, and the
1394	 * unp_detach etc will shut down the socket.
1395	 *
1396	 * 91/09/19, bsy@cs.cmu.edu
1397	 */
1398	extra_ref = malloc(nfiles * sizeof(struct file *), M_TEMP, M_WAITOK);
1399	sx_slock(&filelist_lock);
1400	for (nunref = 0, fp = LIST_FIRST(&filehead), fpp = extra_ref;
1401	    fp != NULL; fp = nextfp) {
1402		nextfp = LIST_NEXT(fp, f_list);
1403		FILE_LOCK(fp);
1404		/*
1405		 * If it's not open, skip it
1406		 */
1407		if (fp->f_count == 0) {
1408			FILE_UNLOCK(fp);
1409			continue;
1410		}
1411		/*
1412		 * If all refs are from msgs, and it's not marked accessible
1413		 * then it must be referenced from some unreachable cycle
1414		 * of (shut-down) FDs, so include it in our
1415		 * list of FDs to remove
1416		 */
1417		if (fp->f_count == fp->f_msgcount && !(fp->f_gcflag & FMARK)) {
1418			*fpp++ = fp;
1419			nunref++;
1420			fp->f_count++;
1421		}
1422		FILE_UNLOCK(fp);
1423	}
1424	sx_sunlock(&filelist_lock);
1425	/*
1426	 * for each FD on our hit list, do the following two things
1427	 */
1428	for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) {
1429		struct file *tfp = *fpp;
1430		FILE_LOCK(tfp);
1431		if (tfp->f_type == DTYPE_SOCKET &&
1432		    tfp->f_data != NULL) {
1433			FILE_UNLOCK(tfp);
1434			sorflush(tfp->f_data);
1435		} else {
1436			FILE_UNLOCK(tfp);
1437		}
1438	}
1439	for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
1440		closef(*fpp, (struct thread *) NULL);
1441	free(extra_ref, M_TEMP);
1442	unp_gcing = 0;
1443}
1444
1445void
1446unp_dispose(m)
1447	struct mbuf *m;
1448{
1449
1450	if (m)
1451		unp_scan(m, unp_discard);
1452}
1453
1454static int
1455unp_listen(unp, td)
1456	struct unpcb *unp;
1457	struct thread *td;
1458{
1459
1460	cru2x(td->td_ucred, &unp->unp_peercred);
1461	unp->unp_flags |= UNP_HAVEPCCACHED;
1462	return (0);
1463}
1464
1465static void
1466unp_scan(m0, op)
1467	register struct mbuf *m0;
1468	void (*op)(struct file *);
1469{
1470	struct mbuf *m;
1471	struct file **rp;
1472	struct cmsghdr *cm;
1473	void *data;
1474	int i;
1475	socklen_t clen, datalen;
1476	int qfds;
1477
1478	while (m0 != NULL) {
1479		for (m = m0; m; m = m->m_next) {
1480			if (m->m_type != MT_CONTROL)
1481				continue;
1482
1483			cm = mtod(m, struct cmsghdr *);
1484			clen = m->m_len;
1485
1486			while (cm != NULL) {
1487				if (sizeof(*cm) > clen || cm->cmsg_len > clen)
1488					break;
1489
1490				data = CMSG_DATA(cm);
1491				datalen = (caddr_t)cm + cm->cmsg_len
1492				    - (caddr_t)data;
1493
1494				if (cm->cmsg_level == SOL_SOCKET &&
1495				    cm->cmsg_type == SCM_RIGHTS) {
1496					qfds = datalen / sizeof (struct file *);
1497					rp = data;
1498					for (i = 0; i < qfds; i++)
1499						(*op)(*rp++);
1500				}
1501
1502				if (CMSG_SPACE(datalen) < clen) {
1503					clen -= CMSG_SPACE(datalen);
1504					cm = (struct cmsghdr *)
1505					    ((caddr_t)cm + CMSG_SPACE(datalen));
1506				} else {
1507					clen = 0;
1508					cm = NULL;
1509				}
1510			}
1511		}
1512		m0 = m0->m_act;
1513	}
1514}
1515
1516static void
1517unp_mark(fp)
1518	struct file *fp;
1519{
1520	if (fp->f_gcflag & FMARK)
1521		return;
1522	unp_defer++;
1523	fp->f_gcflag |= (FMARK|FDEFER);
1524}
1525
1526static void
1527unp_discard(fp)
1528	struct file *fp;
1529{
1530	FILE_LOCK(fp);
1531	fp->f_msgcount--;
1532	unp_rights--;
1533	FILE_UNLOCK(fp);
1534	(void) closef(fp, (struct thread *)NULL);
1535}
1536