Index | Thread | Search

From:
David Gwynne <david@gwynne.id.au>
Subject:
make pf_test require a parent for carp interfaces
To:
tech@openbsd.org
Date:
Wed, 10 Dec 2025 14:46:30 +1000

Download raw body.

Thread
pf has a semantic where it uses the parent of carp interfaces when
applying policy, rather than the carp interface itself. eg, if you have
carp0 on top of em0, the kernel generally operates as if the packets
sent to the carp0 address were received by the carp0 interface, but
pf prefers to operate on em0 in this situation and does a lookup
to figure this out. this means you write rules to pass traffic on em0,
even if it was a carp interface that steered them toward you.

it is possible to run carp on top of an interface that can be detached,
which means it's possible to have a packet received by a carp interface
that can't be translated to the parent interface in pf.

currently, if that lookup fails, we run pf against the carp interface. i
think it's better to let pf drop the packet in this situation, which is
what this diff implements.

ok?

Index: pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
diff -u -p -r1.1223 pf.c
--- pf.c	10 Dec 2025 04:18:16 -0000	1.1223
+++ pf.c	10 Dec 2025 04:26:38 -0000
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pf.c,v 1.1223 2025/12/10 04:18:16 dlg Exp $ */
+/*	$OpenBSD: pf.c,v 1.1222 2025/12/10 03:51:51 dlg Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -8215,7 +8215,7 @@ pf_counters_inc(int action, struct pf_pd
 int
 pf_test(sa_family_t af, int fwdir, struct ifnet *ifp, struct mbuf **m0)
 {
-	struct pfi_kif		*kif;
+	struct pfi_kif		*kif = NULL;
 	u_short			 action, reason = 0;
 	struct pf_rule		*a = NULL, *r = &pf_default_rule;
 	struct pf_state		*st = NULL;
@@ -8229,7 +8229,6 @@ pf_test(sa_family_t af, int fwdir, struc
 	if (!pf_status.running)
 		return (PF_PASS);
 
-	kif = (struct pfi_kif *)ifp->if_pf_kif;
 #if NCARP > 0
 	if (ifp->if_type == IFT_CARP) {
 		struct ifnet *ifp0;
@@ -8239,8 +8238,9 @@ pf_test(sa_family_t af, int fwdir, struc
 		if (ifp0 != NULL)
 			kif = (struct pfi_kif *)ifp0->if_pf_kif;
 		smr_read_leave();
-	}
+	} else
 #endif /* NCARP */
+		kif = (struct pfi_kif *)ifp->if_pf_kif;
 
 	if (kif == NULL) {
 		DPFPRINTF(LOG_ERR,