The branch main has been updated by glebius:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=e7d02be19d40063783d6b8f1ff2bc4c7170fd434

commit e7d02be19d40063783d6b8f1ff2bc4c7170fd434
Author:     Gleb Smirnoff <gleb...@freebsd.org>
AuthorDate: 2022-08-17 18:50:32 +0000
Commit:     Gleb Smirnoff <gleb...@freebsd.org>
CommitDate: 2022-08-17 18:50:32 +0000

    protosw: refactor protosw and domain static declaration and load
    
    o Assert that every protosw has pr_attach.  Now this structure is
      only for socket protocols declarations and nothing else.
    o Merge struct pr_usrreqs into struct protosw.  This was suggested
      in 1996 by wollman@ (see 7b187005d18ef), and later reiterated
      in 2006 by rwatson@ (see 6fbb9cf860dcd).
    o Make struct domain hold a variable sized array of protosw pointers.
      For most protocols these pointers are initialized statically.
      Those domains that may have loadable protocols have spacers. IPv4
      and IPv6 have 8 spacers each (andre@ dff3237ee54ea).
    o For inetsw and inet6sw leave a comment noting that many protosw
      entries very likely are dead code.
    o Refactor pf_proto_[un]register() into protosw_[un]register().
    o Isolate pr_*_notsupp() methods into uipc_domain.c
    
    Reviewed by:            melifaro
    Differential revision:  https://reviews.freebsd.org/D36232
---
 sys/compat/linuxkpi/common/include/linux/net.h     |   4 +-
 sys/dev/cxgbe/tom/t4_tom.c                         |  29 +-
 sys/dev/hyperv/hvsock/hv_sock.c                    |  47 +--
 sys/kern/kern_sendfile.c                           |  17 +-
 sys/kern/sys_socket.c                              |  11 +-
 sys/kern/uipc_domain.c                             | 376 ++++++++++++---------
 sys/kern/uipc_ktls.c                               |  12 +-
 sys/kern/uipc_socket.c                             | 260 +++-----------
 sys/kern/uipc_syscalls.c                           |   4 +-
 sys/kern/uipc_usrreq.c                             | 223 ++++++------
 sys/net/if.c                                       |   3 +-
 sys/net/if_ovpn.c                                  |   2 +-
 sys/net/rtsock.c                                   |  25 +-
 sys/netgraph/bluetooth/socket/ng_btsocket.c        | 210 +++++-------
 sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c |   4 +-
 sys/netgraph/ng_ksocket.c                          |   4 +-
 sys/netgraph/ng_socket.c                           |  59 ++--
 sys/netinet/in_proto.c                             | 202 +++--------
 sys/netinet/ip_divert.c                            |  28 +-
 sys/netinet/ip_output.c                            |   1 -
 sys/netinet/ip_var.h                               |   1 -
 sys/netinet/raw_ip.c                               |  81 ++++-
 sys/netinet/sctp_module.c                          |  60 +---
 sys/netinet/sctp_usrreq.c                          |  51 +--
 sys/netinet/sctp_var.h                             |   2 +-
 sys/netinet/tcp_subr.c                             |   4 +-
 sys/netinet/tcp_usrreq.c                           |  86 ++---
 sys/netinet/tcp_var.h                              |   3 +-
 sys/netinet/udp_usrreq.c                           |  44 ++-
 sys/netinet/udp_var.h                              |   1 -
 sys/netinet6/in6_proto.c                           | 202 +++--------
 sys/netinet6/raw_ip6.c                             |  75 +++-
 sys/netinet6/sctp6_usrreq.c                        |  50 +--
 sys/netinet6/sctp6_var.h                           |   2 +-
 sys/netinet6/send.c                                |  15 +-
 sys/netinet6/udp6_usrreq.c                         |  44 ++-
 sys/netipsec/keysock.c                             |  34 +-
 sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c     |  74 ++--
 sys/rpc/rpc_generic.c                              |   6 +-
 sys/rpc/svc_dg.c                                   |   2 +-
 sys/rpc/svc_vc.c                                   |   6 +-
 sys/security/mac/mac_socket.c                      |   4 +-
 sys/sys/domain.h                                   |   3 +-
 sys/sys/protosw.h                                  | 136 +++-----
 44 files changed, 1042 insertions(+), 1465 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/net.h 
b/sys/compat/linuxkpi/common/include/linux/net.h
index 5438fccb8512..d5752093da74 100644
--- a/sys/compat/linuxkpi/common/include/linux/net.h
+++ b/sys/compat/linuxkpi/common/include/linux/net.h
@@ -58,9 +58,9 @@ sock_getname(struct socket *so, struct sockaddr *addr, int 
*sockaddr_len,
                if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
                        return (-ENOTCONN);
 
-               error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &nam);
+               error = so->so_proto->pr_peeraddr(so, &nam);
        } else
-               error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &nam);
+               error = so->so_proto->pr_sockaddr(so, &nam);
        if (error)
                return (-error);
        *addr = *nam;
diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c
index 9bd6145c9acc..825a4e96ce81 100644
--- a/sys/dev/cxgbe/tom/t4_tom.c
+++ b/sys/dev/cxgbe/tom/t4_tom.c
@@ -80,13 +80,8 @@ __FBSDID("$FreeBSD$");
 #include "tom/t4_tom.h"
 #include "tom/t4_tls.h"
 
-static struct protosw *tcp_protosw;
 static struct protosw toe_protosw;
-static struct pr_usrreqs toe_usrreqs;
-
-static struct protosw *tcp6_protosw;
 static struct protosw toe6_protosw;
-static struct pr_usrreqs toe6_usrreqs;
 
 /* Module ops */
 static int t4_tom_mod_load(void);
@@ -269,9 +264,9 @@ void
 restore_so_proto(struct socket *so, bool v6)
 {
        if (v6)
-               so->so_proto = tcp6_protosw;
+               so->so_proto = &tcp6_protosw;
        else
-               so->so_proto = tcp_protosw;
+               so->so_proto = &tcp_protosw;
 }
 
 /* This is _not_ the normal way to "unoffload" a socket. */
@@ -2024,21 +2019,11 @@ t4_tom_mod_load(void)
        t4_ddp_mod_load();
        t4_tls_mod_load();
 
-       tcp_protosw = pffindproto(PF_INET, IPPROTO_TCP, SOCK_STREAM);
-       if (tcp_protosw == NULL)
-               return (ENOPROTOOPT);
-       bcopy(tcp_protosw, &toe_protosw, sizeof(toe_protosw));
-       bcopy(tcp_protosw->pr_usrreqs, &toe_usrreqs, sizeof(toe_usrreqs));
-       toe_usrreqs.pru_aio_queue = t4_aio_queue_tom;
-       toe_protosw.pr_usrreqs = &toe_usrreqs;
-
-       tcp6_protosw = pffindproto(PF_INET6, IPPROTO_TCP, SOCK_STREAM);
-       if (tcp6_protosw == NULL)
-               return (ENOPROTOOPT);
-       bcopy(tcp6_protosw, &toe6_protosw, sizeof(toe6_protosw));
-       bcopy(tcp6_protosw->pr_usrreqs, &toe6_usrreqs, sizeof(toe6_usrreqs));
-       toe6_usrreqs.pru_aio_queue = t4_aio_queue_tom;
-       toe6_protosw.pr_usrreqs = &toe6_usrreqs;
+       bcopy(&tcp_protosw, &toe_protosw, sizeof(toe_protosw));
+       toe_protosw.pr_aio_queue = t4_aio_queue_tom;
+
+       bcopy(&tcp6_protosw, &toe6_protosw, sizeof(toe6_protosw));
+       toe6_protosw.pr_aio_queue = t4_aio_queue_tom;
 
        return (t4_register_uld(&tom_uld_info));
 }
diff --git a/sys/dev/hyperv/hvsock/hv_sock.c b/sys/dev/hyperv/hvsock/hv_sock.c
index 8c327a22e6fd..f728383a1b6f 100644
--- a/sys/dev/hyperv/hvsock/hv_sock.c
+++ b/sys/dev/hyperv/hvsock/hv_sock.c
@@ -86,48 +86,35 @@ static int hvs_dom_probe(void);
                                         roundup2(payload_len, 8) + \
                                         sizeof(uint64_t))
 
-
-static struct domain           hv_socket_domain;
-
 /*
  * HyperV Transport sockets
  */
-static struct pr_usrreqs       hvs_trans_usrreqs = {
-       .pru_attach =           hvs_trans_attach,
-       .pru_bind =             hvs_trans_bind,
-       .pru_listen =           hvs_trans_listen,
-       .pru_accept =           hvs_trans_accept,
-       .pru_connect =          hvs_trans_connect,
-       .pru_peeraddr =         hvs_trans_peeraddr,
-       .pru_sockaddr =         hvs_trans_sockaddr,
-       .pru_soreceive =        hvs_trans_soreceive,
-       .pru_sosend =           hvs_trans_sosend,
-       .pru_disconnect =       hvs_trans_disconnect,
-       .pru_close =            hvs_trans_close,
-       .pru_detach =           hvs_trans_detach,
-       .pru_shutdown =         hvs_trans_shutdown,
-       .pru_abort =            hvs_trans_abort,
-};
-
-/*
- * Definitions of protocols supported in HyperV socket domain
- */
-static struct protosw          hv_socket_protosw[] = {
-{
+static struct protosw hv_socket_protosw = {
        .pr_type =              SOCK_STREAM,
-       .pr_domain =            &hv_socket_domain,
        .pr_protocol =          HYPERV_SOCK_PROTO_TRANS,
        .pr_flags =             PR_CONNREQUIRED,
-       .pr_usrreqs =           &hvs_trans_usrreqs,
-},
+       .pr_attach =            hvs_trans_attach,
+       .pr_bind =              hvs_trans_bind,
+       .pr_listen =            hvs_trans_listen,
+       .pr_accept =            hvs_trans_accept,
+       .pr_connect =           hvs_trans_connect,
+       .pr_peeraddr =          hvs_trans_peeraddr,
+       .pr_sockaddr =          hvs_trans_sockaddr,
+       .pr_soreceive =         hvs_trans_soreceive,
+       .pr_sosend =            hvs_trans_sosend,
+       .pr_disconnect =        hvs_trans_disconnect,
+       .pr_close =             hvs_trans_close,
+       .pr_detach =            hvs_trans_detach,
+       .pr_shutdown =          hvs_trans_shutdown,
+       .pr_abort =             hvs_trans_abort,
 };
 
 static struct domain           hv_socket_domain = {
        .dom_family =           AF_HYPERV,
        .dom_name =             "hyperv",
        .dom_probe =            hvs_dom_probe,
-       .dom_protosw =          hv_socket_protosw,
-       .dom_protoswNPROTOSW =  &hv_socket_protosw[nitems(hv_socket_protosw)]
+       .dom_nprotosw =         1,
+       .dom_protosw =          { &hv_socket_protosw },
 };
 
 DOMAIN_SET(hv_socket_);
diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c
index 2de015254ab9..f444e38e153d 100644
--- a/sys/kern/kern_sendfile.c
+++ b/sys/kern/kern_sendfile.c
@@ -377,7 +377,7 @@ sendfile_iodone(void *arg, vm_page_t *pa, int count, int 
error)
                 * for read, so that application receives EIO on next
                 * syscall and eventually closes the socket.
                 */
-               so->so_proto->pr_usrreqs->pru_abort(so);
+               so->so_proto->pr_abort(so);
                so->so_error = EIO;
 
                mb_free_notready(sfio->m, sfio->npages);
@@ -396,8 +396,7 @@ sendfile_iodone(void *arg, vm_page_t *pa, int count, int 
error)
                goto out_with_ref;
 #endif
        } else
-               (void)(so->so_proto->pr_usrreqs->pru_ready)(so, sfio->m,
-                   sfio->npages);
+               (void)so->so_proto->pr_ready(so, sfio->m, sfio->npages);
 
        sorele(so);
 #ifdef KERN_TLS
@@ -1172,8 +1171,8 @@ prepend_header:
                                sendfile_iodone(sfio, NULL, 0, 0);
 #ifdef KERN_TLS
                        if (tls != NULL && tls->mode == TCP_TLS_MODE_SW) {
-                               error = (*so->so_proto->pr_usrreqs->pru_send)
-                                   (so, PRUS_NOTREADY, m, NULL, NULL, td);
+                               error = so->so_proto->pr_send(so,
+                                   PRUS_NOTREADY, m, NULL, NULL, td);
                                if (error != 0) {
                                        m_freem(m);
                                } else {
@@ -1182,14 +1181,14 @@ prepend_header:
                                }
                        } else
 #endif
-                               error = (*so->so_proto->pr_usrreqs->pru_send)
-                                   (so, 0, m, NULL, NULL, td);
+                               error = so->so_proto->pr_send(so, 0, m, NULL,
+                                   NULL, td);
                } else {
                        sfio->so = so;
                        sfio->m = m0;
                        soref(so);
-                       error = (*so->so_proto->pr_usrreqs->pru_send)
-                           (so, PRUS_NOTREADY, m, NULL, NULL, td);
+                       error = so->so_proto->pr_send(so, PRUS_NOTREADY, m,
+                           NULL, NULL, td);
                        sendfile_iodone(sfio, NULL, 0, error);
                }
                CURVNET_RESTORE();
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
index 7f39e58f4ce4..5b8aadc12e08 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -276,8 +276,7 @@ soo_ioctl(struct file *fp, u_long cmd, void *data, struct 
ucred *active_cred,
                        CURVNET_RESTORE();
                } else {
                        CURVNET_SET(so->so_vnet);
-                       error = ((*so->so_proto->pr_usrreqs->pru_control)
-                           (so, cmd, data, 0, td));
+                       error = so->so_proto->pr_control(so, cmd, data, 0, td);
                        CURVNET_RESTORE();
                }
                break;
@@ -336,7 +335,7 @@ soo_stat(struct file *fp, struct stat *ub, struct ucred 
*active_cred)
        }
        ub->st_uid = so->so_cred->cr_uid;
        ub->st_gid = so->so_cred->cr_gid;
-       error = so->so_proto->pr_usrreqs->pru_sense(so, ub);
+       error = so->so_proto->pr_sense(so, ub);
        SOCK_UNLOCK(so);
        return (error);
 }
@@ -414,13 +413,13 @@ soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, 
struct filedesc *fdp)
                }
                break;
        }
-       error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
+       error = so->so_proto->pr_sockaddr(so, &sa);
        if (error == 0 &&
            sa->sa_len <= sizeof(kif->kf_un.kf_sock.kf_sa_local)) {
                bcopy(sa, &kif->kf_un.kf_sock.kf_sa_local, sa->sa_len);
                free(sa, M_SONAME);
        }
-       error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
+       error = so->so_proto->pr_peeraddr(so, &sa);
        if (error == 0 &&
            sa->sa_len <= sizeof(kif->kf_un.kf_sock.kf_sa_peer)) {
                bcopy(sa, &kif->kf_un.kf_sock.kf_sa_peer, sa->sa_len);
@@ -812,7 +811,7 @@ soo_aio_queue(struct file *fp, struct kaiocb *job)
        int error;
 
        so = fp->f_data;
-       error = (*so->so_proto->pr_usrreqs->pru_aio_queue)(so, job);
+       error = so->so_proto->pr_aio_queue(so, job);
        if (error == 0)
                return (0);
 
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index c6a79d34beb2..d2b8d9095f13 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/rmlock.h>
 #include <sys/socketvar.h>
 #include <sys/systm.h>
+#include <sys/stat.h>          /* XXXGL: remove */
 
 #include <machine/atomic.h>
 
@@ -76,85 +77,182 @@ int domain_init_status = 0;
 static struct mtx dom_mtx;             /* domain list lock */
 MTX_SYSINIT(domain, &dom_mtx, "domain list", MTX_DEF);
 
+static int
+pr_accept_notsupp(struct socket *so, struct sockaddr **nam)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_aio_queue_notsupp(struct socket *so, struct kaiocb *job)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_bind_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_bindat_notsupp(int fd, struct socket *so, struct sockaddr *nam,
+    struct thread *td)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_connect_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_connectat_notsupp(int fd, struct socket *so, struct sockaddr *nam,
+    struct thread *td)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_connect2_notsupp(struct socket *so1, struct socket *so2)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_control_notsupp(struct socket *so, u_long cmd, void *data,
+    struct ifnet *ifp, struct thread *td)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_disconnect_notsupp(struct socket *so)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_listen_notsupp(struct socket *so, int backlog, struct thread *td)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_peeraddr_notsupp(struct socket *so, struct sockaddr **nam)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_rcvd_notsupp(struct socket *so, int flags)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_rcvoob_notsupp(struct socket *so, struct mbuf *m, int flags)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_send_notsupp(struct socket *so, int flags, struct mbuf *m,
+    struct sockaddr *addr, struct mbuf *control, struct thread *td)
+{
+       if (control != NULL)
+               m_freem(control);
+       if ((flags & PRUS_NOTREADY) == 0)
+               m_freem(m);
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_ready_notsupp(struct socket *so, struct mbuf *m, int count)
+{
+       return (EOPNOTSUPP);
+}
+
 /*
- * Dummy protocol specific user requests function pointer array.
- * All functions return EOPNOTSUPP.
+ * This isn't really a ``null'' operation, but it's the default one and
+ * doesn't do anything destructive.
  */
-struct pr_usrreqs nousrreqs = {
-       .pru_accept =           pru_accept_notsupp,
-       .pru_attach =           pru_attach_notsupp,
-       .pru_bind =             pru_bind_notsupp,
-       .pru_connect =          pru_connect_notsupp,
-       .pru_connect2 =         pru_connect2_notsupp,
-       .pru_control =          pru_control_notsupp,
-       .pru_disconnect =       pru_disconnect_notsupp,
-       .pru_listen =           pru_listen_notsupp,
-       .pru_peeraddr =         pru_peeraddr_notsupp,
-       .pru_rcvd =             pru_rcvd_notsupp,
-       .pru_rcvoob =           pru_rcvoob_notsupp,
-       .pru_send =             pru_send_notsupp,
-       .pru_sense =            pru_sense_null,
-       .pru_shutdown =         pru_shutdown_notsupp,
-       .pru_sockaddr =         pru_sockaddr_notsupp,
-       .pru_sosend =           pru_sosend_notsupp,
-       .pru_soreceive =        pru_soreceive_notsupp,
-       .pru_sopoll =           pru_sopoll_notsupp,
-};
+static int
+pr_sense_notsupp(struct socket *so, struct stat *sb)
+{
+       sb->st_blksize = so->so_snd.sb_hiwat;
+       return (0);
+}
 
-static void
-pr_usrreqs_init(struct protosw *pr)
+static int
+pr_shutdown_notsupp(struct socket *so)
 {
-       struct pr_usrreqs *pu;
+       return (EOPNOTSUPP);
+}
 
-       pu = pr->pr_usrreqs;
-       KASSERT(pu != NULL, ("%s: %ssw[%d] has no usrreqs!", __func__,
-           pr->pr_domain->dom_name,
-           (int)(pr - pr->pr_domain->dom_protosw)));
+static int
+pr_sockaddr_notsupp(struct socket *so, struct sockaddr **nam)
+{
+       return (EOPNOTSUPP);
+}
 
-       /*
-        * Protocol switch methods fall into three categories: mandatory,
-        * mandatory but protosw_init() provides a default, and optional.
-        *
-        * For true protocols (i.e., pru_attach != NULL), KASSERT truly
-        * mandatory methods with no defaults, and initialize defaults for
-        * other mandatory methods if the protocol hasn't defined an
-        * implementation (NULL function pointer).
-        */
-#if 0
-       if (pu->pru_attach != NULL) {
-               KASSERT(pu->pru_abort != NULL,
-                   ("protosw_init: %ssw[%d] pru_abort NULL",
-                   pr->pr_domain->dom_name,
-                   (int)(pr - pr->pr_domain->dom_protosw)));
-               KASSERT(pu->pru_send != NULL,
-                   ("protosw_init: %ssw[%d] pru_send NULL",
-                   pr->pr_domain->dom_name,
-                   (int)(pr - pr->pr_domain->dom_protosw)));
-       }
-#endif
+static int
+pr_sosend_notsupp(struct socket *so, struct sockaddr *addr, struct uio *uio,
+    struct mbuf *top, struct mbuf *control, int flags, struct thread *td)
+{
+       return (EOPNOTSUPP);
+}
 
-#define DEFAULT(foo, bar)      if ((foo) == NULL)  (foo) = (bar)
-       DEFAULT(pu->pru_accept, pru_accept_notsupp);
-       DEFAULT(pu->pru_aio_queue, pru_aio_queue_notsupp);
-       DEFAULT(pu->pru_bind, pru_bind_notsupp);
-       DEFAULT(pu->pru_bindat, pru_bindat_notsupp);
-       DEFAULT(pu->pru_connect, pru_connect_notsupp);
-       DEFAULT(pu->pru_connect2, pru_connect2_notsupp);
-       DEFAULT(pu->pru_connectat, pru_connectat_notsupp);
-       DEFAULT(pu->pru_control, pru_control_notsupp);
-       DEFAULT(pu->pru_disconnect, pru_disconnect_notsupp);
-       DEFAULT(pu->pru_listen, pru_listen_notsupp);
-       DEFAULT(pu->pru_peeraddr, pru_peeraddr_notsupp);
-       DEFAULT(pu->pru_rcvd, pru_rcvd_notsupp);
-       DEFAULT(pu->pru_rcvoob, pru_rcvoob_notsupp);
-       DEFAULT(pu->pru_sense, pru_sense_null);
-       DEFAULT(pu->pru_shutdown, pru_shutdown_notsupp);
-       DEFAULT(pu->pru_sockaddr, pru_sockaddr_notsupp);
-       DEFAULT(pu->pru_sosend, sosend_generic);
-       DEFAULT(pu->pru_soreceive, soreceive_generic);
-       DEFAULT(pu->pru_sopoll, sopoll_generic);
-       DEFAULT(pu->pru_ready, pru_ready_notsupp);
-#undef DEFAULT
+static int
+pr_soreceive_notsupp(struct socket *so, struct sockaddr **paddr,
+    struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
+{
+       return (EOPNOTSUPP);
+}
+
+static int
+pr_sopoll_notsupp(struct socket *so, int events, struct ucred *cred,
+    struct thread *td)
+{
+       return (EOPNOTSUPP);
+}
+
+static void
+pr_init(struct protosw *pr)
+{
+
+       KASSERT(pr->pr_attach != NULL,
+           ("%s: protocol doesn't have pr_attach", __func__));
+
+#define        DEFAULT(foo, bar)       if (pr->foo == NULL) pr->foo = bar
+       DEFAULT(pr_sosend, sosend_generic);
+       DEFAULT(pr_soreceive, soreceive_generic);
+       DEFAULT(pr_sopoll, sopoll_generic);
+
+#define NOTSUPP(foo)   if (pr->foo == NULL)  pr->foo = foo ## _notsupp
+       NOTSUPP(pr_accept);
+       NOTSUPP(pr_aio_queue);
+       NOTSUPP(pr_bind);
+       NOTSUPP(pr_bindat);
+       NOTSUPP(pr_connect);
+       NOTSUPP(pr_connect2);
+       NOTSUPP(pr_connectat);
+       NOTSUPP(pr_control);
+       NOTSUPP(pr_disconnect);
+       NOTSUPP(pr_listen);
+       NOTSUPP(pr_peeraddr);
+       NOTSUPP(pr_rcvd);
+       NOTSUPP(pr_rcvoob);
+       NOTSUPP(pr_send);
+       NOTSUPP(pr_sense);
+       NOTSUPP(pr_shutdown);
+       NOTSUPP(pr_sockaddr);
+       NOTSUPP(pr_sosend);
+       NOTSUPP(pr_soreceive);
+       NOTSUPP(pr_sopoll);
+       NOTSUPP(pr_ready);
 }
 
 /*
@@ -176,9 +274,11 @@ domain_init(void *arg)
                return;
        MPASS((flags & DOMF_INITED) == 0);
 
-       for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
-               pr_usrreqs_init(pr);
-       }
+       for (int i = 0; i < dp->dom_nprotosw; i++)
+               if ((pr = dp->dom_protosw[i]) != NULL) {
+                       pr->pr_domain = dp;
+                       pr_init(pr);
+               }
 
        /*
         * update global information about maximums
@@ -288,9 +388,10 @@ pffindtype(int family, int type)
        if (dp == NULL)
                return (NULL);
 
-       for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
-               if (pr->pr_type && pr->pr_type == type)
+       for (int i = 0; i < dp->dom_nprotosw; i++)
+               if ((pr = dp->dom_protosw[i]) != NULL && pr->pr_type == type)
                        return (pr);
+
        return (NULL);
 }
 
@@ -301,18 +402,18 @@ pffindproto(int family, int protocol, int type)
        struct protosw *pr;
        struct protosw *maybe;
 
-       maybe = NULL;
-       if (family == 0)
-               return (NULL);
-
        dp = pffinddomain(family);
        if (dp == NULL)
                return (NULL);
 
-       for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
+       maybe = NULL;
+       for (int i = 0; i < dp->dom_nprotosw; i++) {
+               if ((pr = dp->dom_protosw[i]) == NULL)
+                       continue;
                if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
                        return (pr);
 
+               /* XXX: raw catches all. Why? */
                if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
                    pr->pr_protocol == 0 && maybe == NULL)
                        maybe = pr;
@@ -325,60 +426,49 @@ pffindproto(int family, int protocol, int type)
  * accept requests before it is registered.
  */
 int
-pf_proto_register(int family, struct protosw *npr)
+protosw_register(struct domain *dp, struct protosw *npr)
 {
-       struct domain *dp;
-       struct protosw *pr, *fpr;
-
-       /* Sanity checks. */
-       if (family == 0)
-               return (EPFNOSUPPORT);
-       if (npr->pr_type == 0)
-               return (EPROTOTYPE);
-       if (npr->pr_protocol == 0)
-               return (EPROTONOSUPPORT);
-       if (npr->pr_usrreqs == NULL)
-               return (ENXIO);
-
-       /* Try to find the specified domain based on the family. */
-       dp = pffinddomain(family);
-       if (dp == NULL)
-               return (EPFNOSUPPORT);
+       struct protosw **prp;
 
-       /* Initialize backpointer to struct domain. */
-       npr->pr_domain = dp;
-       fpr = NULL;
+       MPASS(dp);
+       MPASS(npr && npr->pr_type > 0 && npr->pr_protocol > 0);
 
+       prp = NULL;
        /*
         * Protect us against races when two protocol registrations for
         * the same protocol happen at the same time.
         */
        mtx_lock(&dom_mtx);
+       for (int i = 0; i < dp->dom_nprotosw; i++) {
+               if (dp->dom_protosw[i] == NULL) {
+                       /* Remember the first free spacer. */
+                       if (prp == NULL)
+                               prp = &dp->dom_protosw[i];
+               } else {
+                       /*
+                        * The new protocol must not yet exist.
+                        * XXXAO: Check only protocol?
+                        * XXXGL: Maybe assert that it doesn't exist?
+                        */
+                       if ((dp->dom_protosw[i]->pr_type == npr->pr_type) &&
+                           (dp->dom_protosw[i]->pr_protocol ==
+                           npr->pr_protocol)) {
+                               mtx_unlock(&dom_mtx);
+                               return (EEXIST);
+                       }
 
-       /* The new protocol must not yet exist. */
-       for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
-               if ((pr->pr_type == npr->pr_type) &&
-                   (pr->pr_protocol == npr->pr_protocol)) {
-                       mtx_unlock(&dom_mtx);
-                       return (EEXIST);        /* XXX: Check only protocol? */
                }
-               /* While here, remember the first free spacer. */
-               if ((fpr == NULL) && (pr->pr_protocol == PROTO_SPACER))
-                       fpr = pr;
        }
 
        /* If no free spacer is found we can't add the new protocol. */
-       if (fpr == NULL) {
+       if (prp == NULL) {
                mtx_unlock(&dom_mtx);
                return (ENOMEM);
        }
 
-       /* Copy the new struct protosw over the spacer. */
-       bcopy(npr, fpr, sizeof(*fpr));
-
-       pr_usrreqs_init(fpr);
-
-       /* Job is done, no more protection required. */
+       npr->pr_domain = dp;
+       pr_init(npr);
+       *prp = npr;
        mtx_unlock(&dom_mtx);
 
        return (0);
@@ -389,55 +479,33 @@ pf_proto_register(int family, struct protosw *npr)
  * all sockets and release all locks and memory references.
  */
 int
-pf_proto_unregister(int family, int protocol, int type)
+protosw_unregister(struct protosw *pr)
 {
        struct domain *dp;
-       struct protosw *pr, *dpr;
+       struct protosw **prp;
 
-       /* Sanity checks. */
-       if (family == 0)
-               return (EPFNOSUPPORT);
-       if (protocol == 0)
-               return (EPROTONOSUPPORT);
-       if (type == 0)
-               return (EPROTOTYPE);
+       dp = pr->pr_domain;
+       prp = NULL;
 
-       /* Try to find the specified domain based on the family type. */
-       dp = pffinddomain(family);
-       if (dp == NULL)
-               return (EPFNOSUPPORT);
-
-       dpr = NULL;
-
-       /* Lock out everyone else while we are manipulating the protosw. */
        mtx_lock(&dom_mtx);
-
        /* The protocol must exist and only once. */
-       for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
-               if ((pr->pr_type == type) && (pr->pr_protocol == protocol)) {
-                       if (dpr != NULL) {
-                               mtx_unlock(&dom_mtx);
-                               return (EMLINK);   /* Should not happen! */
-                       } else
-                               dpr = pr;
+       for (int i = 0; i < dp->dom_nprotosw; i++) {
+               if (dp->dom_protosw[i] == pr) {
+                       KASSERT(prp == NULL,
+                           ("%s: domain %p protocol %p registered twice\n",
+                           __func__, dp, pr));
+                       prp = &dp->dom_protosw[i];
                }
        }
 
-       /* Protocol does not exist. */
-       if (dpr == NULL) {
+       /* Protocol does not exist.  XXXGL: assert that it does? */
+       if (prp == NULL) {
                mtx_unlock(&dom_mtx);
                return (EPROTONOSUPPORT);
        }
 
        /* De-orbit the protocol and make the slot available again. */
-       dpr->pr_type = 0;
-       dpr->pr_domain = dp;
-       dpr->pr_protocol = PROTO_SPACER;
-       dpr->pr_flags = 0;
-       dpr->pr_ctloutput = NULL;
-       dpr->pr_usrreqs = &nousrreqs;
-
-       /* Job is done, not more protection required. */
+       *prp = NULL;
        mtx_unlock(&dom_mtx);
 
        return (0);
diff --git a/sys/kern/uipc_ktls.c b/sys/kern/uipc_ktls.c
index 5855e62bd983..ff20b3652407 100644
--- a/sys/kern/uipc_ktls.c
+++ b/sys/kern/uipc_ktls.c
@@ -2366,7 +2366,7 @@ ktls_decrypt(struct socket *so)
                        counter_u64_add(ktls_offload_corrupted_records, 1);
 
                        CURVNET_SET(so->so_vnet);
-                       so->so_proto->pr_usrreqs->pru_abort(so);
+                       so->so_proto->pr_abort(so);
                        so->so_error = error;
                        CURVNET_RESTORE();
                        goto deref;
@@ -2890,9 +2890,9 @@ ktls_encrypt(struct ktls_wq *wq, struct mbuf *top)
 
        CURVNET_SET(so->so_vnet);
        if (error == 0) {
-               (void)(*so->so_proto->pr_usrreqs->pru_ready)(so, top, npages);
+               (void)so->so_proto->pr_ready(so, top, npages);
        } else {
-               so->so_proto->pr_usrreqs->pru_abort(so);
+               so->so_proto->pr_abort(so);
                so->so_error = EIO;
                mb_free_notready(top, total_pages);
        }
@@ -2934,9 +2934,9 @@ ktls_encrypt_cb(struct ktls_ocf_encrypt_state *state, int 
error)
        npages = m->m_epg_nrdy;
 
        if (error == 0) {
-               (void)(*so->so_proto->pr_usrreqs->pru_ready)(so, m, npages);
+               (void)so->so_proto->pr_ready(so, m, npages);
        } else {
-               so->so_proto->pr_usrreqs->pru_abort(so);
+               so->so_proto->pr_abort(so);
                so->so_error = EIO;
                mb_free_notready(m, npages);
        }
@@ -3001,7 +3001,7 @@ ktls_encrypt_async(struct ktls_wq *wq, struct mbuf *top)
 
        CURVNET_SET(so->so_vnet);
        if (error != 0) {
-               so->so_proto->pr_usrreqs->pru_abort(so);
+               so->so_proto->pr_abort(so);
                so->so_error = EIO;
                mb_free_notready(m, total_pages - npages);
        }
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index bbca2d8663d7..bf22c0245f24 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -523,9 +523,8 @@ socreate(int dom, struct socket **aso, int type, int proto,
                        return (EPROTOTYPE);
                return (EPROTONOSUPPORT);
        }
-       if (prp->pr_usrreqs->pru_attach == NULL ||
-           prp->pr_usrreqs->pru_attach == pru_attach_notsupp)
-               return (EPROTONOSUPPORT);
+
+       MPASS(prp->pr_attach);
 
        if (IN_CAPABILITY_MODE(td) && (prp->pr_flags & PR_CAPATTACH) == 0)
                return (ECAPMODE);
@@ -564,7 +563,7 @@ socreate(int dom, struct socket **aso, int type, int proto,
         * the appropriate flags must be set in the pru_attach function.
         */
        CURVNET_SET(so->so_vnet);
-       error = (*prp->pr_usrreqs->pru_attach)(so, proto, td);
+       error = prp->pr_attach(so, proto, td);
        CURVNET_RESTORE();
        if (error) {
                sodealloc(so);
@@ -789,9 +788,9 @@ sonewconn(struct socket *head, int connstatus)
        if ((so = solisten_clone(head)) == NULL)
                return (NULL);
 
-       if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) {
+       if (so->so_proto->pr_attach(so, 0, NULL) != 0) {
                sodealloc(so);
-               log(LOG_DEBUG, "%s: pcb %p: pru_attach() failed\n",
+               log(LOG_DEBUG, "%s: pcb %p: pr_attach() failed\n",
                    __func__, head->so_pcb);
                return (NULL);
        }
@@ -894,7 +893,7 @@ sopeeloff(struct socket *head)
                    __func__, head->so_pcb);
                return (NULL);
        }
-       if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) {
+       if ((*so->so_proto->pr_attach)(so, 0, NULL)) {
                sodealloc(so);
                log(LOG_DEBUG, "%s: pcb %p: pru_attach() failed\n",
                    __func__, head->so_pcb);
@@ -919,7 +918,7 @@ sobind(struct socket *so, struct sockaddr *nam, struct 
thread *td)
        int error;
 
        CURVNET_SET(so->so_vnet);
-       error = (*so->so_proto->pr_usrreqs->pru_bind)(so, nam, td);
+       error = so->so_proto->pr_bind(so, nam, td);
        CURVNET_RESTORE();
        return (error);
 }
@@ -930,7 +929,7 @@ sobindat(int fd, struct socket *so, struct sockaddr *nam, 
struct thread *td)
        int error;
 
        CURVNET_SET(so->so_vnet);
-       error = (*so->so_proto->pr_usrreqs->pru_bindat)(fd, so, nam, td);
+       error = so->so_proto->pr_bindat(fd, so, nam, td);
        CURVNET_RESTORE();
        return (error);
 }
@@ -953,7 +952,7 @@ solisten(struct socket *so, int backlog, struct thread *td)
        int error;
 
        CURVNET_SET(so->so_vnet);
-       error = (*so->so_proto->pr_usrreqs->pru_listen)(so, backlog, td);
+       error = so->so_proto->pr_listen(so, backlog, td);
        CURVNET_RESTORE();
        return (error);
 }
@@ -1178,8 +1177,8 @@ sofree(struct socket *so)
                MPASS(pr->pr_domain->dom_dispose != NULL);
                (*pr->pr_domain->dom_dispose)(so);
        }
-       if (pr->pr_usrreqs->pru_detach != NULL)
-               (*pr->pr_usrreqs->pru_detach)(so);
+       if (pr->pr_detach != NULL)
+               pr->pr_detach(so);
 
        /*
         * From this point on, we assume that no other references to this
@@ -1253,8 +1252,8 @@ soclose(struct socket *so)
        }
 
 drop:
-       if (so->so_proto->pr_usrreqs->pru_close != NULL)
-               (*so->so_proto->pr_usrreqs->pru_close)(so);
+       if (so->so_proto->pr_close != NULL)
+               so->so_proto->pr_close(so);
 
        SOCK_LOCK(so);
        if ((listening = SOLISTENING(so))) {
@@ -1314,8 +1313,8 @@ soabort(struct socket *so)
 
        VNET_SO_ASSERT(so);
 
-       if (so->so_proto->pr_usrreqs->pru_abort != NULL)
-               (*so->so_proto->pr_usrreqs->pru_abort)(so);
+       if (so->so_proto->pr_abort != NULL)
+               so->so_proto->pr_abort(so);
        SOCK_LOCK(so);
        sorele_locked(so);
 }
@@ -1326,7 +1325,7 @@ soaccept(struct socket *so, struct sockaddr **nam)
        int error;
 
        CURVNET_SET(so->so_vnet);
-       error = (*so->so_proto->pr_usrreqs->pru_accept)(so, nam);
+       error = so->so_proto->pr_accept(so, nam);
        CURVNET_RESTORE();
        return (error);
 }
@@ -1360,11 +1359,9 @@ soconnectat(int fd, struct socket *so, struct sockaddr 
*nam, struct thread *td)
                 */
                so->so_error = 0;
                if (fd == AT_FDCWD) {
-                       error = (*so->so_proto->pr_usrreqs->pru_connect)(so,
-                           nam, td);
+                       error = so->so_proto->pr_connect(so, nam, td);
                } else {
-                       error = (*so->so_proto->pr_usrreqs->pru_connectat)(fd,
-                           so, nam, td);
+                       error = so->so_proto->pr_connectat(fd, so, nam, td);
                }
        }
        CURVNET_RESTORE();
@@ -1378,7 +1375,7 @@ soconnect2(struct socket *so1, struct socket *so2)
        int error;
 
        CURVNET_SET(so1->so_vnet);
-       error = (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2);
+       error = so1->so_proto->pr_connect2(so1, so2);
        CURVNET_RESTORE();
        return (error);
 }
@@ -1393,7 +1390,7 @@ sodisconnect(struct socket *so)
        if (so->so_state & SS_ISDISCONNECTING)
                return (EALREADY);
        VNET_SO_ASSERT(so);
-       error = (*so->so_proto->pr_usrreqs->pru_disconnect)(so);
+       error = so->so_proto->pr_disconnect(so);
        return (error);
 }
 
*** 2768 LINES SKIPPED ***

Reply via email to