git: 18d04cd2d42c - main - pf: align IPv6 dummynet handling with IPv4

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Tue, 23 Nov 2021 17:48:12 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=18d04cd2d42c16209c8f615bb9735dded328915b

commit 18d04cd2d42c16209c8f615bb9735dded328915b
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2021-11-22 20:28:10 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2021-11-23 15:46:15 +0000

    pf: align IPv6 dummynet handling with IPv4
    
    In e5c4987e3f we fixed issues with nat and dummynet, but only changed
    the IPv4 code. Make the same change for IPv6 as well.
    
    Reviewed by:    glebius
    MFC after:      3 weeks
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D33086
---
 sys/netpfil/pf/pf.c | 87 ++++++++++++++++++++++++++++-------------------------
 1 file changed, 46 insertions(+), 41 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 1ddb61836e2e..34fa7918d697 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -6873,6 +6873,7 @@ done:
 			if (ip_dn_io_ptr == NULL) {
 				m_freem(*m0);
 				*m0 = NULL;
+				action = PF_DROP;
 				REASON_SET(&reason, PFRES_MEMORY);
 			} else {
 				struct ip_fw_args dnflow;
@@ -6951,6 +6952,13 @@ pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb
 			}
 			pd.pf_mtag->flags |= PF_PACKET_LOOPED;
 			m_tag_delete(m, ipfwtag);
+			if (rr->info & IPFW_IS_DUMMYNET) {
+				/* Dummynet re-injects packets after they've
+				 * completed their delay. We've already
+				 * processed them, so pass unconditionally. */
+				PF_RULES_RUNLOCK();
+				return (PF_PASS);
+			}
 		}
 	} else if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) {
 		action = PF_DROP;
@@ -7211,47 +7219,6 @@ done:
 	}
 #endif /* ALTQ */
 
-	if (s && (s->dnpipe || s->dnrpipe)) {
-		pd.act.dnpipe = s->dnpipe;
-		pd.act.dnrpipe = s->dnrpipe;
-		pd.act.flags = s->state_flags;
-	} else {
-		pd.act.dnpipe = r->dnpipe;
-		pd.act.dnrpipe = r->dnrpipe;
-		pd.act.flags = r->free_flags;
-	}
-	if ((pd.act.dnpipe || pd.act.dnrpipe) && !PACKET_LOOPED(&pd)) {
-		if (ip_dn_io_ptr == NULL) {
-			action = PF_DROP;
-			REASON_SET(&reason, PFRES_MEMORY);
-		} else {
-			struct ip_fw_args dnflow;
-
-			if (pd.pf_mtag == NULL &&
-			    ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
-				action = PF_DROP;
-				REASON_SET(&reason, PFRES_MEMORY);
-				if (s)
-					PF_STATE_UNLOCK(s);
-				return (action);
-			}
-
-			if (pf_pdesc_to_dnflow(dir, &pd, r, s, &dnflow)) {
-				ip_dn_io_ptr(m0, &dnflow);
-
-				if (*m0 == NULL) {
-					if (s)
-						PF_STATE_UNLOCK(s);
-					return (action);
-				} else {
-					/* This is dummynet fast io processing */
-					m_tag_delete(*m0, m_tag_first(*m0));
-					pd.pf_mtag->flags &= ~PF_PACKET_LOOPED;
-				}
-			}
-		}
-	}
-
 	if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
 	    pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
 	    (s->nat_rule.ptr->action == PF_RDR ||
@@ -7348,6 +7315,44 @@ done:
 			pf_route6(m0, r, dir, kif->pfik_ifp, s, &pd, inp);
 			return (action);
 		}
+		/* Dummynet processing. */
+		if (s && (s->dnpipe || s->dnrpipe)) {
+			pd.act.dnpipe = s->dnpipe;
+			pd.act.dnrpipe = s->dnrpipe;
+			pd.act.flags = s->state_flags;
+		} else {
+			pd.act.dnpipe = r->dnpipe;
+			pd.act.dnrpipe = r->dnrpipe;
+			pd.act.flags = r->free_flags;
+		}
+		if (pd.act.dnpipe || pd.act.dnrpipe) {
+			if (ip_dn_io_ptr == NULL) {
+				m_freem(*m0);
+				*m0 = NULL;
+				action = PF_DROP;
+				REASON_SET(&reason, PFRES_MEMORY);
+			} else {
+				struct ip_fw_args dnflow;
+
+				if (pd.pf_mtag == NULL &&
+				    ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
+					m_freem(*m0);
+					*m0 = NULL;
+					action = PF_DROP;
+					REASON_SET(&reason, PFRES_MEMORY);
+					if (s)
+						PF_STATE_UNLOCK(s);
+					return (action);
+				}
+
+				if (pf_pdesc_to_dnflow(dir, &pd, r, s, &dnflow)) {
+					ip_dn_io_ptr(m0, &dnflow);
+
+					if (*m0 == NULL)
+						action = PF_DROP;
+				}
+			}
+		}
 		break;
 	}