guenther@ proposed to split out handlers for SOCK_DGRAM unix(4) sockets from SOCK_STREAM and SOCK_SEQPACKET.
The diff below introduces `uipc_dgram_usrreqs' to store pointers to 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. Index: sys/kern/uipc_proto.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_proto.c,v retrieving revision 1.24 diff -u -p -r1.24 uipc_proto.c --- sys/kern/uipc_proto.c 15 Aug 2022 09:11:38 -0000 1.24 +++ sys/kern/uipc_proto.c 5 Nov 2022 23:36:14 -0000 @@ -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, } }; Index: sys/kern/uipc_usrreq.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v retrieving revision 1.191 diff -u -p -r1.191 uipc_usrreq.c --- sys/kern/uipc_usrreq.c 17 Oct 2022 14:49:01 -0000 1.191 +++ sys/kern/uipc_usrreq.c 5 Nov 2022 23:36:14 -0000 @@ -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 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); @@ -973,26 +1005,6 @@ unp_disconnect(struct unpcb *unp) if (so2 != unp->unp_socket) 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 * Index: sys/sys/unpcb.h =================================================================== RCS file: /cvs/src/sys/sys/unpcb.h,v retrieving revision 1.43 diff -u -p -r1.43 unpcb.h --- sys/sys/unpcb.h 17 Oct 2022 14:49:02 -0000 1.43 +++ sys/sys/unpcb.h 5 Nov 2022 23:36:14 -0000 @@ -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 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 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 *);