git: 9a1cab6d79b7 - main - pfsync: support deferring IPv6 packets
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 16 Feb 2023 08:26:24 UTC
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=9a1cab6d79b7286e5f650f57ed95625e6ddb8e4b
commit 9a1cab6d79b7286e5f650f57ed95625e6ddb8e4b
Author: Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2023-02-14 06:11:38 +0000
Commit: Kristof Provost <kp@FreeBSD.org>
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();