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
This commit is contained in:
parent
889a9acc54
commit
9a1cab6d79
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user