Hello,
back in Gouveia claudio@ complained 'set skip on ...' requires reloading
pf.conf, when new interface appears. Diff below should fix that.
the idea is to introduce yet another reference type (PFI_KIF_REF_FLAG) pfi_kif
objects. PFI_KIF_REF_FLAG type keeps pfi_kif object in pf's interface table,
when there is no other reference to interface/group than 'set skip ...'
statement itself. The PFI_KIF_REF_FLAG is grabbed/dropped if and only if the
interface flag is being changed.
OK?
thanks and
regards
sashan
--------8<---------------8<---------------8<------------------8<--------
diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5
index bff448aa8dc..4afe841651f 100644
--- a/share/man/man5/pf.conf.5
+++ b/share/man/man5/pf.conf.5
@@ -1383,9 +1383,6 @@ Packets passing in or out on such interfaces are passed
as if pf was
disabled, i.e. pf does not process them in any way.
This can be useful on loopback and other virtual interfaces, when
packet filtering is not desired and can have unexpected effects.
-.Ar ifspec
-is only evaluated when the ruleset is loaded; interfaces created
-later will not be skipped.
PF filters traffic on all interfaces by default.
.It Ic set Cm state-defaults Ar state-option , ...
The
diff --git a/sys/net/pf_if.c b/sys/net/pf_if.c
index 8de37375ab4..e91ba692a57 100644
--- a/sys/net/pf_if.c
+++ b/sys/net/pf_if.c
@@ -187,6 +187,9 @@ pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what)
case PFI_KIF_REF_SRCNODE:
kif->pfik_srcnodes++;
break;
+ case PFI_KIF_REF_FLAG:
+ kif->pfik_flagrefs++;
+ break;
default:
panic("pfi_kif_ref with unknown type");
}
@@ -233,15 +236,23 @@ pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what)
}
kif->pfik_srcnodes--;
break;
+ case PFI_KIF_REF_FLAG:
+ if (kif->pfik_flagrefs <= 0) {
+ DPFPRINTF(LOG_ERR,
+ "pfi_kif_unref: flags refcount <= 0");
+ return;
+ }
+ kif->pfik_flagrefs--;
+ break;
default:
panic("pfi_kif_unref with unknown type");
}
- if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all)
+ if (kif->pfik_ifp != NULL || kif->pfik_group != NULL ||kif == pfi_all)
return;
if (kif->pfik_rules || kif->pfik_states || kif->pfik_routes ||
- kif->pfik_srcnodes)
+ kif->pfik_srcnodes || kif->pfik_flagrefs)
return;
RB_REMOVE(pfi_ifhead, &pfi_ifs, kif);
@@ -786,24 +797,51 @@ int
pfi_set_flags(const char *name, int flags)
{
struct pfi_kif *p;
+ size_t n;
- RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
- if (pfi_skip_if(name, p))
- continue;
- p->pfik_flags_new = p->pfik_flags | flags;
+ if (name == NULL)
+ return (0);
+
+ n = strlen(name);
+ if ((n < 1) || (n >= IFNAMSIZ))
+ return (0);
+
+ if (name[n-1] >= '0' && name[n-1] <= '9') {
+ p = pfi_kif_get(name, NULL);
+ if (p != NULL) {
+ p->pfik_flags_new = p->pfik_flags | flags;
+ if (p->pfik_flags_new != p->pfik_flags)
+ pfi_kif_ref(p, PFI_KIF_REF_FLAG);
+ }
+ } else {
+ p = pfi_kif_get(name, NULL);
+ if (p != NULL) {
+ p->pfik_flags_new = p->pfik_flags | flags;
+ if (p->pfik_flags_new != p->pfik_flags)
+ pfi_kif_ref(p, PFI_KIF_REF_FLAG);
+ }
+
+ RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+ if (pfi_skip_if(name, p))
+ continue;
+ p->pfik_flags_new = p->pfik_flags | flags;
+ }
}
+
return (0);
}
int
pfi_clear_flags(const char *name, int flags)
{
- struct pfi_kif *p;
+ struct pfi_kif *p, *w;
- RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+ RB_FOREACH_SAFE(p, pfi_ifhead, &pfi_ifs, w) {
if (pfi_skip_if(name, p))
continue;
p->pfik_flags_new = p->pfik_flags & ~flags;
+ if (p->pfik_flags_new != p->pfik_flags)
+ pfi_kif_unref(p, PFI_KIF_REF_FLAG);
}
return (0);
}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 514b9e156f3..53ced8ab97d 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1171,6 +1171,7 @@ struct pfi_kif {
int pfik_rules;
int pfik_routes;
int pfik_srcnodes;
+ int pfik_flagrefs;
TAILQ_HEAD(, pfi_dynaddr) pfik_dynaddrs;
};
@@ -1179,7 +1180,8 @@ enum pfi_kif_refs {
PFI_KIF_REF_STATE,
PFI_KIF_REF_RULE,
PFI_KIF_REF_ROUTE,
- PFI_KIF_REF_SRCNODE
+ PFI_KIF_REF_SRCNODE,
+ PFI_KIF_REF_FLAG
};
#define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */