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