⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uipc_usrreq.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1982, 1986, 1989, 1991, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)uipc_usrreq.c	8.3 (Berkeley) 1/4/94 */#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/filedesc.h>#include <sys/domain.h>#include <sys/protosw.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/unpcb.h>#include <sys/un.h>#include <sys/namei.h>#include <sys/vnode.h>#include <sys/file.h>#include <sys/stat.h>#include <sys/mbuf.h>/* * Unix communications domain. * * TODO: *	SEQPACKET, RDM *	rethink name space problems *	need a proper out-of-band */struct	sockaddr sun_noname = { sizeof(sun_noname), AF_UNIX };ino_t	unp_ino;			/* prototype for fake inode numbers *//*ARGSUSED*/uipc_usrreq(so, req, m, nam, control)	struct socket *so;	int req;	struct mbuf *m, *nam, *control;{	struct unpcb *unp = sotounpcb(so);	register struct socket *so2;	register int error = 0;	struct proc *p = curproc;	/* XXX */	if (req == PRU_CONTROL)		return (EOPNOTSUPP);	if (req != PRU_SEND && control && control->m_len) {		error = EOPNOTSUPP;		goto release;	}	if (unp == 0 && req != PRU_ATTACH) {		error = EINVAL;		goto release;	}	switch (req) {	case PRU_ATTACH:		if (unp) {			error = EISCONN;			break;		}		error = unp_attach(so);		break;	case PRU_DETACH:		unp_detach(unp);		break;	case PRU_BIND:		error = unp_bind(unp, nam, p);		break;	case PRU_LISTEN:		if (unp->unp_vnode == 0)			error = EINVAL;		break;	case PRU_CONNECT:		error = unp_connect(so, nam, p);		break;	case PRU_CONNECT2:		error = unp_connect2(so, (struct socket *)nam);		break;	case PRU_DISCONNECT:		unp_disconnect(unp);		break;	case PRU_ACCEPT:		/*		 * Pass back name of connected socket,		 * if it was bound and we are still connected		 * (our peer may have closed already!).		 */		if (unp->unp_conn && unp->unp_conn->unp_addr) {			nam->m_len = unp->unp_conn->unp_addr->m_len;			bcopy(mtod(unp->unp_conn->unp_addr, caddr_t),			    mtod(nam, caddr_t), (unsigned)nam->m_len);		} else {			nam->m_len = sizeof(sun_noname);			*(mtod(nam, struct sockaddr *)) = sun_noname;		}		break;	case PRU_SHUTDOWN:		socantsendmore(so);		unp_shutdown(unp);		break;	case PRU_RCVD:		switch (so->so_type) {		case SOCK_DGRAM:			panic("uipc 1");			/*NOTREACHED*/		case SOCK_STREAM:#define	rcv (&so->so_rcv)#define snd (&so2->so_snd)			if (unp->unp_conn == 0)				break;			so2 = unp->unp_conn->unp_socket;			/*			 * Adjust backpressure on sender			 * and wakeup any waiting to write.			 */			snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt;			unp->unp_mbcnt = rcv->sb_mbcnt;			snd->sb_hiwat += unp->unp_cc - rcv->sb_cc;			unp->unp_cc = rcv->sb_cc;			sowwakeup(so2);#undef snd#undef rcv			break;		default:			panic("uipc 2");		}		break;	case PRU_SEND:		if (control && (error = unp_internalize(control, p)))			break;		switch (so->so_type) {		case SOCK_DGRAM: {			struct sockaddr *from;			if (nam) {				if (unp->unp_conn) {					error = EISCONN;					break;				}				error = unp_connect(so, nam, p);				if (error)					break;			} else {				if (unp->unp_conn == 0) {					error = ENOTCONN;					break;				}			}			so2 = unp->unp_conn->unp_socket;			if (unp->unp_addr)				from = mtod(unp->unp_addr, struct sockaddr *);			else				from = &sun_noname;			if (sbappendaddr(&so2->so_rcv, from, m, control)) {				sorwakeup(so2);				m = 0;				control = 0;			} else				error = ENOBUFS;			if (nam)				unp_disconnect(unp);			break;		}		case SOCK_STREAM:#define	rcv (&so2->so_rcv)#define	snd (&so->so_snd)			if (so->so_state & SS_CANTSENDMORE) {				error = EPIPE;				break;			}			if (unp->unp_conn == 0)				panic("uipc 3");			so2 = unp->unp_conn->unp_socket;			/*			 * Send to paired receive port, and then reduce			 * send buffer hiwater marks to maintain backpressure.			 * Wake up readers.			 */			if (control) {				if (sbappendcontrol(rcv, m, control))					control = 0;			} else				sbappend(rcv, m);			snd->sb_mbmax -=			    rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt;			unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt;			snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc;			unp->unp_conn->unp_cc = rcv->sb_cc;			sorwakeup(so2);			m = 0;#undef snd#undef rcv			break;		default:			panic("uipc 4");		}		break;	case PRU_ABORT:		unp_drop(unp, ECONNABORTED);		break;	case PRU_SENSE:		((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat;		if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) {			so2 = unp->unp_conn->unp_socket;			((struct stat *) m)->st_blksize += so2->so_rcv.sb_cc;		}		((struct stat *) m)->st_dev = NODEV;		if (unp->unp_ino == 0)			unp->unp_ino = unp_ino++;		((struct stat *) m)->st_ino = unp->unp_ino;		return (0);	case PRU_RCVOOB:		return (EOPNOTSUPP);	case PRU_SENDOOB:		error = EOPNOTSUPP;		break;	case PRU_SOCKADDR:		if (unp->unp_addr) {			nam->m_len = unp->unp_addr->m_len;			bcopy(mtod(unp->unp_addr, caddr_t),			    mtod(nam, caddr_t), (unsigned)nam->m_len);		} else			nam->m_len = 0;		break;	case PRU_PEERADDR:		if (unp->unp_conn && unp->unp_conn->unp_addr) {			nam->m_len = unp->unp_conn->unp_addr->m_len;			bcopy(mtod(unp->unp_conn->unp_addr, caddr_t),			    mtod(nam, caddr_t), (unsigned)nam->m_len);		} else			nam->m_len = 0;		break;	case PRU_SLOWTIMO:		break;	default:		panic("piusrreq");	}release:	if (control)		m_freem(control);	if (m)		m_freem(m);	return (error);}/* * Both send and receive buffers are allocated PIPSIZ bytes of buffering * for stream sockets, although the total for sender and receiver is * actually only PIPSIZ. * Datagram sockets really use the sendspace as the maximum datagram size, * and don't really want to reserve the sendspace.  Their recvspace should * be large enough for at least one max-size datagram plus address. */#define	PIPSIZ	4096u_long	unpst_sendspace = PIPSIZ;u_long	unpst_recvspace = PIPSIZ;u_long	unpdg_sendspace = 2*1024;	/* really max datagram size */u_long	unpdg_recvspace = 4*1024;int	unp_rights;			/* file descriptors in flight */unp_attach(so)	struct socket *so;{	register struct mbuf *m;	register struct unpcb *unp;	int error;		if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {		switch (so->so_type) {		case SOCK_STREAM:			error = soreserve(so, unpst_sendspace, unpst_recvspace);			break;		case SOCK_DGRAM:			error = soreserve(so, unpdg_sendspace, unpdg_recvspace);			break;		default:			panic("unp_attach");		}		if (error)			return (error);	}	m = m_getclr(M_DONTWAIT, MT_PCB);	if (m == NULL)		return (ENOBUFS);	unp = mtod(m, struct unpcb *);	so->so_pcb = (caddr_t)unp;	unp->unp_socket = so;	return (0);}unp_detach(unp)	register struct unpcb *unp;{		if (unp->unp_vnode) {		unp->unp_vnode->v_socket = 0;		vrele(unp->unp_vnode);		unp->unp_vnode = 0;	}	if (unp->unp_conn)		unp_disconnect(unp);	while (unp->unp_refs)		unp_drop(unp->unp_refs, ECONNRESET);	soisdisconnected(unp->unp_socket);	unp->unp_socket->so_pcb = 0;	m_freem(unp->unp_addr);	(void) m_free(dtom(unp));	if (unp_rights) {		/*		 * Normally the receive buffer is flushed later,		 * in sofree, but if our receive buffer holds references		 * to descriptors that are now garbage, we will dispose		 * of those descriptor references after the garbage collector		 * gets them (resulting in a "panic: closef: count < 0").		 */		sorflush(unp->unp_socket);		unp_gc();	}}unp_bind(unp, nam, p)	struct unpcb *unp;	struct mbuf *nam;	struct proc *p;{	struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);	register struct vnode *vp;	struct vattr vattr;	int error;	struct nameidata nd;	NDINIT(&nd, CREATE, FOLLOW | LOCKPARENT, UIO_SYSSPACE,		soun->sun_path, p);	if (unp->unp_vnode != NULL)		return (EINVAL);	if (nam->m_len == MLEN) {		if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0)			return (EINVAL);	} else		*(mtod(nam, caddr_t) + nam->m_len) = 0;/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */	if (error = namei(&nd))		return (error);	vp = nd.ni_vp;	if (vp != NULL) {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		vrele(vp);		return (EADDRINUSE);	}	VATTR_NULL(&vattr);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -