Split out handlers for SOCK_DGRAM unix(4) sockets from SOCK_STREAM and
authormvs <mvs@openbsd.org>
Sun, 13 Nov 2022 16:01:32 +0000 (16:01 +0000)
committermvs <mvs@openbsd.org>
Sun, 13 Nov 2022 16:01:32 +0000 (16:01 +0000)
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
sys/kern/uipc_usrreq.c
sys/sys/unpcb.h

index d6447bf..ba62595 100644 (file)
@@ -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,
 }
 };
 
index 38f4d07..51edacb 100644 (file)
@@ -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)
 {
index 03f4cbb..c71617e 100644 (file)
@@ -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 *);