The branch main has been updated by kp:

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

commit 9a1cab6d79b7286e5f650f57ed95625e6ddb8e4b
Author:     Kristof Provost <[email protected]>
AuthorDate: 2023-02-14 06:11:38 +0000
Commit:     Kristof Provost <[email protected]>
CommitDate: 2023-02-16 06:43:04 +0000

    pfsync: support deferring IPv6 packets
    
    When we send out a deferred packet we must make sure to call
    ip6_output() for IPv6 packets. If not we might end up attempting to
    ip_fragment() an IPv6 packet, which could lead to us reading outside of
    the mbuf.
    
    PR:             268246
    Reviewed by:    melifaro, zlei
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D38586
---
 sys/netpfil/pf/if_pfsync.c | 91 +++++++++++++++++++++++++++++-----------------
 1 file changed, 58 insertions(+), 33 deletions(-)

diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c
index 2301dc475e27..1c8d8d325346 100644
--- a/sys/netpfil/pf/if_pfsync.c
+++ b/sys/netpfil/pf/if_pfsync.c
@@ -103,9 +103,13 @@ __FBSDID("$FreeBSD$");
 #include <netinet/tcp_fsm.h>
 #include <netinet/tcp_seq.h>
 
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+
 #include <netpfil/pf/pfsync_nv.h>
 
 struct pfsync_bucket;
+struct pfsync_softc;
 
 union inet_template {
        struct ip      ipv4;
@@ -171,6 +175,7 @@ static void pfsync_q_ins(struct pf_kstate *, int, bool);
 static void    pfsync_q_del(struct pf_kstate *, bool, struct pfsync_bucket *);
 
 static void    pfsync_update_state(struct pf_kstate *);
+static void    pfsync_tx(struct pfsync_softc *, struct mbuf *);
 
 struct pfsync_upd_req_item {
        TAILQ_ENTRY(pfsync_upd_req_item)        ur_entry;
@@ -187,8 +192,6 @@ struct pfsync_deferral {
        struct mbuf                     *pd_m;
 };
 
-struct pfsync_sofct;
-
 struct pfsync_bucket
 {
        int                     b_id;
@@ -1837,13 +1840,7 @@ pfsync_defer_tmo(void *arg)
                free(pd, M_PFSYNC);
        PFSYNC_BUCKET_UNLOCK(b);
 
-       switch (sc->sc_sync_peer.ss_family) {
-#ifdef INET
-       case AF_INET:
-               ip_output(m, NULL, NULL, 0, NULL, NULL);
-               break;
-#endif
-       }
+       pfsync_tx(sc, m);
 
        pf_release_state(st);
 
@@ -2326,6 +2323,56 @@ pfsync_push_all(struct pfsync_softc *sc)
        }
 }
 
+static void
+pfsync_tx(struct pfsync_softc *sc, struct mbuf *m)
+{
+       struct ip *ip;
+       int error, af;
+
+       ip = mtod(m, struct ip *);
+       MPASS(ip->ip_v == IPVERSION || ip->ip_v == (IPV6_VERSION >> 4));
+
+       af = ip->ip_v == IPVERSION ? AF_INET : AF_INET6;
+
+       /*
+        * We distinguish between a deferral packet and our
+        * own pfsync packet based on M_SKIP_FIREWALL
+        * flag. This is XXX.
+        */
+       switch (af) {
+#ifdef INET
+       case AF_INET:
+               if (m->m_flags & M_SKIP_FIREWALL) {
+                       error = ip_output(m, NULL, NULL, 0,
+                           NULL, NULL);
+               } else {
+                       error = ip_output(m, NULL, NULL,
+                           IP_RAWOUTPUT, &sc->sc_imo, NULL);
+               }
+               break;
+#endif
+#ifdef INET6
+       case AF_INET6:
+               if (m->m_flags & M_SKIP_FIREWALL) {
+                       error = ip6_output(m, NULL, NULL, 0,
+                           NULL, NULL, NULL);
+               } else {
+                       MPASS(false);
+                       /* We don't support pfsync over IPv6. */
+                       /*error = ip6_output(m, NULL, NULL,
+                           IP_RAWOUTPUT, &sc->sc_imo6, NULL);*/
+               }
+               break;
+#endif
+       }
+
+       if (error == 0)
+               V_pfsyncstats.pfsyncs_opackets++;
+       else
+               V_pfsyncstats.pfsyncs_oerrors++;
+
+}
+
 static void
 pfsyncintr(void *arg)
 {
@@ -2333,7 +2380,7 @@ pfsyncintr(void *arg)
        struct pfsync_softc *sc = arg;
        struct pfsync_bucket *b;
        struct mbuf *m, *n;
-       int c, error;
+       int c;
 
        NET_EPOCH_ENTER(et);
        CURVNET_SET(sc->sc_ifp->if_vnet);
@@ -2353,29 +2400,7 @@ pfsyncintr(void *arg)
                        n = m->m_nextpkt;
                        m->m_nextpkt = NULL;
 
-                       /*
-                        * We distinguish between a deferral packet and our
-                        * own pfsync packet based on M_SKIP_FIREWALL
-                        * flag. This is XXX.
-                        */
-                       switch (sc->sc_sync_peer.ss_family) {
-#ifdef INET
-                       case AF_INET:
-                               if (m->m_flags & M_SKIP_FIREWALL) {
-                                       error = ip_output(m, NULL, NULL, 0,
-                                           NULL, NULL);
-                               } else {
-                                       error = ip_output(m, NULL, NULL,
-                                           IP_RAWOUTPUT, &sc->sc_imo, NULL);
-                               }
-                               break;
-#endif
-                       }
-
-                       if (error == 0)
-                               V_pfsyncstats.pfsyncs_opackets++;
-                       else
-                               V_pfsyncstats.pfsyncs_oerrors++;
+                       pfsync_tx(sc, m);
                }
        }
        CURVNET_RESTORE();

Reply via email to