The branch stable/13 has been updated by kp:

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

commit 3dec62eded04eaf431bf0948f4e6412deede87d5
Author:     Kristof Provost <[email protected]>
AuthorDate: 2023-02-14 06:11:38 +0000
Commit:     Kristof Provost <[email protected]>
CommitDate: 2023-03-02 16:21:59 +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
    
    (cherry picked from commit 9a1cab6d79b7286e5f650f57ed95625e6ddb8e4b)
---
 sys/netpfil/pf/if_pfsync.c | 71 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 56 insertions(+), 15 deletions(-)

diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c
index f6c7bd9b566d..6c25ddb7f6b3 100644
--- a/sys/netpfil/pf/if_pfsync.c
+++ b/sys/netpfil/pf/if_pfsync.c
@@ -102,12 +102,16 @@ __FBSDID("$FreeBSD$");
 #include <netinet/tcp_fsm.h>
 #include <netinet/tcp_seq.h>
 
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+
 #define PFSYNC_MINPKT ( \
        sizeof(struct ip) + \
        sizeof(struct pfsync_header) + \
        sizeof(struct pfsync_subheader) )
 
 struct pfsync_bucket;
+struct pfsync_softc;
 
 struct pfsync_pkt {
        struct ip *ip;
@@ -170,6 +174,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;
@@ -186,8 +191,6 @@ struct pfsync_deferral {
        struct mbuf                     *pd_m;
 };
 
-struct pfsync_sofct;
-
 struct pfsync_bucket
 {
        int                     b_id;
@@ -1839,7 +1842,7 @@ pfsync_defer_tmo(void *arg)
                free(pd, M_PFSYNC);
        PFSYNC_BUCKET_UNLOCK(b);
 
-       ip_output(m, NULL, NULL, 0, NULL, NULL);
+       pfsync_tx(sc, m);
 
        pf_release_state(st);
 
@@ -2322,6 +2325,55 @@ 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)
 {
@@ -2349,18 +2401,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.
-                        */
-                       if (m->m_flags & M_SKIP_FIREWALL)
-                               ip_output(m, NULL, NULL, 0, NULL, NULL);
-                       else if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, 
&sc->sc_imo,
-                           NULL) == 0)
-                               V_pfsyncstats.pfsyncs_opackets++;
-                       else
-                               V_pfsyncstats.pfsyncs_oerrors++;
+                       pfsync_tx(sc, m);
                }
        }
        CURVNET_RESTORE();

Reply via email to