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