示例#1
0
static int
portal_connect(struct socket *so, struct socket *so2)
{
	/* from unp_connect, bypassing the namei stuff... */
	struct socket *so3;
	struct unpcb *unp2;
	struct unpcb *unp3;

	if (so2 == 0)
		return (ECONNREFUSED);

	if (so->so_type != so2->so_type)
		return (EPROTOTYPE);

	if ((so2->so_options & SO_ACCEPTCONN) == 0)
		return (ECONNREFUSED);

	if ((so3 = sonewconn(so2, 0)) == 0)
		return (ECONNREFUSED);

	unp2 = so2->so_pcb;
	unp3 = so3->so_pcb;
	if (unp2->unp_addr)
		unp3->unp_addr = (struct sockaddr_un *)
			dup_sockaddr((struct sockaddr *)unp2->unp_addr);
	so2 = so3;

	return (unp_connect2(so, so2));
}
示例#2
0
static int
uipc_connect2(struct socket *so1, struct socket *so2)
{
	struct unpcb *unp = sotounpcb(so1);

	if (unp == 0)
		return EINVAL;

	return unp_connect2(so1, so2);
}
示例#3
0
int
pipe1(struct lwp *l, register_t *retval, int flags)
{
	file_t		*rf, *wf;
	struct socket	*rso, *wso;
	int		fd, error;
	proc_t		*p;

	if (flags & ~(O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE))
		return EINVAL;
	p = curproc;
	if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0)
		return error;
	if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso)) != 0)
		goto free1;
	/* remember this socket pair implements a pipe */
	wso->so_state |= SS_ISAPIPE;
	rso->so_state |= SS_ISAPIPE;
	if ((error = fd_allocfile(&rf, &fd)) != 0)
		goto free2;
	retval[0] = fd;
	rf->f_flag = FREAD | flags;
	rf->f_type = DTYPE_SOCKET;
	rf->f_ops = &socketops;
	rf->f_socket = rso;
	if ((error = fd_allocfile(&wf, &fd)) != 0)
		goto free3;
	wf->f_flag = FWRITE | flags;
	wf->f_type = DTYPE_SOCKET;
	wf->f_ops = &socketops;
	wf->f_socket = wso;
	retval[1] = fd;
	solock(wso);
	error = unp_connect2(wso, rso);
	sounlock(wso);
	if (error != 0)
		goto free4;
	fd_affix(p, wf, (int)retval[1]);
	fd_affix(p, rf, (int)retval[0]);
	return (0);
 free4:
	fd_abort(p, wf, (int)retval[1]);
 free3:
	fd_abort(p, rf, (int)retval[0]);
 free2:
	(void)soclose(wso);
 free1:
	(void)soclose(rso);
	return error;
}
示例#4
0
/*
 * Open called to set up a new instance of a fifo or
 * to find an active instance of a fifo.
 */
static int
fifo_open(void *v)
{
    struct vop_open_args /* {
		struct vnode	*a_vp;
		int		a_mode;
		kauth_cred_t	a_cred;
	} */ *ap = v;
    struct lwp	*l = curlwp;
    struct vnode	*vp;
    struct fifoinfo	*fip;
    struct socket	*rso, *wso;
    int		error;

    vp = ap->a_vp;
    KASSERT(VOP_ISLOCKED(vp));

    if ((fip = vp->v_fifoinfo) == NULL) {
        fip = kmem_alloc(sizeof(*fip), KM_SLEEP);
        error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL);
        if (error != 0) {
            kmem_free(fip, sizeof(*fip));
            return (error);
        }
        fip->fi_readsock = rso;
        error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso);
        if (error != 0) {
            (void)soclose(rso);
            kmem_free(fip, sizeof(*fip));
            return (error);
        }
        fip->fi_writesock = wso;
        solock(wso);
        if ((error = unp_connect2(wso, rso, PRU_CONNECT2)) != 0) {
            sounlock(wso);
            (void)soclose(wso);
            (void)soclose(rso);
            kmem_free(fip, sizeof(*fip));
            return (error);
        }
        fip->fi_readers = 0;
        fip->fi_writers = 0;
        wso->so_state |= SS_CANTRCVMORE;
        rso->so_state |= SS_CANTSENDMORE;
        cv_init(&fip->fi_rcv, "fiford");
        cv_init(&fip->fi_wcv, "fifowr");
        vp->v_fifoinfo = fip;
    } else {
        wso = fip->fi_writesock;
        rso = fip->fi_readsock;
        solock(wso);
    }

    if (ap->a_mode & FREAD) {
        if (fip->fi_readers++ == 0) {
            wso->so_state &= ~SS_CANTSENDMORE;
            cv_broadcast(&fip->fi_wcv);
        }
    }
    if (ap->a_mode & FWRITE) {
        if (fip->fi_writers++ == 0) {
            rso->so_state &= ~SS_CANTRCVMORE;
            cv_broadcast(&fip->fi_rcv);
        }
    }
    if (ap->a_mode & FREAD) {
        if (ap->a_mode & O_NONBLOCK) {
        } else {
            while (!soreadable(rso) && fip->fi_writers == 0) {
                VOP_UNLOCK(vp);
                error = cv_wait_sig(&fip->fi_rcv,
                                    wso->so_lock);
                sounlock(wso);
                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                if (error)
                    goto bad;
                solock(wso);
            }
        }
    }
    if (ap->a_mode & FWRITE) {
        if (ap->a_mode & O_NONBLOCK) {
            if (fip->fi_readers == 0) {
                error = ENXIO;
                sounlock(wso);
                goto bad;
            }
        } else {
            while (fip->fi_readers == 0) {
                VOP_UNLOCK(vp);
                error = cv_wait_sig(&fip->fi_wcv,
                                    wso->so_lock);
                sounlock(wso);
                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                if (error)
                    goto bad;
                solock(wso);
            }
        }
    }
    sounlock(wso);
    return (0);
bad:
    VOP_CLOSE(vp, ap->a_mode, ap->a_cred);
    return (error);
}
示例#5
0
/* ARGSUSED */
int
fifo_open(void *v)
{
	struct vop_open_args *ap = v;
	struct vnode *vp = ap->a_vp;
	struct fifoinfo *fip;
	struct proc *p = ap->a_p;
	struct socket *rso, *wso;
	int error;

	if ((fip = vp->v_fifoinfo) == NULL) {
		fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK);
		vp->v_fifoinfo = fip;
		if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0) {
			free(fip, M_VNODE);
			vp->v_fifoinfo = NULL;
			return (error);
		}
		fip->fi_readsock = rso;
		if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0) {
			(void)soclose(rso);
			free(fip, M_VNODE);
			vp->v_fifoinfo = NULL;
			return (error);
		}
		fip->fi_writesock = wso;
		if ((error = unp_connect2(wso, rso)) != 0) {
			(void)soclose(wso);
			(void)soclose(rso);
			free(fip, M_VNODE);
			vp->v_fifoinfo = NULL;
			return (error);
		}
		fip->fi_readers = fip->fi_writers = 0;
		wso->so_snd.sb_lowat = PIPE_BUF;
		rso->so_state |= SS_CANTRCVMORE;
	}
	if (ap->a_mode & FREAD) {
		fip->fi_readers++;
		if (fip->fi_readers == 1) {
			fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
			if (fip->fi_writers > 0)
				wakeup(&fip->fi_writers);
		}
	}
	if (ap->a_mode & FWRITE) {
		fip->fi_writers++;
		if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
			error = ENXIO;
			goto bad;
		}
		if (fip->fi_writers == 1) {
			fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
			if (fip->fi_readers > 0)
				wakeup(&fip->fi_readers);
		}
	}
	if ((ap->a_mode & O_NONBLOCK) == 0) {
		if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
			VOP_UNLOCK(vp, 0, p);
			error = tsleep(&fip->fi_readers,
			    PCATCH | PSOCK, "fifor", 0);
			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
			if (error)
				goto bad;
		}
		if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
			VOP_UNLOCK(vp, 0, p);
			error = tsleep(&fip->fi_writers,
			    PCATCH | PSOCK, "fifow", 0);
			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
			if (error)
				goto bad;
		}
	}
	return (0);
bad:
	VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
	return (error);
}