Example #1
0
int
sys_socketpair(struct lwp *l, const struct sys_socketpair_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(int)		domain;
		syscallarg(int)		type;
		syscallarg(int)		protocol;
		syscallarg(int *)	rsv;
	} */
	file_t		*fp1, *fp2;
	struct socket	*so1, *so2;
	int		fd, error, sv[2];
	proc_t		*p = curproc;
	int		flags = SCARG(uap, type) & SOCK_FLAGS_MASK;
	int		type = SCARG(uap, type) & ~SOCK_FLAGS_MASK;
	int		domain = SCARG(uap, domain);
	int		proto = SCARG(uap, protocol);

	error = makesocket(l, &fp1, &fd, flags, type, domain, proto, NULL);
	if (error)
		return error;
	so1 = fp1->f_socket;
	sv[0] = fd;

	error = makesocket(l, &fp2, &fd, flags, type, domain, proto, so1);
	if (error)
		goto out;
	so2 = fp2->f_socket;
	sv[1] = fd;

	solock(so1);
	error = soconnect2(so1, so2);
	if (error == 0 && type == SOCK_DGRAM) {
		/*
		 * Datagram socket connection is asymmetric.
		 */
		error = soconnect2(so2, so1);
	}
	sounlock(so1);

	if (error == 0)
		error = copyout(sv, SCARG(uap, rsv), sizeof(sv));
	if (error == 0) {
		fd_affix(p, fp2, sv[1]);
		fd_affix(p, fp1, sv[0]);
		return 0;
	}
	fd_abort(p, fp2, sv[1]);
	(void)soclose(so2);
out:
	fd_abort(p, fp1, sv[0]);
	(void)soclose(so1);
	return error;
}
Example #2
0
int
sys_socketpair(struct proc *p, void *v, register_t *retval)
{
	struct sys_socketpair_args /* {
		syscallarg(int) domain;
		syscallarg(int) type;
		syscallarg(int) protocol;
		syscallarg(int *) rsv;
	} */ *uap = v;
	struct filedesc *fdp = p->p_fd;
	struct file *fp1, *fp2;
	struct socket *so1, *so2;
	int fd, error, sv[2];

	error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
	    SCARG(uap, protocol));
	if (error)
		return (error);
	error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
	    SCARG(uap, protocol));
	if (error)
		goto free1;

	fdplock(fdp);
	if ((error = falloc(p, &fp1, &fd)) != 0)
		goto free2;
	sv[0] = fd;
	fp1->f_flag = FREAD|FWRITE;
	fp1->f_type = DTYPE_SOCKET;
	fp1->f_ops = &socketops;
	fp1->f_data = so1;
	if ((error = falloc(p, &fp2, &fd)) != 0)
		goto free3;
	fp2->f_flag = FREAD|FWRITE;
	fp2->f_type = DTYPE_SOCKET;
	fp2->f_ops = &socketops;
	fp2->f_data = so2;
	sv[1] = fd;
	if ((error = soconnect2(so1, so2)) != 0)
		goto free4;
	if (SCARG(uap, type) == SOCK_DGRAM) {
		/*
		 * Datagram socket connection is asymmetric.
		 */
		 if ((error = soconnect2(so2, so1)) != 0)
			goto free4;
	}
	error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int));
	if (error == 0) {
		FILE_SET_MATURE(fp1, p);
		FILE_SET_MATURE(fp2, p);
		fdpunlock(fdp);
		return (0);
	}
free4:
	fdremove(fdp, sv[1]);
	closef(fp2, p);
	so2 = NULL;
free3:
	fdremove(fdp, sv[0]);
	closef(fp1, p);
	so1 = NULL;
free2:
	if (so2 != NULL)
		(void)soclose(so2);
	fdpunlock(fdp);
free1:
	if (so1 != NULL)
		(void)soclose(so1);
	return (error);
}
Example #3
0
/* ARGSUSED */
int
fifo_open(struct vnop_open_args *ap)
{
	struct vnode *vp = ap->a_vp;
	struct fifoinfo *fip;
	struct socket *rso, *wso;
	int error;

	vnode_lock(vp);

retry:

	fip = vp->v_fifoinfo;

	if (fip == (struct fifoinfo *)0)
		panic("fifo_open with no fifoinfo");

	if ((fip->fi_flags & FIFO_CREATED) == 0) {
		if (fip->fi_flags & FIFO_INCREATE) {
			fip->fi_flags |= FIFO_CREATEWAIT;	
			error = msleep(&fip->fi_flags, &vp->v_lock, PRIBIO | PCATCH, "fifocreatewait", NULL);
			if (error) {
				vnode_unlock(vp);
				return(error);
			}
			goto retry;
		} else {
			fip->fi_flags |= FIFO_INCREATE;	
			vnode_unlock(vp);
			if ( (error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) ) {
			        goto bad1;
			}

			if ( (error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) ) {
				(void)soclose(rso);
			        goto bad1;
			}

			if ( (error = soconnect2(wso, rso)) ) {
				(void)soclose(wso);
				(void)soclose(rso);
			        goto bad1;
			}
			fip->fi_readers = fip->fi_writers = 0;

			/* Lock ordering between wso and rso does not matter here 
		 	 * because they are just created and no one has a reference to them
		 	 */
	        	socket_lock(wso, 1);
			wso->so_state |= SS_CANTRCVMORE;
			wso->so_snd.sb_lowat = PIPE_BUF;
	        	socket_unlock(wso, 1);

	        	socket_lock(rso, 1);
			rso->so_state |= SS_CANTSENDMORE;
	        	socket_unlock(rso, 1);

			vnode_lock(vp);
			fip->fi_readsock = rso;
			fip->fi_writesock = wso;

			fip->fi_flags |= FIFO_CREATED;
			fip->fi_flags &= ~FIFO_INCREATE;
			
			if ((fip->fi_flags & FIFO_CREATEWAIT)) {
				fip->fi_flags &= ~FIFO_CREATEWAIT;
				wakeup(&fip->fi_flags);
			}
			/* vnode lock is held  to process further */
		}
	}

	/* vnode is locked at this point */
	/* fifo in created already */
	if (ap->a_mode & FREAD) {
		fip->fi_readers++;
		if (fip->fi_readers == 1) {
			socket_lock(fip->fi_writesock, 1);
			fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
			socket_unlock(fip->fi_writesock, 1);

			if (fip->fi_writers > 0)
				wakeup((caddr_t)&fip->fi_writers);
		}
	}
	if (ap->a_mode & FWRITE) {
		fip->fi_writers++;
		if (fip->fi_writers == 1) {
			socket_lock(fip->fi_readsock, 1);
			fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
			socket_unlock(fip->fi_readsock, 1);
	
			if (fip->fi_readers > 0)
				wakeup((caddr_t)&fip->fi_readers);
		}
	}
	if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
		if (fip->fi_writers == 0) {
			error = msleep((caddr_t)&fip->fi_readers, &vp->v_lock,
					PCATCH | PSOCK, "fifoor", NULL);
			if (error)
				goto bad;
			if (fip->fi_readers == 1) {
				if (fip->fi_writers > 0)
					wakeup((caddr_t)&fip->fi_writers);
			}
		}
	}
	if (ap->a_mode & FWRITE) {
		if (ap->a_mode & O_NONBLOCK) {
			if (fip->fi_readers == 0) {
					error = ENXIO;
					goto bad;
			}
		} else {
			if (fip->fi_readers == 0) {
				error = msleep((caddr_t)&fip->fi_writers,&vp->v_lock,
						PCATCH | PSOCK, "fifoow", NULL);
				if (error)
					goto bad;
				if (fip->fi_writers == 1) {
					if (fip->fi_readers > 0)
						wakeup((caddr_t)&fip->fi_readers);
				}
			}
		}
	}

	vnode_unlock(vp);
	return (0);
bad:
	fifo_close_internal(vp, ap->a_mode, ap->a_context, 1);

	vnode_unlock(vp);
	return (error);
bad1:
	vnode_lock(vp);

	fip->fi_flags &= ~FIFO_INCREATE;
			
	if ((fip->fi_flags & FIFO_CREATEWAIT)) {
		fip->fi_flags &= ~FIFO_CREATEWAIT;
		wakeup(&fip->fi_flags);
	}
	vnode_unlock(vp);

	return (error);
}