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

Reply via email to