aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYannis Planus <yannis.planus@alstomgroup.com>2021-01-28 13:59:07 +0000
committerKristof Provost <kp@FreeBSD.org>2021-01-28 15:46:44 +0000
commit0c458752ceee14818034df7bfcdfb04129dceeda (patch)
tree4bb271058141aa6a684e5ede03b1f624dd71e0dc
parentd386f3a3c32f0396aa7995349dd65d6c59711393 (diff)
downloadsrc-0c458752ceee14818034df7bfcdfb04129dceeda.tar.gz
src-0c458752ceee14818034df7bfcdfb04129dceeda.zip
pf: duplicate frames only once when using dup-to pf rule
When using DUP-TO rule, frames are duplicated 3 times on both output interfaces and duplication interface. Add a flag to not duplicate a duplicated frame. Inspired by a patch from MiƂosz Kaniewski milosz.kaniewski at gmail.com https://lists.freebsd.org/pipermail/freebsd-pf/2015-November/007886.html Reviewed by: kp@ Differential Revision: https://reviews.freebsd.org/D27018
-rw-r--r--sys/netpfil/pf/pf.c50
-rw-r--r--sys/netpfil/pf/pf_mtag.h1
2 files changed, 45 insertions, 6 deletions
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 4cccb0101650..86354e69d11f 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -5488,10 +5488,29 @@ pf_route(struct mbuf **m, struct pf_krule *r, int dir, struct ifnet *oifp,
}
if (r->rt == PF_DUPTO) {
- if ((m0 = m_dup(*m, M_NOWAIT)) == NULL) {
- if (s)
+ if ((pd->pf_mtag->flags & PF_DUPLICATED)) {
+ if (s == NULL) {
+ ifp = r->rpool.cur->kif ?
+ r->rpool.cur->kif->pfik_ifp : NULL;
+ } else {
+ ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
PF_STATE_UNLOCK(s);
- return;
+ }
+ if (ifp == oifp) {
+ /* When the 2nd interface is not skipped */
+ return;
+ } else {
+ m0 = *m;
+ *m = NULL;
+ goto bad;
+ }
+ } else {
+ pd->pf_mtag->flags |= PF_DUPLICATED;
+ if (((m0 = m_dup(*m, M_NOWAIT)) == NULL)) {
+ if (s)
+ PF_STATE_UNLOCK(s);
+ return;
+ }
}
} else {
if ((r->rt == PF_REPLYTO) == (r->direction == dir)) {
@@ -5649,10 +5668,29 @@ pf_route6(struct mbuf **m, struct pf_krule *r, int dir, struct ifnet *oifp,
}
if (r->rt == PF_DUPTO) {
- if ((m0 = m_dup(*m, M_NOWAIT)) == NULL) {
- if (s)
+ if ((pd->pf_mtag->flags & PF_DUPLICATED)) {
+ if (s == NULL) {
+ ifp = r->rpool.cur->kif ?
+ r->rpool.cur->kif->pfik_ifp : NULL;
+ } else {
+ ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
PF_STATE_UNLOCK(s);
- return;
+ }
+ if (ifp == oifp) {
+ /* When the 2nd interface is not skipped */
+ return;
+ } else {
+ m0 = *m;
+ *m = NULL;
+ goto bad;
+ }
+ } else {
+ pd->pf_mtag->flags |= PF_DUPLICATED;
+ if (((m0 = m_dup(*m, M_NOWAIT)) == NULL)) {
+ if (s)
+ PF_STATE_UNLOCK(s);
+ return;
+ }
}
} else {
if ((r->rt == PF_REPLYTO) == (r->direction == dir)) {
diff --git a/sys/netpfil/pf/pf_mtag.h b/sys/netpfil/pf/pf_mtag.h
index 67c79350e8eb..ad28ab7a7c30 100644
--- a/sys/netpfil/pf/pf_mtag.h
+++ b/sys/netpfil/pf/pf_mtag.h
@@ -42,6 +42,7 @@
#define PF_PACKET_LOOPED 0x08
#define PF_FASTFWD_OURS_PRESENT 0x10
#define PF_REASSEMBLED 0x20
+#define PF_DUPLICATED 0x40
struct pf_mtag {
void *hdr; /* saved hdr pos in mbuf, for ECN */