From 67a10ba2366df7017b776ada734f425cd14cc7b0 Mon Sep 17 00:00:00 2001 From: mvs Date: Sun, 13 Nov 2022 16:01:32 +0000 Subject: [PATCH] Split out handlers for SOCK_DGRAM unix(4) sockets from SOCK_STREAM and SOCK_SEQPACKET. Introduce `uipc_dgram_usrreqs' to store pointers for dgram specific handlers. The dgram pru_shutdown and pru_send handlers were splitted to uipc_dgram_shutdown() and uipc_dgram_send(). The pru_accept, pru_rcvd and pru_abort handlers are not required for dgram sockets. The unp_disconnect() remains shared between all unix(4) sockets because it called from common paths too. Proposed by and ok guenther@ --- sys/kern/uipc_proto.c | 4 +- sys/kern/uipc_usrreq.c | 236 ++++++++++++++++++++++------------------- sys/sys/unpcb.h | 7 +- 3 files changed, 131 insertions(+), 116 deletions(-) diff --git a/sys/kern/uipc_proto.c b/sys/kern/uipc_proto.c index d6447bf9958..ba6259566f7 100644 --- a/sys/kern/uipc_proto.c +++ b/sys/kern/uipc_proto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_proto.c,v 1.24 2022/08/15 09:11:38 mvs Exp $ */ +/* $OpenBSD: uipc_proto.c,v 1.25 2022/11/13 16:01:32 mvs Exp $ */ /* $NetBSD: uipc_proto.c,v 1.8 1996/02/13 21:10:47 christos Exp $ */ /*- @@ -62,7 +62,7 @@ const struct protosw unixsw[] = { .pr_domain = &unixdomain, .pr_protocol = PF_UNIX, .pr_flags = PR_ATOMIC|PR_ADDR|PR_RIGHTS, - .pr_usrreqs = &uipc_usrreqs, + .pr_usrreqs = &uipc_dgram_usrreqs, } }; diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 38f4d073198..51edacb135d 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_usrreq.c,v 1.191 2022/10/17 14:49:01 mvs Exp $ */ +/* $OpenBSD: uipc_usrreq.c,v 1.192 2022/11/13 16:01:32 mvs Exp $ */ /* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */ /* @@ -144,6 +144,21 @@ const struct pr_usrreqs uipc_usrreqs = { .pru_connect2 = uipc_connect2, }; +const struct pr_usrreqs uipc_dgram_usrreqs = { + .pru_attach = uipc_attach, + .pru_detach = uipc_detach, + .pru_bind = uipc_bind, + .pru_listen = uipc_listen, + .pru_connect = uipc_connect, + .pru_disconnect = uipc_disconnect, + .pru_shutdown = uipc_dgram_shutdown, + .pru_send = uipc_dgram_send, + .pru_sense = uipc_sense, + .pru_sockaddr = uipc_sockaddr, + .pru_peeraddr = uipc_peeraddr, + .pru_connect2 = uipc_connect2, +}; + void unp_init(void) { @@ -358,9 +373,22 @@ int uipc_shutdown(struct socket *so) { struct unpcb *unp = sotounpcb(so); + struct socket *so2; + + socantsendmore(so); + + if ((so2 = unp_solock_peer(unp->unp_socket))){ + socantrcvmore(so2); + sounlock(so2); + } + + return (0); +} +int +uipc_dgram_shutdown(struct socket *so) +{ socantsendmore(so); - unp_shutdown(unp); return (0); } @@ -369,35 +397,22 @@ uipc_rcvd(struct socket *so) { struct socket *so2; - switch (so->so_type) { - case SOCK_DGRAM: - panic("uipc 1"); - /*NOTREACHED*/ - - case SOCK_STREAM: - case SOCK_SEQPACKET: - if ((so2 = unp_solock_peer(so)) == NULL) - break; - /* - * Adjust backpressure on sender - * and wakeup any waiting to write. - */ - so2->so_snd.sb_mbcnt = so->so_rcv.sb_mbcnt; - so2->so_snd.sb_cc = so->so_rcv.sb_cc; - sowwakeup(so2); - sounlock(so2); - break; - - default: - panic("uipc 2"); - } + if ((so2 = unp_solock_peer(so)) == NULL) + return; + /* + * Adjust backpressure on sender + * and wakeup any waiting to write. + */ + so2->so_snd.sb_mbcnt = so->so_rcv.sb_mbcnt; + so2->so_snd.sb_cc = so->so_rcv.sb_cc; + sowwakeup(so2); + sounlock(so2); } int uipc_send(struct socket *so, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { - struct unpcb *unp = sotounpcb(so); struct socket *so2; int error = 0; @@ -409,88 +424,105 @@ uipc_send(struct socket *so, struct mbuf *m, struct mbuf *nam, goto out; } - switch (so->so_type) { - case SOCK_DGRAM: { - const struct sockaddr *from; + if (so->so_state & SS_CANTSENDMORE) { + error = EPIPE; + goto dispose; + } + if ((so2 = unp_solock_peer(so)) == NULL) { + error = ENOTCONN; + goto dispose; + } - if (nam) { - if (unp->unp_conn) { - error = EISCONN; - break; - } - error = unp_connect(so, nam, curproc); - if (error) - break; + /* + * Send to paired receive port, and then raise + * send buffer counts to maintain backpressure. + * Wake up readers. + */ + if (control) { + if (sbappendcontrol(so2, &so2->so_rcv, m, control)) { + control = NULL; + } else { + sounlock(so2); + error = ENOBUFS; + goto dispose; } + } else if (so->so_type == SOCK_SEQPACKET) + sbappendrecord(so2, &so2->so_rcv, m); + else + sbappend(so2, &so2->so_rcv, m); + so->so_snd.sb_mbcnt = so2->so_rcv.sb_mbcnt; + so->so_snd.sb_cc = so2->so_rcv.sb_cc; + if (so2->so_rcv.sb_cc > 0) + sorwakeup(so2); - if ((so2 = unp_solock_peer(so)) == NULL) { - if (nam != NULL) - error = ECONNREFUSED; - else - error = ENOTCONN; - break; - } + sounlock(so2); + m = NULL; - if (unp->unp_addr) - from = mtod(unp->unp_addr, struct sockaddr *); - else - from = &sun_noname; - if (sbappendaddr(so2, &so2->so_rcv, from, m, control)) { - sorwakeup(so2); - m = NULL; - control = NULL; - } else - error = ENOBUFS; +dispose: + /* we need to undo unp_internalize in case of errors */ + if (control && error) + unp_dispose(control); - if (so2 != so) - sounlock(so2); +out: + m_freem(control); + m_freem(m); - if (nam) - unp_disconnect(unp); - break; + return (error); +} + +int +uipc_dgram_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control) +{ + struct unpcb *unp = sotounpcb(so); + struct socket *so2; + const struct sockaddr *from; + int error = 0; + + if (control) { + sounlock(so); + error = unp_internalize(control, curproc); + solock(so); + if (error) + goto out; } - case SOCK_STREAM: - case SOCK_SEQPACKET: - if (so->so_state & SS_CANTSENDMORE) { - error = EPIPE; - break; - } - if ((so2 = unp_solock_peer(so)) == NULL) { - error = ENOTCONN; - break; + if (nam) { + if (unp->unp_conn) { + error = EISCONN; + goto dispose; } + error = unp_connect(so, nam, curproc); + if (error) + goto dispose; + } - /* - * Send to paired receive port, and then raise - * send buffer counts to maintain backpressure. - * Wake up readers. - */ - if (control) { - if (sbappendcontrol(so2, &so2->so_rcv, m, control)) { - control = NULL; - } else { - sounlock(so2); - error = ENOBUFS; - break; - } - } else if (so->so_type == SOCK_SEQPACKET) - sbappendrecord(so2, &so2->so_rcv, m); + if ((so2 = unp_solock_peer(so)) == NULL) { + if (nam != NULL) + error = ECONNREFUSED; else - sbappend(so2, &so2->so_rcv, m); - so->so_snd.sb_mbcnt = so2->so_rcv.sb_mbcnt; - so->so_snd.sb_cc = so2->so_rcv.sb_cc; - if (so2->so_rcv.sb_cc > 0) - sorwakeup(so2); + error = ENOTCONN; + goto dispose; + } - sounlock(so2); + if (unp->unp_addr) + from = mtod(unp->unp_addr, struct sockaddr *); + else + from = &sun_noname; + if (sbappendaddr(so2, &so2->so_rcv, from, m, control)) { + sorwakeup(so2); m = NULL; - break; + control = NULL; + } else + error = ENOBUFS; - default: - panic("uipc 4"); - } + if (so2 != so) + sounlock(so2); + if (nam) + unp_disconnect(unp); + +dispose: /* we need to undo unp_internalize in case of errors */ if (control && error) unp_dispose(control); @@ -975,26 +1007,6 @@ unp_disconnect(struct unpcb *unp) sounlock(so2); } -void -unp_shutdown(struct unpcb *unp) -{ - struct socket *so2; - - switch (unp->unp_socket->so_type) { - case SOCK_STREAM: - case SOCK_SEQPACKET: - if ((so2 = unp_solock_peer(unp->unp_socket)) == NULL) - break; - - socantrcvmore(so2); - sounlock(so2); - - break; - default: - break; - } -} - static struct unpcb * fptounp(struct file *fp) { diff --git a/sys/sys/unpcb.h b/sys/sys/unpcb.h index 03f4cbb9e55..c71617ef7cd 100644 --- a/sys/sys/unpcb.h +++ b/sys/sys/unpcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: unpcb.h,v 1.43 2022/10/17 14:49:02 mvs Exp $ */ +/* $OpenBSD: unpcb.h,v 1.44 2022/11/13 16:01:32 mvs Exp $ */ /* $NetBSD: unpcb.h,v 1.6 1994/06/29 06:46:08 cgd Exp $ */ /* @@ -111,6 +111,7 @@ struct fdpass { }; extern const struct pr_usrreqs uipc_usrreqs; +extern const struct pr_usrreqs uipc_dgram_usrreqs; int uipc_attach(struct socket *, int, int); int uipc_detach(struct socket *); @@ -120,9 +121,12 @@ int uipc_connect(struct socket *, struct mbuf *); int uipc_accept(struct socket *, struct mbuf *); int uipc_disconnect(struct socket *); int uipc_shutdown(struct socket *); +int uipc_dgram_shutdown(struct socket *); void uipc_rcvd(struct socket *); int uipc_send(struct socket *, struct mbuf *, struct mbuf *, struct mbuf *); +int uipc_dgram_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); void uipc_abort(struct socket *); int uipc_sense(struct socket *, struct stat *); int uipc_sockaddr(struct socket *, struct mbuf *); @@ -136,7 +140,6 @@ int unp_connect2(struct socket *, struct socket *); void unp_detach(struct unpcb *); void unp_disconnect(struct unpcb *); void unp_gc(void *); -void unp_shutdown(struct unpcb *); int unp_externalize(struct mbuf *, socklen_t, int); int unp_internalize(struct mbuf *, struct proc *); void unp_dispose(struct mbuf *); -- 2.20.1