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

📄 uipc_syscalls.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1982, 1986, 1989, 1990, 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_syscalls.c	8.4 (Berkeley) 2/21/94 */#include <sys/param.h>#include <sys/filedesc.h>#include <sys/proc.h>#include <sys/file.h>#include <sys/buf.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/protosw.h>#include <sys/socket.h>#include <sys/socketvar.h>#ifdef KTRACE#include <sys/ktrace.h>#endif/* * System call interface to the socket abstraction. */#if defined(COMPAT_43) || defined(COMPAT_SUNOS)#define COMPAT_OLDSOCK#endifextern	struct fileops socketops;struct socket_args {	int	domain;	int	type;	int	protocol;};socket(p, uap, retval)	struct proc *p;	register struct socket_args *uap;	int *retval;{	struct filedesc *fdp = p->p_fd;	struct socket *so;	struct file *fp;	int fd, error;	if (error = falloc(p, &fp, &fd))		return (error);	fp->f_flag = FREAD|FWRITE;	fp->f_type = DTYPE_SOCKET;	fp->f_ops = &socketops;	if (error = socreate(uap->domain, &so, uap->type, uap->protocol)) {		fdp->fd_ofiles[fd] = 0;		ffree(fp);	} else {		fp->f_data = (caddr_t)so;		*retval = fd;	}	return (error);}struct bind_args {	int	s;	caddr_t	name;	int	namelen;};/* ARGSUSED */bind(p, uap, retval)	struct proc *p;	register struct bind_args *uap;	int *retval;{	struct file *fp;	struct mbuf *nam;	int error;	if (error = getsock(p->p_fd, uap->s, &fp))		return (error);	if (error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME))		return (error);	error = sobind((struct socket *)fp->f_data, nam);	m_freem(nam);	return (error);}struct listen_args {	int	s;	int	backlog;};/* ARGSUSED */listen(p, uap, retval)	struct proc *p;	register struct listen_args *uap;	int *retval;{	struct file *fp;	int error;	if (error = getsock(p->p_fd, uap->s, &fp))		return (error);	return (solisten((struct socket *)fp->f_data, uap->backlog));}struct accept_args {	int	s;	caddr_t	name;	int	*anamelen;#ifdef COMPAT_OLDSOCK	int	compat_43;	/* pseudo */#endif};#ifdef COMPAT_OLDSOCKaccept(p, uap, retval)	struct proc *p;	struct accept_args *uap;	int *retval;{	uap->compat_43 = 0;	return (accept1(p, uap, retval));}oaccept(p, uap, retval)	struct proc *p;	struct accept_args *uap;	int *retval;{	uap->compat_43 = 1;	return (accept1(p, uap, retval));}#else /* COMPAT_OLDSOCK */#define	accept1	accept#endifaccept1(p, uap, retval)	struct proc *p;	register struct accept_args *uap;	int *retval;{	struct file *fp;	struct mbuf *nam;	int namelen, error, s;	register struct socket *so;	if (uap->name && (error = copyin((caddr_t)uap->anamelen,	    (caddr_t)&namelen, sizeof (namelen))))		return (error);	if (error = getsock(p->p_fd, uap->s, &fp))		return (error);	s = splnet();	so = (struct socket *)fp->f_data;	if ((so->so_options & SO_ACCEPTCONN) == 0) {		splx(s);		return (EINVAL);	}	if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {		splx(s);		return (EWOULDBLOCK);	}	while (so->so_qlen == 0 && so->so_error == 0) {		if (so->so_state & SS_CANTRCVMORE) {			so->so_error = ECONNABORTED;			break;		}		if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,		    netcon, 0)) {			splx(s);			return (error);		}	}	if (so->so_error) {		error = so->so_error;		so->so_error = 0;		splx(s);		return (error);	}	if (error = falloc(p, &fp, retval)) {		splx(s);		return (error);	}	{ struct socket *aso = so->so_q;	  if (soqremque(aso, 1) == 0)		panic("accept");	  so = aso;	}	fp->f_type = DTYPE_SOCKET;	fp->f_flag = FREAD|FWRITE;	fp->f_ops = &socketops;	fp->f_data = (caddr_t)so;	nam = m_get(M_WAIT, MT_SONAME);	(void) soaccept(so, nam);	if (uap->name) {#ifdef COMPAT_OLDSOCK		if (uap->compat_43)			mtod(nam, struct osockaddr *)->sa_family =			    mtod(nam, struct sockaddr *)->sa_family;#endif		if (namelen > nam->m_len)			namelen = nam->m_len;		/* SHOULD COPY OUT A CHAIN HERE */		if ((error = copyout(mtod(nam, caddr_t), (caddr_t)uap->name,		    (u_int)namelen)) == 0)			error = copyout((caddr_t)&namelen,			    (caddr_t)uap->anamelen, sizeof (*uap->anamelen));	}	m_freem(nam);	splx(s);	return (error);}struct connect_args {	int	s;	caddr_t	name;	int	namelen;};/* ARGSUSED */connect(p, uap, retval)	struct proc *p;	register struct connect_args *uap;	int *retval;{	struct file *fp;	register struct socket *so;	struct mbuf *nam;	int error, s;	if (error = getsock(p->p_fd, uap->s, &fp))		return (error);	so = (struct socket *)fp->f_data;	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))		return (EALREADY);	if (error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME))		return (error);	error = soconnect(so, nam);	if (error)		goto bad;	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {		m_freem(nam);		return (EINPROGRESS);	}	s = splnet();	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)		if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,		    netcon, 0))			break;	if (error == 0) {		error = so->so_error;		so->so_error = 0;	}	splx(s);bad:	so->so_state &= ~SS_ISCONNECTING;	m_freem(nam);	if (error == ERESTART)		error = EINTR;	return (error);}struct socketpair_args {	int	domain;	int	type;	int	protocol;	int	*rsv;};socketpair(p, uap, retval)	struct proc *p;	register struct socketpair_args *uap;	int retval[];{	register struct filedesc *fdp = p->p_fd;	struct file *fp1, *fp2;	struct socket *so1, *so2;	int fd, error, sv[2];	if (error = socreate(uap->domain, &so1, uap->type, uap->protocol))		return (error);	if (error = socreate(uap->domain, &so2, uap->type, uap->protocol))		goto free1;	if (error = falloc(p, &fp1, &fd))		goto free2;	sv[0] = fd;	fp1->f_flag = FREAD|FWRITE;	fp1->f_type = DTYPE_SOCKET;	fp1->f_ops = &socketops;	fp1->f_data = (caddr_t)so1;	if (error = falloc(p, &fp2, &fd))		goto free3;	fp2->f_flag = FREAD|FWRITE;	fp2->f_type = DTYPE_SOCKET;	fp2->f_ops = &socketops;	fp2->f_data = (caddr_t)so2;	sv[1] = fd;	if (error = soconnect2(so1, so2))		goto free4;	if (uap->type == SOCK_DGRAM) {		/*		 * Datagram socket connection is asymmetric.		 */		 if (error = soconnect2(so2, so1))			goto free4;	}	error = copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));	retval[0] = sv[0];		/* XXX ??? */	retval[1] = sv[1];		/* XXX ??? */	return (error);free4:	ffree(fp2);	fdp->fd_ofiles[sv[1]] = 0;free3:	ffree(fp1);	fdp->fd_ofiles[sv[0]] = 0;free2:	(void)soclose(so2);free1:	(void)soclose(so1);	return (error);}struct sendto_args {	int	s;	caddr_t	buf;	size_t	len;	int	flags;	caddr_t	to;	int	tolen;};sendto(p, uap, retval)	struct proc *p;	register struct sendto_args *uap;	int *retval;{	struct msghdr msg;	struct iovec aiov;	msg.msg_name = uap->to;	msg.msg_namelen = uap->tolen;	msg.msg_iov = &aiov;	msg.msg_iovlen = 1;	msg.msg_control = 0;#ifdef COMPAT_OLDSOCK	msg.msg_flags = 0;#endif	aiov.iov_base = uap->buf;	aiov.iov_len = uap->len;	return (sendit(p, uap->s, &msg, uap->flags, retval));}#ifdef COMPAT_OLDSOCKstruct osend_args {	int	s;	caddr_t	buf;	int	len;	int	flags;};osend(p, uap, retval)	struct proc *p;	register struct osend_args *uap;	int *retval;{	struct msghdr msg;	struct iovec aiov;	msg.msg_name = 0;	msg.msg_namelen = 0;	msg.msg_iov = &aiov;	msg.msg_iovlen = 1;	aiov.iov_base = uap->buf;	aiov.iov_len = uap->len;	msg.msg_control = 0;	msg.msg_flags = 0;	return (sendit(p, uap->s, &msg, uap->flags, retval));}#define MSG_COMPAT	0x8000struct osendmsg_args {	int	s;	caddr_t	msg;	int	flags;};osendmsg(p, uap, retval)	struct proc *p;	register struct osendmsg_args *uap;	int *retval;{	struct msghdr msg;	struct iovec aiov[UIO_SMALLIOV], *iov;	int error;	if (error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr)))		return (error);	if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {		if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)			return (EMSGSIZE);		MALLOC(iov, struct iovec *,		      sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 		      M_WAITOK);	} else		iov = aiov;	if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,	    (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))		goto done;	msg.msg_flags = MSG_COMPAT;	msg.msg_iov = iov;	error = sendit(p, uap->s, &msg, uap->flags, retval);done:	if (iov != aiov)		FREE(iov, M_IOV);	return (error);}#endifstruct sendmsg_args {	int	s;	caddr_t	msg;	int	flags;};sendmsg(p, uap, retval)	struct proc *p;	register struct sendmsg_args *uap;	int *retval;{	struct msghdr msg;	struct iovec aiov[UIO_SMALLIOV], *iov;	int error;	if (error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)))		return (error);	if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {		if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)			return (EMSGSIZE);		MALLOC(iov, struct iovec *,		       sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,		       M_WAITOK);	} else		iov = aiov;	if (msg.msg_iovlen &&	    (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,	    (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))		goto done;	msg.msg_iov = iov;#ifdef COMPAT_OLDSOCK	msg.msg_flags = 0;#endif	error = sendit(p, uap->s, &msg, uap->flags, retval);done:	if (iov != aiov)		FREE(iov, M_IOV);	return (error);}sendit(p, s, mp, flags, retsize)	register struct proc *p;	int s;	register struct msghdr *mp;	int flags, *retsize;{	struct file *fp;	struct uio auio;	register struct iovec *iov;	register int i;	struct mbuf *to, *control;	int len, error;#ifdef KTRACE	struct iovec *ktriov = NULL;#endif		if (error = getsock(p->p_fd, s, &fp))		return (error);	auio.uio_iov = mp->msg_iov;	auio.uio_iovcnt = mp->msg_iovlen;	auio.uio_segflg = UIO_USERSPACE;	auio.uio_rw = UIO_WRITE;	auio.uio_procp = p;	auio.uio_offset = 0;			/* XXX */	auio.uio_resid = 0;	iov = mp->msg_iov;	for (i = 0; i < mp->msg_iovlen; i++, iov++) {		if (iov->iov_len < 0)			return (EINVAL);		if ((auio.uio_resid += iov->iov_len) < 0)			return (EINVAL);	}	if (mp->msg_name) {		if (error = sockargs(&to, mp->msg_name, mp->msg_namelen,		    MT_SONAME))			return (error);	} else		to = 0;	if (mp->msg_control) {		if (mp->msg_controllen < sizeof(struct cmsghdr)#ifdef COMPAT_OLDSOCK		    && mp->msg_flags != MSG_COMPAT#endif		) {			error = EINVAL;			goto bad;		}		if (error = sockargs(&control, mp->msg_control,		    mp->msg_controllen, MT_CONTROL))			goto bad;#ifdef COMPAT_OLDSOCK		if (mp->msg_flags == MSG_COMPAT) {			register struct cmsghdr *cm;			M_PREPEND(control, sizeof(*cm), M_WAIT);			if (control == 0) {				error = ENOBUFS;				goto bad;			} else {				cm = mtod(control, struct cmsghdr *);				cm->cmsg_len = control->m_len;				cm->cmsg_level = SOL_SOCKET;				cm->cmsg_type = SCM_RIGHTS;			}		}#endif	} else		control = 0;#ifdef KTRACE	if (KTRPOINT(p, KTR_GENIO)) {		int iovlen = auio.uio_iovcnt * sizeof (struct iovec);		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);	}#endif	len = auio.uio_resid;	if (error = sosend((struct socket *)fp->f_data, to, &auio,	    (struct mbuf *)0, control, flags)) {		if (auio.uio_resid != len && (error == ERESTART ||		    error == EINTR || error == EWOULDBLOCK))			error = 0;		if (error == EPIPE)			psignal(p, SIGPIPE);	}	if (error == 0)		*retsize = len - auio.uio_resid;#ifdef KTRACE	if (ktriov != NULL) {		if (error == 0)			ktrgenio(p->p_tracep, s, UIO_WRITE,				ktriov, *retsize, error);		FREE(ktriov, M_TEMP);	}#endifbad:	if (to)		m_freem(to);	return (error);}struct recvfrom_args {	int	s;	caddr_t	buf;	size_t	len;	int	flags;	caddr_t	from;	int	*fromlenaddr;};#ifdef COMPAT_OLDSOCKorecvfrom(p, uap, retval)	struct proc *p;	struct recvfrom_args *uap;	int *retval;{	uap->flags |= MSG_COMPAT;	return (recvfrom(p, uap, retval));}#endifrecvfrom(p, uap, retval)	struct proc *p;	register struct recvfrom_args *uap;	int *retval;{	struct msghdr msg;	struct iovec aiov;

⌨️ 快捷键说明

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