diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/sys_socket.c | 50 | ||||
-rw-r--r-- | sys/kern/uipc_domain.c | 7 | ||||
-rw-r--r-- | sys/kern/uipc_proto.c | 11 | ||||
-rw-r--r-- | sys/kern/uipc_sockbuf.c | 13 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 83 | ||||
-rw-r--r-- | sys/kern/uipc_socket2.c | 13 | ||||
-rw-r--r-- | sys/kern/uipc_syscalls.c | 22 | ||||
-rw-r--r-- | sys/kern/uipc_usrreq.c | 517 |
8 files changed, 411 insertions, 305 deletions
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index c3e6615..0c3b495 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93 - * $Id: sys_socket.c,v 1.11 1997/03/23 03:36:25 bde Exp $ + * $Id: sys_socket.c,v 1.12 1997/03/24 11:52:26 bde Exp $ */ #include <sys/param.h> @@ -68,9 +68,8 @@ soo_read(fp, uio, cred) struct uio *uio; struct ucred *cred; { - - return (soreceive((struct socket *)fp->f_data, (struct mbuf **)0, - uio, (struct mbuf **)0, (struct mbuf **)0, (int *)0)); + struct socket *so = (struct socket *)fp->f_data; + return so->so_proto->pr_usrreqs->pru_soreceive(so, 0, uio, 0, 0, 0); } /* ARGSUSED */ @@ -80,9 +79,8 @@ soo_write(fp, uio, cred) struct uio *uio; struct ucred *cred; { - - return (sosend((struct socket *)fp->f_data, (struct mbuf *)0, - uio, (struct mbuf *)0, (struct mbuf *)0, 0)); + struct socket *so = (struct socket *)fp->f_data; + return so->so_proto->pr_usrreqs->pru_sosend(so, 0, uio, 0, 0, 0); } int @@ -140,7 +138,7 @@ soo_ioctl(fp, cmd, data, p) return (ifioctl(so, cmd, data, p)); if (IOCGROUP(cmd) == 'r') return (rtioctl(cmd, data, p)); - return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, 0)); + return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, 0, p)); } int @@ -149,40 +147,8 @@ soo_select(fp, which, p) int which; struct proc *p; { - register struct socket *so = (struct socket *)fp->f_data; - register int s = splnet(); - - switch (which) { - - case FREAD: - if (soreadable(so)) { - splx(s); - return (1); - } - selrecord(p, &so->so_rcv.sb_sel); - so->so_rcv.sb_flags |= SB_SEL; - break; - - case FWRITE: - if (sowriteable(so)) { - splx(s); - return (1); - } - selrecord(p, &so->so_snd.sb_sel); - so->so_snd.sb_flags |= SB_SEL; - break; - - case 0: - if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) { - splx(s); - return (1); - } - selrecord(p, &so->so_rcv.sb_sel); - so->so_rcv.sb_flags |= SB_SEL; - break; - } - splx(s); - return (0); + struct socket *so = (struct socket *)fp->f_data; + return so->so_proto->pr_usrreqs->pru_soselect(so, which, p); } int diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c index a2c3477..c2ec35f 100644 --- a/sys/kern/uipc_domain.c +++ b/sys/kern/uipc_domain.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_domain.c 8.2 (Berkeley) 10/18/93 - * $Id$ + * $Id: uipc_domain.c,v 1.16 1997/02/22 09:39:27 peter Exp $ */ #include <sys/param.h> @@ -108,6 +108,11 @@ domaininit(dummy) /* See comments in uipc_socket2.c. */ if (pr->pr_usrreqs == 0 && pr->pr_ousrreq) pr->pr_usrreqs = &pru_oldstyle; +#else + if (pr->pr_usrreqs == 0) + panic("domaininit: %ssw[%d] has no usrreqs!", + dp->dom_name, + (int)(pr - dp->dom_protosw)); #endif if (pr->pr_init) (*pr->pr_init)(); diff --git a/sys/kern/uipc_proto.c b/sys/kern/uipc_proto.c index 664373c..bcd918c 100644 --- a/sys/kern/uipc_proto.c +++ b/sys/kern/uipc_proto.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_proto.c 8.1 (Berkeley) 6/10/93 - * $Id: uipc_proto.c,v 1.10 1997/02/24 20:30:55 wollman Exp $ + * $Id: uipc_proto.c,v 1.11 1997/04/14 18:23:48 phk Exp $ */ #include <sys/param.h> @@ -53,18 +53,21 @@ static struct protosw localsw[] = { { SOCK_STREAM, &localdomain, 0, PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS, 0, 0, 0, 0, - uipc_usrreq, + 0, 0, 0, 0, 0, + &uipc_usrreqs }, { SOCK_DGRAM, &localdomain, 0, PR_ATOMIC|PR_ADDR|PR_RIGHTS, 0, 0, 0, 0, - uipc_usrreq, + 0, 0, 0, 0, 0, + &uipc_usrreqs }, { 0, 0, 0, 0, 0, 0, raw_ctlinput, 0, - raw_usrreq, + 0, raw_init, 0, 0, 0, + &raw_usrreqs } }; diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index 4bddd1a..f31cc98 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 - * $Id: uipc_socket2.c,v 1.22 1997/02/24 20:30:57 wollman Exp $ + * $Id: uipc_socket2.c,v 1.23 1997/03/31 12:29:59 davidg Exp $ */ #include <sys/param.h> @@ -220,7 +220,7 @@ sonewconn1(head, connstatus) so->so_pgid = head->so_pgid; (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat); - if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0)) { + if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, curproc)) { /*XXX*/ (void) free((caddr_t)so, M_SOCKET); return ((struct socket *)0); } @@ -975,7 +975,14 @@ pru_connect2_notsupp(struct socket *so1, struct socket *so2) } int -pru_listen_notsupp(struct socket *so) +pru_control_notsupp(struct socket *so, int cmd, caddr_t data, + struct ifnet *ifp, struct proc *p) +{ + return EOPNOTSUPP; +} + +int +pru_listen_notsupp(struct socket *so, struct proc *p) { return EOPNOTSUPP; } diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 9f70207..095f764 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94 - * $Id: uipc_socket.c,v 1.24 1997/02/24 20:30:56 wollman Exp $ + * $Id: uipc_socket.c,v 1.25 1997/03/23 03:36:31 bde Exp $ */ #include <sys/param.h> @@ -78,7 +78,7 @@ socreate(dom, aso, type, proto, p) prp = pffindproto(dom, proto, type); else prp = pffindtype(dom, type); - if (prp == 0 || prp->pr_usrreqs == 0) + if (prp == 0 || prp->pr_usrreqs->pru_attach == 0) return (EPROTONOSUPPORT); if (prp->pr_type != type) return (EPROTOTYPE); @@ -87,10 +87,8 @@ socreate(dom, aso, type, proto, p) TAILQ_INIT(&so->so_incomp); TAILQ_INIT(&so->so_comp); so->so_type = type; - if (p->p_ucred->cr_uid == 0) - so->so_state = SS_PRIV; so->so_proto = prp; - error = (*prp->pr_usrreqs->pru_attach)(so, proto); + error = (*prp->pr_usrreqs->pru_attach)(so, proto, p); if (error) { so->so_state |= SS_NOFDREF; sofree(so); @@ -101,26 +99,28 @@ socreate(dom, aso, type, proto, p) } int -sobind(so, nam) +sobind(so, nam, p) struct socket *so; struct mbuf *nam; + struct proc *p; { int s = splnet(); int error; - error = (*so->so_proto->pr_usrreqs->pru_bind)(so, nam); + error = (*so->so_proto->pr_usrreqs->pru_bind)(so, nam, p); splx(s); return (error); } int -solisten(so, backlog) +solisten(so, backlog, p) register struct socket *so; int backlog; + struct proc *p; { int s = splnet(), error; - error = (*so->so_proto->pr_usrreqs->pru_listen)(so); + error = (*so->so_proto->pr_usrreqs->pru_listen)(so, p); if (error) { splx(s); return (error); @@ -247,9 +247,10 @@ soaccept(so, nam) } int -soconnect(so, nam) +soconnect(so, nam, p) register struct socket *so; struct mbuf *nam; + struct proc *p; { int s; int error; @@ -268,7 +269,7 @@ soconnect(so, nam) (error = sodisconnect(so)))) error = EISCONN; else - error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam); + error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam, p); splx(s); return (error); } @@ -471,7 +472,7 @@ nopages: (so->so_proto->pr_flags & PR_IMPLOPCL) && (resid <= 0)) ? PRUS_EOF : 0, - top, addr, control); + top, addr, control, p); splx(s); if (dontroute) so->so_options &= ~SO_DONTROUTE; @@ -847,10 +848,11 @@ sorflush(so) } int -sosetopt(so, level, optname, m0) +sosetopt(so, level, optname, m0, p) register struct socket *so; int level, optname; struct mbuf *m0; + struct proc *p; { int error = 0; register struct mbuf *m = m0; @@ -858,7 +860,7 @@ sosetopt(so, level, optname, m0) if (level != SOL_SOCKET) { if (so->so_proto && so->so_proto->pr_ctloutput) return ((*so->so_proto->pr_ctloutput) - (PRCO_SETOPT, so, level, optname, &m0)); + (PRCO_SETOPT, so, level, optname, &m0, p)); error = ENOPROTOOPT; } else { switch (optname) { @@ -948,18 +950,13 @@ sosetopt(so, level, optname, m0) break; } - case SO_PRIVSTATE: - /* we don't care what the parameter is... */ - so->so_state &= ~SS_PRIV; - break; - default: error = ENOPROTOOPT; break; } if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) { (void) ((*so->so_proto->pr_ctloutput) - (PRCO_SETOPT, so, level, optname, &m0)); + (PRCO_SETOPT, so, level, optname, &m0, p)); m = NULL; /* freed by protocol */ } } @@ -970,17 +967,18 @@ bad: } int -sogetopt(so, level, optname, mp) +sogetopt(so, level, optname, mp, p) register struct socket *so; int level, optname; struct mbuf **mp; + struct proc *p; { register struct mbuf *m; if (level != SOL_SOCKET) { if (so->so_proto && so->so_proto->pr_ctloutput) { return ((*so->so_proto->pr_ctloutput) - (PRCO_GETOPT, so, level, optname, mp)); + (PRCO_GETOPT, so, level, optname, mp, p)); } else return (ENOPROTOOPT); } else { @@ -1008,10 +1006,6 @@ sogetopt(so, level, optname, mp) *mtod(m, int *) = so->so_options & optname; break; - case SO_PRIVSTATE: - *mtod(m, int *) = so->so_state & SS_PRIV; - break; - case SO_TYPE: *mtod(m, int *) = so->so_type; break; @@ -1071,3 +1065,40 @@ sohasoutofband(so) psignal(p, SIGURG); selwakeup(&so->so_rcv.sb_sel); } + +int +soselect(struct socket *so, int which, struct proc *p) +{ + int s = splnet(); + switch (which) { + + case FREAD: + if (soreadable(so)) { + splx(s); + return (1); + } + selrecord(p, &so->so_rcv.sb_sel); + so->so_rcv.sb_flags |= SB_SEL; + break; + + case FWRITE: + if (sowriteable(so)) { + splx(s); + return (1); + } + selrecord(p, &so->so_snd.sb_sel); + so->so_snd.sb_flags |= SB_SEL; + break; + + case 0: + if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) { + splx(s); + return (1); + } + selrecord(p, &so->so_rcv.sb_sel); + so->so_rcv.sb_flags |= SB_SEL; + break; + } + splx(s); + return (0); +} diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index 4bddd1a..f31cc98 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 - * $Id: uipc_socket2.c,v 1.22 1997/02/24 20:30:57 wollman Exp $ + * $Id: uipc_socket2.c,v 1.23 1997/03/31 12:29:59 davidg Exp $ */ #include <sys/param.h> @@ -220,7 +220,7 @@ sonewconn1(head, connstatus) so->so_pgid = head->so_pgid; (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat); - if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0)) { + if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, curproc)) { /*XXX*/ (void) free((caddr_t)so, M_SOCKET); return ((struct socket *)0); } @@ -975,7 +975,14 @@ pru_connect2_notsupp(struct socket *so1, struct socket *so2) } int -pru_listen_notsupp(struct socket *so) +pru_control_notsupp(struct socket *so, int cmd, caddr_t data, + struct ifnet *ifp, struct proc *p) +{ + return EOPNOTSUPP; +} + +int +pru_listen_notsupp(struct socket *so, struct proc *p) { return EOPNOTSUPP; } diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 09156f0..fb8f428 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 - * $Id: uipc_syscalls.c,v 1.24 1997/03/31 12:30:01 davidg Exp $ + * $Id: uipc_syscalls.c,v 1.25 1997/04/09 16:53:40 bde Exp $ */ #include "opt_ktrace.h" @@ -130,7 +130,7 @@ bind(p, uap, retval) error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME); if (error) return (error); - error = sobind((struct socket *)fp->f_data, nam); + error = sobind((struct socket *)fp->f_data, nam, p); m_freem(nam); return (error); } @@ -151,7 +151,7 @@ listen(p, uap, retval) error = getsock(p->p_fd, uap->s, &fp); if (error) return (error); - return (solisten((struct socket *)fp->f_data, uap->backlog)); + return (solisten((struct socket *)fp->f_data, uap->backlog, p)); } static int @@ -312,7 +312,7 @@ connect(p, uap, retval) error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME); if (error) return (error); - error = soconnect(so, nam); + error = soconnect(so, nam, p); if (error) goto bad; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { @@ -420,6 +420,7 @@ sendit(p, s, mp, flags, retsize) register int i; struct mbuf *to, *control; int len, error; + struct socket *so; #ifdef KTRACE struct iovec *ktriov = NULL; #endif @@ -485,8 +486,9 @@ sendit(p, s, mp, flags, retsize) } #endif len = auio.uio_resid; - error = sosend((struct socket *)fp->f_data, to, &auio, - (struct mbuf *)0, control, flags); + so = (struct socket *)fp->f_data; + error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control, + flags); if (error) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) @@ -659,6 +661,7 @@ recvit(p, s, mp, namelenp, retsize) int len, error; struct mbuf *m, *from = 0, *control = 0; caddr_t ctlbuf; + struct socket *so; #ifdef KTRACE struct iovec *ktriov = NULL; #endif @@ -687,7 +690,8 @@ recvit(p, s, mp, namelenp, retsize) } #endif len = auio.uio_resid; - error = soreceive((struct socket *)fp->f_data, &from, &auio, + so = (struct socket *)fp->f_data; + error = so->so_proto->pr_usrreqs->pru_soreceive(so, &from, &auio, (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, &mp->msg_flags); if (error) { @@ -1012,7 +1016,7 @@ setsockopt(p, uap, retval) m->m_len = uap->valsize; } return (sosetopt((struct socket *)fp->f_data, uap->level, - uap->name, m)); + uap->name, m, p)); } /* ARGSUSED */ @@ -1043,7 +1047,7 @@ getsockopt(p, uap, retval) } else valsize = 0; if ((error = sogetopt((struct socket *)fp->f_data, uap->level, - uap->name, &m)) == 0 && uap->val && valsize && m != NULL) { + uap->name, &m, p)) == 0 && uap->val && valsize && m != NULL) { op = 0; while (m && !error && op < valsize) { i = min(m->m_len, (valsize - op)); diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 0a47414..2734778d 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94 - * $Id: uipc_usrreq.c,v 1.21 1997/03/21 16:12:32 wpaul Exp $ + * $Id: uipc_usrreq.c,v 1.22 1997/03/23 03:36:33 bde Exp $ */ #include <sys/param.h> @@ -78,270 +78,353 @@ static void unp_mark __P((struct file *)); static void unp_discard __P((struct file *)); static int unp_internalize __P((struct mbuf *, struct proc *)); +static int +uipc_abort(struct socket *so) +{ + struct unpcb *unp = sotounpcb(so); -/*ARGSUSED*/ -int -uipc_usrreq(so, req, m, nam, control) - struct socket *so; - int req; - struct mbuf *m, *nam, *control; + if (unp == 0) + return EINVAL; + unp_drop(unp, ECONNABORTED); + return 0; +} + +static int +uipc_accept(struct socket *so, struct mbuf *nam) { 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; + if (unp == 0) + return EINVAL; + + /* + * 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; } - switch (req) { + return 0; +} - case PRU_ATTACH: - if (unp) { - error = EISCONN; - break; - } - error = unp_attach(so); - break; +static int +uipc_attach(struct socket *so, int proto, struct proc *p) +{ + struct unpcb *unp = sotounpcb(so); - case PRU_DETACH: - unp_detach(unp); - break; + if (unp != 0) + return EISCONN; + return unp_attach(so); +} - case PRU_BIND: - error = unp_bind(unp, nam, p); - break; +static int +uipc_bind(struct socket *so, struct mbuf *nam, struct proc *p) +{ + struct unpcb *unp = sotounpcb(so); - case PRU_LISTEN: - if (unp->unp_vnode == 0) - error = EINVAL; - break; + if (unp == 0) + return EINVAL; - case PRU_CONNECT: - error = unp_connect(so, nam, p); - break; + return unp_bind(unp, nam, p); +} - case PRU_CONNECT2: - error = unp_connect2(so, (struct socket *)nam); - break; +static int +uipc_connect(struct socket *so, struct mbuf *nam, struct proc *p) +{ + struct unpcb *unp = sotounpcb(so); - case PRU_DISCONNECT: - unp_disconnect(unp); - break; + if (unp == 0) + return EINVAL; + return unp_connect(so, nam, curproc); +} - 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; +static int +uipc_connect2(struct socket *so1, struct socket *so2) +{ + struct unpcb *unp = sotounpcb(so1); - case PRU_SHUTDOWN: - socantsendmore(so); - unp_shutdown(unp); - break; + if (unp == 0) + return EINVAL; - case PRU_RCVD: - switch (so->so_type) { + return unp_connect2(so1, so2); +} - case SOCK_DGRAM: - panic("uipc 1"); - /*NOTREACHED*/ +/* control is EOPNOTSUPP */ - case SOCK_STREAM: +static int +uipc_detach(struct socket *so) +{ + struct unpcb *unp = sotounpcb(so); + + if (unp == 0) + return EINVAL; + + unp_detach(unp); + return 0; +} + +static int +uipc_disconnect(struct socket *so) +{ + struct unpcb *unp = sotounpcb(so); + + if (unp == 0) + return EINVAL; + unp_disconnect(unp); + return 0; +} + +static int +uipc_listen(struct socket *so, struct proc *p) +{ + struct unpcb *unp = sotounpcb(so); + + if (unp == 0 || unp->unp_vnode == 0) + return EINVAL; + return 0; +} + +static int +uipc_peeraddr(struct socket *so, struct mbuf *nam) +{ + struct unpcb *unp = sotounpcb(so); + + if (unp == 0) + return EINVAL; + 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; + return 0; +} + +static int +uipc_rcvd(struct socket *so, int flags) +{ + struct unpcb *unp = sotounpcb(so); + struct socket *so2; + + if (unp == 0) + return EINVAL; + switch (so->so_type) { + case SOCK_DGRAM: + panic("uipc_rcvd DGRAM?"); + /*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); + 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: - case PRU_SEND_EOF: - if (control && (error = unp_internalize(control, p))) - break; - switch (so->so_type) { + default: + panic("uipc_rcvd unknown socktype"); + } + return 0; +} - case SOCK_DGRAM: { - struct sockaddr *from; +/* pru_rcvoob is EOPNOTSUPP */ - 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; - } +static int +uipc_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam, + struct mbuf *control, struct proc *p) +{ + int error = 0; + struct unpcb *unp = sotounpcb(so); + struct socket *so2; - case SOCK_STREAM: -#define rcv (&so2->so_rcv) -#define snd (&so->so_snd) - /* Connect if not connected yet. */ - /* - * Note: A better implementation would complain - * if not equal to the peer's address. - */ - if ((so->so_state & SS_ISCONNECTED) == 0) { - if (nam) { - error = unp_connect(so, nam, p); - if (error) - break; /* XXX */ - } else { - error = ENOTCONN; - break; - } - } + if (unp == 0) { + error = EINVAL; + goto release; + } + if (flags & PRUS_OOB) { + error = EOPNOTSUPP; + goto release; + } + + if (control && (error = unp_internalize(control, p))) + goto release; - if (so->so_state & SS_CANTSENDMORE) { - error = EPIPE; + switch (so->so_type) { + case SOCK_DGRAM: + { + struct sockaddr *from; + + if (nam) { + if (unp->unp_conn) { + error = EISCONN; 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; + 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; -#undef snd -#undef rcv - break; + control = 0; + } else + error = ENOBUFS; + if (nam) + unp_disconnect(unp); + break; + } - default: - panic("uipc 4"); - } + case SOCK_STREAM: +#define rcv (&so2->so_rcv) +#define snd (&so->so_snd) + /* Connect if not connected yet. */ /* - * SEND_EOF is equivalent to a SEND followed by - * a SHUTDOWN. + * Note: A better implementation would complain + * if not equal to the peer's address. */ - if (req == PRU_SEND_EOF) { - socantsendmore(so); - unp_shutdown(unp); + if ((so->so_state & SS_ISCONNECTED) == 0) { + if (nam) { + error = unp_connect(so, nam, p); + if (error) + break; /* XXX */ + } else { + error = ENOTCONN; + break; + } } - 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; + if (so->so_state & SS_CANTSENDMORE) { + error = EPIPE; + break; } - ((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); + if (unp->unp_conn == 0) + panic("uipc_send connected but no connection?"); + 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 - nam->m_len = 0; - break; - - case PRU_SLOWTIMO: + 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("piusrreq"); + panic("uipc_send unknown socktype"); + } + + /* + * SEND_EOF is equivalent to a SEND followed by + * a SHUTDOWN. + */ + if (flags & PRUS_EOF) { + socantsendmore(so); + unp_shutdown(unp); } + release: if (control) m_freem(control); if (m) m_freem(m); - return (error); + return error; +} + +static int +uipc_sense(struct socket *so, struct stat *sb) +{ + struct unpcb *unp = sotounpcb(so); + struct socket *so2; + + if (unp == 0) + return EINVAL; + sb->st_blksize = so->so_snd.sb_hiwat; + if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) { + so2 = unp->unp_conn->unp_socket; + sb->st_blksize += so2->so_rcv.sb_cc; + } + sb->st_dev = NODEV; + if (unp->unp_ino == 0) + unp->unp_ino = unp_ino++; + sb->st_ino = unp->unp_ino; + return (0); +} + +static int +uipc_shutdown(struct socket *so) +{ + struct unpcb *unp = sotounpcb(so); + + if (unp == 0) + return EINVAL; + socantsendmore(so); + unp_shutdown(unp); + return 0; +} + +static int +uipc_sockaddr(struct socket *so, struct mbuf *nam) +{ + struct unpcb *unp = sotounpcb(so); + + if (unp == 0) + return EINVAL; + 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; + return 0; } +struct pr_usrreqs uipc_usrreqs = { + uipc_abort, uipc_accept, uipc_attach, uipc_bind, uipc_connect, + uipc_connect2, pru_control_notsupp, uipc_detach, uipc_disconnect, + uipc_listen, uipc_peeraddr, uipc_rcvd, pru_rcvoob_notsupp, + uipc_send, uipc_sense, uipc_shutdown, uipc_sockaddr, + sosend, soreceive, soselect +}; + /* * Both send and receive buffers are allocated PIPSIZ bytes of buffering * for stream sockets, although the total for sender and receiver is @@ -472,7 +555,7 @@ unp_bind(unp, nam, p) } VATTR_NULL(&vattr); vattr.va_type = VSOCK; - vattr.va_mode = ACCESSPERMS; + vattr.va_mode = (ACCESSPERMS & ~p->p_fd->fd_cmask); VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); if (error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)) return (error); |