The branch main has been updated by glebius:

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

commit caf32b260ad46b17a4c1a8ce6383e37ac489f023
Author:     Gleb Smirnoff <[email protected]>
AuthorDate: 2023-02-14 18:02:49 +0000
Commit:     Gleb Smirnoff <[email protected]>
CommitDate: 2023-02-14 18:02:49 +0000

    pfil: add pfil_mem_{in,out}() and retire pfil_run_hooks()
    
    The 0b70e3e78b0 changed the original design of a single entry point
    into pfil(9) chains providing separate functions for the filtering
    points that always provide mbufs and know the direction of a flow.
    The motivation was to reduce branching.  The logical continuation
    would be to do the same for the filtering points that always provide
    a memory pointer and retire the single entry point.
    
    o Hooks now provide two functions: one for mbufs and optional for
      memory pointers.
    o pfil_hook_args() has a new member and pfil_add_hook() has a
      requirement to zero out uninitialized data. Bump PFIL_VERSION.
    o As it was before, a hook function for a memory pointer may realloc
      into an mbuf.  Such mbuf would be returned via a pointer that must
      be provided in argument.
    o The only hook that supports memory pointers is ipfw:default-link.
      It is rewritten to provide two functions.
    o All remaining uses of pfil_run_hooks() are converted to
      pfil_mem_in().
    o Transparent union of pfil_packet_t and tricks to fix pointer
      alignment are retired. Internal pfil_realloc() reduces down to
      m_devget() and thus is retired, too.
    
    Reviewed by:            mjg, ocochard
    Differential revision:  https://reviews.freebsd.org/D37977
---
 sys/dev/cxgbe/t4_sge.c                        |   4 +-
 sys/dev/mlx5/mlx5_en/mlx5_en_rx.c             |   6 +-
 sys/net/iflib.c                               |   5 +-
 sys/net/pfil.c                                | 122 +++++++++---------
 sys/net/pfil.h                                |  51 +++-----
 sys/netinet/siftr.c                           |  26 ++--
 sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c |  30 ++---
 sys/netpfil/ipfw/ip_fw_pfil.c                 | 171 ++++++++++++++++----------
 sys/netpfil/pf/pf_ioctl.c                     |  44 ++++---
 9 files changed, 233 insertions(+), 226 deletions(-)

diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index 8dbb9e1fe93a..88a7f44cadb7 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -1998,8 +1998,7 @@ eth_rx(struct adapter *sc, struct sge_rxq *rxq, const 
struct iq_desc *d,
                    sc->params.sge.fl_pktshift;
                frame = sd->cl + fl->rx_offset + sc->params.sge.fl_pktshift;
                CURVNET_SET_QUIET(ifp->if_vnet);
-               rc = pfil_run_hooks(vi->pfil, frame, ifp,
-                   slen | PFIL_MEMPTR | PFIL_IN, NULL);
+               rc = pfil_mem_in(vi->pfil, frame, slen, ifp, &m0);
                CURVNET_RESTORE();
                if (rc == PFIL_DROPPED || rc == PFIL_CONSUMED) {
                        skip_fl_payload(sc, fl, plen);
@@ -2007,7 +2006,6 @@ eth_rx(struct adapter *sc, struct sge_rxq *rxq, const 
struct iq_desc *d,
                }
                if (rc == PFIL_REALLOCED) {
                        skip_fl_payload(sc, fl, plen);
-                       m0 = pfil_mem2mbuf(frame);
                        goto have_mbuf;
                }
        }
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c 
b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
index f6caddfdf933..4b1fb25e0f82 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
@@ -536,9 +536,8 @@ mlx5e_poll_rx_cq(struct mlx5e_rq *rq, int budget)
                }
                if (pfil != NULL && PFIL_HOOKED_IN(pfil)) {
                        seglen = MIN(byte_cnt, MLX5E_MAX_RX_BYTES);
-                       rv = pfil_run_hooks(rq->channel->priv->pfil,
-                           rq->mbuf[wqe_counter].data, rq->ifp,
-                           seglen | PFIL_MEMPTR | PFIL_IN, NULL);
+                       rv = pfil_mem_in(rq->channel->priv->pfil,
+                           rq->mbuf[wqe_counter].data, seglen, rq->ifp, &mb);
 
                        switch (rv) {
                        case PFIL_DROPPED:
@@ -556,7 +555,6 @@ mlx5e_poll_rx_cq(struct mlx5e_rq *rq, int budget)
                                 * and receive the new mbuf allocated
                                 * by the Filter
                                 */
-                               mb = pfil_mem2mbuf(rq->mbuf[wqe_counter].data);
                                goto rx_common;
                        default:
                                /*
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index 0a500f8e2810..39f3ccea4317 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -2732,8 +2732,7 @@ rxd_frag_to_sd(iflib_rxq_t rxq, if_rxd_frag_t irf, bool 
unload, if_rxsd_t sd,
                payload  = *sd->ifsd_cl;
                payload +=  ri->iri_pad;
                len = ri->iri_len - ri->iri_pad;
-               *pf_rv = pfil_run_hooks(rxq->pfil, payload, ri->iri_ifp,
-                   len | PFIL_MEMPTR | PFIL_IN, NULL);
+               *pf_rv = pfil_mem_in(rxq->pfil, payload, len, ri->iri_ifp, &m);
                switch (*pf_rv) {
                case PFIL_DROPPED:
                case PFIL_CONSUMED:
@@ -2746,8 +2745,8 @@ rxd_frag_to_sd(iflib_rxq_t rxq, if_rxd_frag_t irf, bool 
unload, if_rxsd_t sd,
                case PFIL_REALLOCED:
                        /*
                         * The filter copied it.  Everything is recycled.
+                        * 'm' points at new mbuf.
                         */
-                       m = pfil_mem2mbuf(payload);
                        unload = 0;
                        break;
                case PFIL_PASS:
diff --git a/sys/net/pfil.c b/sys/net/pfil.c
index b68fbe8db5c5..e6f3ff8c1269 100644
--- a/sys/net/pfil.c
+++ b/sys/net/pfil.c
@@ -70,7 +70,8 @@ MTX_SYSINIT(pfil_mtxinit, &pfil_lock, "pfil(9) lock", 
MTX_DEF);
 #define        PFIL_LOCK_ASSERT()      mtx_assert(&pfil_lock, MA_OWNED)
 
 struct pfil_hook {
-       pfil_func_t      hook_func;
+       pfil_mbuf_chk_t  hook_mbuf_chk;
+       pfil_mem_chk_t   hook_mem_chk;
        void            *hook_ruleset;
        int              hook_flags;
        int              hook_links;
@@ -82,7 +83,8 @@ struct pfil_hook {
 
 struct pfil_link {
        CK_STAILQ_ENTRY(pfil_link) link_chain;
-       pfil_func_t              link_func;
+       pfil_mbuf_chk_t          link_mbuf_chk;
+       pfil_mem_chk_t           link_mem_chk;
        void                    *link_ruleset;
        int                      link_flags;
        struct pfil_hook        *link_hook;
@@ -114,92 +116,86 @@ VNET_DEFINE_STATIC(struct pfilhookhead, pfil_hook_list) =
 static struct pfil_link *pfil_link_remove(pfil_chain_t *, pfil_hook_t );
 static void pfil_link_free(epoch_context_t);
 
-int
-pfil_realloc(pfil_packet_t *p, int flags, struct ifnet *ifp)
-{
-       struct mbuf *m;
-
-       MPASS(flags & PFIL_MEMPTR);
-
-       if ((m = m_devget(p->mem, PFIL_LENGTH(flags), 0, ifp, NULL)) == NULL)
-               return (ENOMEM);
-       *p = pfil_packet_align(*p);
-       *p->m = m;
-
-       return (0);
-}
-
+/*
+ * To couple a filtering point that provides memory pointer with a filter that
+ * works on mbufs only.
+ */
 static __noinline int
-pfil_fake_mbuf(pfil_func_t func, pfil_packet_t *p, struct ifnet *ifp, int 
flags,
-    void *ruleset, struct inpcb *inp)
+pfil_fake_mbuf(pfil_mbuf_chk_t func, void *mem, u_int len, struct ifnet *ifp,
+    int flags, void *ruleset, struct mbuf **mp)
 {
-       struct mbuf m, *mp;
+       struct mbuf m;
        pfil_return_t rv;
 
        (void)m_init(&m, M_NOWAIT, MT_DATA, M_NOFREE | M_PKTHDR);
-       m_extadd(&m, p->mem, PFIL_LENGTH(flags), NULL, NULL, NULL, 0,
-           EXT_RXRING);
-       m.m_len = m.m_pkthdr.len = PFIL_LENGTH(flags);
-       mp = &m;
-       flags &= ~(PFIL_MEMPTR | PFIL_LENMASK);
-
-       rv = func(&mp, ifp, flags, ruleset, inp);
-       if (rv == PFIL_PASS && mp != &m) {
+       m_extadd(&m, mem, len, NULL, NULL, NULL, 0, EXT_RXRING);
+       m.m_len = m.m_pkthdr.len = len;
+       *mp = &m;
+
+       rv = func(mp, ifp, flags, ruleset, NULL);
+       if (rv == PFIL_PASS && *mp != &m) {
                /*
                 * Firewalls that need pfil_fake_mbuf() most likely don't
                 * know they need return PFIL_REALLOCED.
                 */
                rv = PFIL_REALLOCED;
-               *p = pfil_packet_align(*p);
-               *p->m = mp;
        }
 
        return (rv);
 }
 
-/*
- * pfil_run_hooks() runs the specified packet filter hook chain.
- */
-int
-pfil_run_hooks(struct pfil_head *head, pfil_packet_t p, struct ifnet *ifp,
-    int flags, struct inpcb *inp)
+static __always_inline int
+pfil_mem_common(pfil_chain_t *pch, void *mem, u_int len, int flags,
+    struct ifnet *ifp, struct mbuf **m)
 {
-       pfil_chain_t *pch;
        struct pfil_link *link;
        pfil_return_t rv;
        bool realloc = false;
 
        NET_EPOCH_ASSERT();
-
-       if (PFIL_DIR(flags) == PFIL_IN)
-               pch = &head->head_in;
-       else if (__predict_true(PFIL_DIR(flags) == PFIL_OUT))
-               pch = &head->head_out;
-       else
-               panic("%s: bogus flags %d", __func__, flags);
+       KASSERT(flags == PFIL_IN || flags == PFIL_OUT,
+           ("%s: unsupported flags %d", __func__, flags));
 
        rv = PFIL_PASS;
        CK_STAILQ_FOREACH(link, pch, link_chain) {
-               if ((flags & PFIL_MEMPTR) && !(link->link_flags & PFIL_MEMPTR))
-                       rv = pfil_fake_mbuf(link->link_func, &p, ifp, flags,
-                           link->link_ruleset, inp);
+               if (__predict_true(link->link_mem_chk != NULL && !realloc))
+                       rv = link->link_mem_chk(mem, len, flags, ifp,
+                           link->link_ruleset, m);
+               else if (!realloc)
+                       rv = pfil_fake_mbuf(link->link_mbuf_chk, mem, len, ifp,
+                           flags, link->link_ruleset, m);
                else
-                       rv = (*link->link_func)(p, ifp, flags,
-                           link->link_ruleset, inp);
+                       rv = link->link_mbuf_chk(m, ifp, flags,
+                           link->link_ruleset, NULL);
+
                if (rv == PFIL_DROPPED || rv == PFIL_CONSUMED)
                        break;
-               else if (rv == PFIL_REALLOCED) {
-                       flags &= ~(PFIL_MEMPTR | PFIL_LENMASK);
+               else if (rv == PFIL_REALLOCED)
                        realloc = true;
-               }
        }
        if (realloc && rv == PFIL_PASS)
                rv = PFIL_REALLOCED;
        return (rv);
 }
 
+int
+pfil_mem_in(struct pfil_head *head, void *mem, u_int len, struct ifnet *ifp,
+    struct mbuf **m)
+{
+
+       return (pfil_mem_common(&head->head_in, mem, len, PFIL_IN, ifp, m));
+}
+
+int
+pfil_mem_out(struct pfil_head *head, void *mem, u_int len, struct ifnet *ifp,
+    struct mbuf **m)
+{
+
+       return (pfil_mem_common(&head->head_out, mem, len, PFIL_OUT, ifp, m));
+}
+
 static __always_inline int
-pfil_mbuf_common(pfil_chain_t *pch, pfil_packet_t p, struct ifnet *ifp,
+pfil_mbuf_common(pfil_chain_t *pch, struct mbuf **m, struct ifnet *ifp,
     int flags, struct inpcb *inp)
 {
        struct pfil_link *link;
@@ -211,7 +207,8 @@ pfil_mbuf_common(pfil_chain_t *pch, pfil_packet_t p, struct 
ifnet *ifp,
 
        rv = PFIL_PASS;
        CK_STAILQ_FOREACH(link, pch, link_chain) {
-               rv = (*link->link_func)(p, ifp, flags, link->link_ruleset, inp);
+               rv = link->link_mbuf_chk(m, ifp, flags, link->link_ruleset,
+                   inp);
                if (rv == PFIL_DROPPED || rv == PFIL_CONSUMED)
                        break;
        }
@@ -219,19 +216,19 @@ pfil_mbuf_common(pfil_chain_t *pch, pfil_packet_t p, 
struct ifnet *ifp,
 }
 
 int
-pfil_mbuf_in(struct pfil_head *head, pfil_packet_t p, struct ifnet *ifp,
+pfil_mbuf_in(struct pfil_head *head, struct mbuf **m, struct ifnet *ifp,
    struct inpcb *inp)
 {
 
-       return (pfil_mbuf_common(&head->head_in, p, ifp, PFIL_IN, inp));
+       return (pfil_mbuf_common(&head->head_in, m, ifp, PFIL_IN, inp));
 }
 
 int
-pfil_mbuf_out(struct pfil_head *head, pfil_packet_t p, struct ifnet *ifp,
+pfil_mbuf_out(struct pfil_head *head, struct mbuf **m, struct ifnet *ifp,
     struct inpcb *inp)
 {
 
-       return (pfil_mbuf_common(&head->head_out, p, ifp, PFIL_OUT, inp));
+       return (pfil_mbuf_common(&head->head_out, m, ifp, PFIL_OUT, inp));
 }
 
 /*
@@ -298,7 +295,8 @@ pfil_add_hook(struct pfil_hook_args *pa)
        MPASS(pa->pa_version == PFIL_VERSION);
 
        hook = malloc(sizeof(struct pfil_hook), M_PFIL, M_WAITOK | M_ZERO);
-       hook->hook_func = pa->pa_func;
+       hook->hook_mbuf_chk = pa->pa_mbuf_chk;
+       hook->hook_mem_chk = pa->pa_mem_chk;
        hook->hook_ruleset = pa->pa_ruleset;
        hook->hook_flags = pa->pa_flags;
        hook->hook_type = pa->pa_type;
@@ -416,7 +414,8 @@ pfil_link(struct pfil_link_args *pa)
 
        if (pa->pa_flags & PFIL_IN) {
                in->link_hook = hook;
-               in->link_func = hook->hook_func;
+               in->link_mbuf_chk = hook->hook_mbuf_chk;
+               in->link_mem_chk = hook->hook_mem_chk;
                in->link_flags = hook->hook_flags;
                in->link_ruleset = hook->hook_ruleset;
                if (pa->pa_flags & PFIL_APPEND)
@@ -428,7 +427,8 @@ pfil_link(struct pfil_link_args *pa)
        }
        if (pa->pa_flags & PFIL_OUT) {
                out->link_hook = hook;
-               out->link_func = hook->hook_func;
+               out->link_mbuf_chk = hook->hook_mbuf_chk;
+               out->link_mem_chk = hook->hook_mem_chk;
                out->link_flags = hook->hook_flags;
                out->link_ruleset = hook->hook_ruleset;
                if (pa->pa_flags & PFIL_APPEND)
diff --git a/sys/net/pfil.h b/sys/net/pfil.h
index d5e9eadd8b8c..b99ec6896266 100644
--- a/sys/net/pfil.h
+++ b/sys/net/pfil.h
@@ -82,41 +82,16 @@ struct pfilioc_link {
 #define        PFIL_OUT        0x00020000
 /* UNUSED              0x00040000 */
 #define        PFIL_DIR(f)     ((f) & (PFIL_IN|PFIL_OUT))
-#define        PFIL_MEMPTR     0x00080000
 #define        PFIL_HEADPTR    0x00100000
 #define        PFIL_HOOKPTR    0x00200000
 #define        PFIL_APPEND     0x00400000
 #define        PFIL_UNLINK     0x00800000
-#define        PFIL_LENMASK    0x0000ffff
-#define        PFIL_LENGTH(f)  ((f) & PFIL_LENMASK)
 
 #ifdef _KERNEL
 struct mbuf;
 struct ifnet;
 struct inpcb;
 
-typedef union {
-       struct mbuf     **m;
-       void            *mem;
-       uintptr_t       __ui;
-} pfil_packet_t __attribute__((__transparent_union__));
-
-static inline pfil_packet_t
-pfil_packet_align(pfil_packet_t p)
-{
-
-       return ((pfil_packet_t ) (((uintptr_t)(p).mem +
-           (_Alignof(void *) - 1)) & - _Alignof(void *)));
-}
-
-static inline struct mbuf *
-pfil_mem2mbuf(void *v)
-{
-
-       return (*(struct mbuf **) (((uintptr_t)(v) +
-           (_Alignof(void *) - 1)) & - _Alignof(void *)));
-}
-
 typedef enum {
        PFIL_PASS = 0,
        PFIL_DROPPED,
@@ -124,8 +99,11 @@ typedef enum {
        PFIL_REALLOCED,
 } pfil_return_t;
 
-typedef        pfil_return_t   (*pfil_func_t)(pfil_packet_t, struct ifnet *, 
int,
+typedef        pfil_return_t   (*pfil_mbuf_chk_t)(struct mbuf **, struct ifnet 
*, int,
                            void *, struct inpcb *);
+typedef pfil_return_t  (*pfil_mem_chk_t)(void *, u_int, int, struct ifnet *,
+                           void *, struct mbuf **);
+
 /*
  * A pfil head is created by a packet intercept point.
  *
@@ -142,14 +120,15 @@ typedef struct pfil_head *        pfil_head_t;
 /*
  * Give us a chance to modify pfil_xxx_args structures in future.
  */
-#define        PFIL_VERSION    1
+#define        PFIL_VERSION    2
 
 /* Argument structure used by packet filters to register themselves. */
 struct pfil_hook_args {
        int              pa_version;
        int              pa_flags;
        enum pfil_types  pa_type;
-       pfil_func_t      pa_func;
+       pfil_mbuf_chk_t  pa_mbuf_chk;
+       pfil_mem_chk_t   pa_mem_chk;
        void            *pa_ruleset;
        const char      *pa_modname;
        const char      *pa_rulname;
@@ -192,12 +171,15 @@ pfil_head_t       pfil_head_register(struct 
pfil_head_args *);
 void           pfil_head_unregister(pfil_head_t);
 
 /* Public functions to run the packet inspection by inspection points. */
-int    pfil_run_hooks(struct pfil_head *, pfil_packet_t, struct ifnet *, int,
+int    pfil_mem_in(struct pfil_head *, void *, u_int, struct ifnet *,
+    struct mbuf **);
+int    pfil_mem_out(struct pfil_head *, void *, u_int, struct ifnet *,
+    struct mbuf **);
+int    pfil_mbuf_in(struct pfil_head *, struct mbuf **, struct ifnet *,
     struct inpcb *inp);
-int    pfil_mbuf_in(struct pfil_head *, pfil_packet_t, struct ifnet *,
-    struct inpcb *inp);
-int    pfil_mbuf_out(struct pfil_head *, pfil_packet_t, struct ifnet *,
+int    pfil_mbuf_out(struct pfil_head *, struct mbuf **, struct ifnet *,
     struct inpcb *inp);
+
 /*
  * Minimally exposed structure to avoid function call in case of absence
  * of any filters by protocols and macros to do the check.
@@ -209,10 +191,5 @@ struct _pfil_head {
 #define        PFIL_HOOKED_IN(p) (((struct _pfil_head *)(p))->head_nhooksin > 
0)
 #define        PFIL_HOOKED_OUT(p) (((struct _pfil_head *)(p))->head_nhooksout 
> 0)
 
-/*
- * Alloc mbuf to be used instead of memory pointer.
- */
-int    pfil_realloc(pfil_packet_t *, int, struct ifnet *);
-
 #endif /* _KERNEL */
 #endif /* _NET_PFIL_H_ */
diff --git a/sys/netinet/siftr.c b/sys/netinet/siftr.c
index e21d15212979..7861031b724b 100644
--- a/sys/netinet/siftr.c
+++ b/sys/netinet/siftr.c
@@ -1139,18 +1139,16 @@ VNET_DEFINE_STATIC(pfil_hook_t, siftr_inet6_hook);
 static int
 siftr_pfil(int action)
 {
-       struct pfil_hook_args pha;
-       struct pfil_link_args pla;
-
-       pha.pa_version = PFIL_VERSION;
-       pha.pa_flags = PFIL_IN | PFIL_OUT;
-       pha.pa_modname = "siftr";
-       pha.pa_ruleset = NULL;
-       pha.pa_rulname = "default";
-
-       pla.pa_version = PFIL_VERSION;
-       pla.pa_flags = PFIL_IN | PFIL_OUT |
-           PFIL_HEADPTR | PFIL_HOOKPTR;
+       struct pfil_hook_args pha = {
+               .pa_version = PFIL_VERSION,
+               .pa_flags = PFIL_IN | PFIL_OUT,
+               .pa_modname = "siftr",
+               .pa_rulname = "default",
+       };
+       struct pfil_link_args pla = {
+               .pa_version = PFIL_VERSION,
+               .pa_flags = PFIL_IN | PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR,
+       };
 
        VNET_ITERATOR_DECL(vnet_iter);
 
@@ -1159,14 +1157,14 @@ siftr_pfil(int action)
                CURVNET_SET(vnet_iter);
 
                if (action == HOOK) {
-                       pha.pa_func = siftr_chkpkt;
+                       pha.pa_mbuf_chk = siftr_chkpkt;
                        pha.pa_type = PFIL_TYPE_IP4;
                        V_siftr_inet_hook = pfil_add_hook(&pha);
                        pla.pa_hook = V_siftr_inet_hook;
                        pla.pa_head = V_inet_pfil_head;
                        (void)pfil_link(&pla);
 #ifdef SIFTR_IPV6
-                       pha.pa_func = siftr_chkpkt6;
+                       pha.pa_mbuf_chk = siftr_chkpkt6;
                        pha.pa_type = PFIL_TYPE_IP6;
                        V_siftr_inet6_hook = pfil_add_hook(&pha);
                        pla.pa_hook = V_siftr_inet6_hook;
diff --git a/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c 
b/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
index 95c8b73e6388..1822d19fbb4c 100644
--- a/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
+++ b/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
@@ -1311,31 +1311,31 @@ int ipf_pfil_unhook(void) {
 }
 
 int ipf_pfil_hook(void) {
-       struct pfil_hook_args pha;
-       struct pfil_link_args pla;
        int error, error6;
 
-       pha.pa_version = PFIL_VERSION;
-       pha.pa_flags = PFIL_IN | PFIL_OUT;
-       pha.pa_modname = "ipfilter";
-       pha.pa_rulname = "default-ip4";
-       pha.pa_func = ipf_check_wrapper;
-       pha.pa_ruleset = NULL;
-       pha.pa_type = PFIL_TYPE_IP4;
+       struct pfil_hook_args pha = {
+               .pa_version = PFIL_VERSION,
+               .pa_flags = PFIL_IN | PFIL_OUT,
+               .pa_modname = "ipfilter",
+               .pa_rulname = "default-ip4",
+               .pa_mbuf_chk = ipf_check_wrapper,
+               .pa_type = PFIL_TYPE_IP4,
+       };
        V_ipf_inet_hook = pfil_add_hook(&pha);
 
 #ifdef USE_INET6
        pha.pa_rulname = "default-ip6";
-       pha.pa_func = ipf_check_wrapper6;
+       pha.pa_mbuf_chk = ipf_check_wrapper6;
        pha.pa_type = PFIL_TYPE_IP6;
        V_ipf_inet6_hook = pfil_add_hook(&pha);
 #endif
 
-       pla.pa_version = PFIL_VERSION;
-       pla.pa_flags = PFIL_IN | PFIL_OUT |
-           PFIL_HEADPTR | PFIL_HOOKPTR;
-       pla.pa_head = V_inet_pfil_head;
-       pla.pa_hook = V_ipf_inet_hook;
+       struct pfil_link_args pla = {
+               .pa_version = PFIL_VERSION,
+               .pa_flags = PFIL_IN | PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR,
+               .pa_head = V_inet_pfil_head,
+               .pa_hook = V_ipf_inet_hook,
+       };
        error = pfil_link(&pla);
 
        error6 = 0;
diff --git a/sys/netpfil/ipfw/ip_fw_pfil.c b/sys/netpfil/ipfw/ip_fw_pfil.c
index 29ae06ba7713..ec46c077d8bb 100644
--- a/sys/netpfil/ipfw/ip_fw_pfil.c
+++ b/sys/netpfil/ipfw/ip_fw_pfil.c
@@ -327,52 +327,104 @@ again:
 }
 
 /*
- * ipfw processing for ethernet packets (in and out).
+ * ipfw processing for ethernet packets (in and out), mbuf version.
  */
 static pfil_return_t
-ipfw_check_frame(pfil_packet_t p, struct ifnet *ifp, int flags,
+ipfw_check_frame_mbuf(struct mbuf **m0, struct ifnet *ifp, const int flags,
     void *ruleset __unused, struct inpcb *inp)
 {
-       struct ip_fw_args args;
+       struct ip_fw_args args = {
+               .flags = IPFW_ARGS_ETHER |
+                   ((flags & PFIL_IN) ? IPFW_ARGS_IN : IPFW_ARGS_OUT),
+               .ifp = ifp,
+               .inp = inp,
+       };
+       struct m_tag *mtag;
        pfil_return_t ret;
-       bool mem, realloc;
        int ipfw;
 
-       if (flags & PFIL_MEMPTR) {
-               mem = true;
-               realloc = false;
-               args.flags = PFIL_LENGTH(flags) | IPFW_ARGS_ETHER;
-               args.mem = p.mem;
-       } else {
-               mem = realloc = false;
-               args.flags = IPFW_ARGS_ETHER;
+again:
+       /*
+        * Fetch start point from rule, if any.
+        * Remove the tag if present.
+        */
+       mtag = m_tag_locate(*m0, MTAG_IPFW_RULE, 0, NULL);
+       if (mtag != NULL) {
+               args.rule = *((struct ipfw_rule_ref *)(mtag+1));
+               m_tag_delete(*m0, mtag);
+               if (args.rule.info & IPFW_ONEPASS)
+                       return (PFIL_PASS);
+               args.flags |= IPFW_ARGS_REF;
        }
-       args.flags |= (flags & PFIL_IN) ? IPFW_ARGS_IN : IPFW_ARGS_OUT;
-       args.ifp = ifp;
-       args.inp = inp;
+       args.m = *m0,
 
-again:
-       if (!mem) {
-               /*
-                * Fetch start point from rule, if any.
-                * Remove the tag if present.
-                */
-               struct m_tag *mtag;
-
-               mtag = m_tag_locate(*p.m, MTAG_IPFW_RULE, 0, NULL);
-               if (mtag != NULL) {
-                       args.rule = *((struct ipfw_rule_ref *)(mtag+1));
-                       m_tag_delete(*p.m, mtag);
-                       if (args.rule.info & IPFW_ONEPASS)
-                               return (PFIL_PASS);
-                       args.flags |= IPFW_ARGS_REF;
+       ipfw = ipfw_chk(&args);
+       *m0 = args.m;
+
+       ret = PFIL_PASS;
+       switch (ipfw) {
+       case IP_FW_PASS:
+               break;
+
+       case IP_FW_DENY:
+               ret = PFIL_DROPPED;
+               break;
+
+       case IP_FW_DUMMYNET:
+               if (ip_dn_io_ptr == NULL) {
+                       ret = PFIL_DROPPED;
+                       break;
                }
-               args.m = *p.m;
+               MPASS(args.flags & IPFW_ARGS_REF);
+               ip_dn_io_ptr(m0, &args);
+               return (PFIL_CONSUMED);
+
+       case IP_FW_NGTEE:
+       case IP_FW_NETGRAPH:
+               if (ng_ipfw_input_p == NULL) {
+                       ret = PFIL_DROPPED;
+                       break;
+               }
+               MPASS(args.flags & IPFW_ARGS_REF);
+               (void )ng_ipfw_input_p(m0, &args, ipfw == IP_FW_NGTEE);
+               if (ipfw == IP_FW_NGTEE) /* ignore errors for NGTEE */
+                       goto again;     /* continue with packet */
+               ret = PFIL_CONSUMED;
+               break;
+
+       default:
+               KASSERT(0, ("%s: unknown retval", __func__));
        }
 
+       if (ret != PFIL_PASS) {
+               if (*m0)
+                       FREE_PKT(*m0);
+               *m0 = NULL;
+       }
+
+       return (ret);
+}
+
+/*
+ * ipfw processing for ethernet packets (in and out), memory pointer version,
+ * two in/out accessors.
+ */
+static pfil_return_t
+ipfw_check_frame_mem(void *mem, u_int len, int flags, struct ifnet *ifp,
+    void *ruleset __unused, struct mbuf **m)
+{
+       struct ip_fw_args args = {
+               .flags = len | IPFW_ARGS_ETHER |
+                   ((flags & PFIL_IN) ? IPFW_ARGS_IN : IPFW_ARGS_OUT),
+               .ifp = ifp,
+               .mem = mem,
+       };
+       pfil_return_t ret;
+       int ipfw;
+
+       *m = NULL;
+again:
        ipfw = ipfw_chk(&args);
-       if (!mem)
-               *p.m = args.m;
 
        ret = PFIL_PASS;
        switch (ipfw) {
@@ -388,16 +440,13 @@ again:
                        ret = PFIL_DROPPED;
                        break;
                }
-               if (mem) {
-                       if (pfil_realloc(&p, flags, ifp) != 0) {
-                               ret = PFIL_DROPPED;
-                               break;
-                       }
-                       mem = false;
-                       realloc = true;
+               *m = m_devget(mem, len, 0, ifp, NULL);
+               if (*m == NULL) {
+                       ret = PFIL_DROPPED;
+                       break;
                }
                MPASS(args.flags & IPFW_ARGS_REF);
-               ip_dn_io_ptr(p.m, &args);
+               ip_dn_io_ptr(m, &args);
                return (PFIL_CONSUMED);
 
        case IP_FW_NGTEE:
@@ -406,16 +455,13 @@ again:
                        ret = PFIL_DROPPED;
                        break;
                }
-               if (mem) {
-                       if (pfil_realloc(&p, flags, ifp) != 0) {
-                               ret = PFIL_DROPPED;
-                               break;
-                       }
-                       mem = false;
-                       realloc = true;
+               *m = m_devget(mem, len, 0, ifp, NULL);
+               if (*m == NULL) {
+                       ret = PFIL_DROPPED;
+                       break;
                }
                MPASS(args.flags & IPFW_ARGS_REF);
-               (void )ng_ipfw_input_p(p.m, &args, ipfw == IP_FW_NGTEE);
+               (void )ng_ipfw_input_p(m, &args, ipfw == IP_FW_NGTEE);
                if (ipfw == IP_FW_NGTEE) /* ignore errors for NGTEE */
                        goto again;     /* continue with packet */
                ret = PFIL_CONSUMED;
@@ -425,13 +471,7 @@ again:
                KASSERT(0, ("%s: unknown retval", __func__));
        }
 
-       if (!mem && ret != PFIL_PASS) {
-               if (*p.m)
-                       FREE_PKT(*p.m);
-               *p.m = NULL;
-       }
-
-       if (realloc && ret == PFIL_PASS)
+       if (*m != NULL && ret == PFIL_PASS)
                ret = PFIL_REALLOCED;
 
        return (ret);
@@ -543,34 +583,33 @@ VNET_DEFINE_STATIC(pfil_hook_t, ipfw_link_hook);
 static void
 ipfw_hook(int pf)
 {
-       struct pfil_hook_args pha;
+       struct pfil_hook_args pha = {
+               .pa_version = PFIL_VERSION,
+               .pa_flags = PFIL_IN | PFIL_OUT,
+               .pa_modname = "ipfw",
+       };
        pfil_hook_t *h;
 
-       pha.pa_version = PFIL_VERSION;
-       pha.pa_flags = PFIL_IN | PFIL_OUT;
-       pha.pa_modname = "ipfw";
-       pha.pa_ruleset = NULL;
-
        switch (pf) {
        case AF_INET:
-               pha.pa_func = ipfw_check_packet;
+               pha.pa_mbuf_chk = ipfw_check_packet;
                pha.pa_type = PFIL_TYPE_IP4;
                pha.pa_rulname = "default";
                h = &V_ipfw_inet_hook;
                break;
 #ifdef INET6
        case AF_INET6:
-               pha.pa_func = ipfw_check_packet;
+               pha.pa_mbuf_chk = ipfw_check_packet;
                pha.pa_type = PFIL_TYPE_IP6;
                pha.pa_rulname = "default6";
                h = &V_ipfw_inet6_hook;
                break;
 #endif
        case AF_LINK:
-               pha.pa_func = ipfw_check_frame;
+               pha.pa_mbuf_chk = ipfw_check_frame_mbuf;
+               pha.pa_mem_chk = ipfw_check_frame_mem;
                pha.pa_type = PFIL_TYPE_ETHERNET;
                pha.pa_rulname = "default-link";
-               pha.pa_flags |= PFIL_MEMPTR;
                h = &V_ipfw_link_hook;
                break;
        }
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 76742aebf01a..cc1f5a5c2138 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -6532,21 +6532,20 @@ VNET_DEFINE_STATIC(pfil_hook_t, pf_ip6_out_hook);
 static void
 hook_pf_eth(void)
 {
-       struct pfil_hook_args pha;
-       struct pfil_link_args pla;
+       struct pfil_hook_args pha = {
+               .pa_version = PFIL_VERSION,
+               .pa_modname = "pf",
+               .pa_type = PFIL_TYPE_ETHERNET,
+       };
+       struct pfil_link_args pla = {
+               .pa_version = PFIL_VERSION,
+       };
        int ret __diagused;
 
        if (atomic_load_bool(&V_pf_pfil_eth_hooked))
                return;
 
-       pha.pa_version = PFIL_VERSION;
-       pha.pa_modname = "pf";
-       pha.pa_ruleset = NULL;
-
-       pla.pa_version = PFIL_VERSION;
-
-       pha.pa_type = PFIL_TYPE_ETHERNET;
-       pha.pa_func = pf_eth_check_in;
+       pha.pa_mbuf_chk = pf_eth_check_in;
        pha.pa_flags = PFIL_IN;
        pha.pa_rulname = "eth-in";
        V_pf_eth_in_hook = pfil_add_hook(&pha);
@@ -6555,7 +6554,7 @@ hook_pf_eth(void)
        pla.pa_hook = V_pf_eth_in_hook;
        ret = pfil_link(&pla);
        MPASS(ret == 0);
-       pha.pa_func = pf_eth_check_out;
+       pha.pa_mbuf_chk = pf_eth_check_out;
        pha.pa_flags = PFIL_OUT;
        pha.pa_rulname = "eth-out";
        V_pf_eth_out_hook = pfil_add_hook(&pha);
@@ -6571,22 +6570,21 @@ hook_pf_eth(void)
 static void
 hook_pf(void)
 {
-       struct pfil_hook_args pha;
-       struct pfil_link_args pla;
+       struct pfil_hook_args pha = {
+               .pa_version = PFIL_VERSION,
+               .pa_modname = "pf",
+       };
+       struct pfil_link_args pla = {
+               .pa_version = PFIL_VERSION,
+       };
        int ret __diagused;
 
        if (atomic_load_bool(&V_pf_pfil_hooked))
                return;
 
-       pha.pa_version = PFIL_VERSION;
-       pha.pa_modname = "pf";
-       pha.pa_ruleset = NULL;
-
-       pla.pa_version = PFIL_VERSION;
-
 #ifdef INET
        pha.pa_type = PFIL_TYPE_IP4;
-       pha.pa_func = pf_check_in;
+       pha.pa_mbuf_chk = pf_check_in;
        pha.pa_flags = PFIL_IN;
        pha.pa_rulname = "default-in";
        V_pf_ip4_in_hook = pfil_add_hook(&pha);
@@ -6595,7 +6593,7 @@ hook_pf(void)
        pla.pa_hook = V_pf_ip4_in_hook;
        ret = pfil_link(&pla);
        MPASS(ret == 0);
-       pha.pa_func = pf_check_out;
+       pha.pa_mbuf_chk = pf_check_out;
        pha.pa_flags = PFIL_OUT;
        pha.pa_rulname = "default-out";
        V_pf_ip4_out_hook = pfil_add_hook(&pha);
@@ -6607,7 +6605,7 @@ hook_pf(void)
 #endif
 #ifdef INET6
        pha.pa_type = PFIL_TYPE_IP6;
-       pha.pa_func = pf_check6_in;
+       pha.pa_mbuf_chk = pf_check6_in;
        pha.pa_flags = PFIL_IN;
        pha.pa_rulname = "default-in6";
        V_pf_ip6_in_hook = pfil_add_hook(&pha);
@@ -6616,7 +6614,7 @@ hook_pf(void)
        pla.pa_hook = V_pf_ip6_in_hook;
        ret = pfil_link(&pla);
        MPASS(ret == 0);
-       pha.pa_func = pf_check6_out;
+       pha.pa_mbuf_chk = pf_check6_out;
        pha.pa_rulname = "default-out6";
        pha.pa_flags = PFIL_OUT;
        V_pf_ip6_out_hook = pfil_add_hook(&pha);

Reply via email to