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