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)); }
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); }
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; }
/* * 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); }
/* 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); }