Page MenuHomeFreeBSD

D29780.id87706.diff
No OneTemporary

D29780.id87706.diff

diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -188,5 +188,6 @@
int pfctl_add_rule(int dev, const struct pfctl_rule *r,
const char *anchor, const char *anchor_call, u_int32_t ticket,
u_int32_t pool_ticket);
+int pfctl_set_keepcounters(int dev, bool keep);
#endif
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -569,3 +569,25 @@
return (0);
}
+
+int
+pfctl_set_keepcounters(int dev, bool keep)
+{
+ struct pfioc_nv nv;
+ nvlist_t *nvl;
+ int ret;
+
+ nvl = nvlist_create(0);
+
+ nvlist_add_bool(nvl, "keep_counters", keep);
+
+ nv.data = nvlist_pack(nvl, &nv.len);
+ nv.size = nv.len;
+
+ nvlist_destroy(nvl);
+
+ ret = ioctl(dev, DIOCKEEPCOUNTERS, &nv);
+
+ free(nv.data);
+ return (ret);
+}
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -461,7 +461,7 @@
%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY FAILPOLICY
%token RANDOMID REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
-%token ANTISPOOF FOR INCLUDE
+%token ANTISPOOF FOR INCLUDE KEEPCOUNTERS
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY MAPEPORTSET
%token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME
%token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL
@@ -719,6 +719,9 @@
}
keep_state_defaults = $3;
}
+ | SET KEEPCOUNTERS {
+ pf->keep_counters = true;
+ }
;
stringall : STRING { $$ = $1; }
@@ -5593,6 +5596,7 @@
{ "inet6", INET6},
{ "interval", INTERVAL},
{ "keep", KEEP},
+ { "keepcounters", KEEPCOUNTERS},
{ "label", LABEL},
{ "limit", LIMIT},
{ "linkshare", LINKSHARE},
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1745,6 +1745,10 @@
if (pfctl_load_hostid(pf, pf->hostid))
error = 1;
+ /* load keepcounters */
+ if (pfctl_set_keepcounters(pf->dev, pf->keep_counters))
+ error = 1;
+
return (error);
}
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -98,6 +98,7 @@
u_int32_t debug;
u_int32_t hostid;
char *ifname;
+ bool keep_counters;
u_int8_t timeout_set[PFTM_MAX];
u_int8_t limit_set[PF_LIMIT_MAX];
diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5
--- a/share/man/man5/pf.conf.5
+++ b/share/man/man5/pf.conf.5
@@ -28,7 +28,7 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd December 7, 2019
+.Dd April 19, 2021
.Dt PF.CONF 5
.Os
.Sh NAME
@@ -618,6 +618,13 @@
.It Ar loud
Generate debug messages for common conditions.
.El
+.It Ar set keepcounters
+Preserve rule counters across rule updates.
+Usually rule counters are reset to zero on every update of the ruleset.
+With
+.Ar keepcounters
+set pf will attempt to find matching rules between old and new rulesets
+and preserve the rule counters.
.El
.Sh TRAFFIC NORMALIZATION
Traffic normalization is used to sanitize packet content in such
@@ -2888,7 +2895,8 @@
[ "require-order" ( "yes" | "no" ) ]
[ "fingerprints" filename ] |
[ "skip on" ifspec ] |
- [ "debug" ( "none" | "urgent" | "misc" | "loud" ) ] )
+ [ "debug" ( "none" | "urgent" | "misc" | "loud" ) ]
+ [ "keepcounters" ] )
pf-rule = action [ ( "in" | "out" ) ]
[ "log" [ "(" logopts ")"] ] [ "quick" ]
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -996,6 +996,7 @@
uint32_t hostid;
char ifname[IFNAMSIZ];
uint8_t pf_chksum[PF_MD5_DIGEST_LENGTH];
+ bool keep_counters;
};
struct pf_divert {
@@ -1304,6 +1305,8 @@
#define DIOCSETIFFLAG _IOWR('D', 89, struct pfioc_iface)
#define DIOCCLRIFFLAG _IOWR('D', 90, struct pfioc_iface)
#define DIOCKILLSRCNODES _IOWR('D', 91, struct pfioc_src_node_kill)
+#define DIOCKEEPCOUNTERS _IOWR('D', 92, struct pfioc_nv)
+
struct pf_ifspeed_v0 {
char ifname[IFNAMSIZ];
u_int32_t baudrate;
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -197,6 +197,7 @@
static int pf_clear_tables(void);
static void pf_clear_srcnodes(struct pf_ksrc_node *);
static void pf_kill_srcnodes(struct pfioc_src_node_kill *);
+static int pf_keepcounters(struct pfioc_nv *);
static void pf_tbladdr_copyout(struct pf_addr_wrap *);
/*
@@ -1022,11 +1023,27 @@
PF_MD5_UPD(rule, tos);
}
+static bool
+pf_krule_compare(struct pf_krule *a, struct pf_krule *b)
+{
+ MD5_CTX ctx[2];
+ u_int8_t digest[2][PF_MD5_DIGEST_LENGTH];
+
+ MD5Init(&ctx[0]);
+ MD5Init(&ctx[1]);
+ pf_hash_rule(&ctx[0], a);
+ pf_hash_rule(&ctx[1], b);
+ MD5Final(digest[0], &ctx[0]);
+ MD5Final(digest[1], &ctx[1]);
+
+ return (memcmp(digest[0], digest[1], PF_MD5_DIGEST_LENGTH) == 0);
+}
+
static int
pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
{
struct pf_kruleset *rs;
- struct pf_krule *rule, **old_array;
+ struct pf_krule *rule, **old_array, *tail;
struct pf_krulequeue *old_rules;
int error;
u_int32_t old_rcount;
@@ -1058,6 +1075,29 @@
rs->rules[rs_num].inactive.ptr_array;
rs->rules[rs_num].active.rcount =
rs->rules[rs_num].inactive.rcount;
+
+ /* Attempt to preserve counter information. */
+ if (V_pf_status.keep_counters) {
+ TAILQ_FOREACH(rule, rs->rules[rs_num].active.ptr,
+ entries) {
+ tail = TAILQ_FIRST(old_rules);
+ while ((tail != NULL) && ! pf_krule_compare(tail, rule))
+ tail = TAILQ_NEXT(tail, entries);
+ if (tail != NULL) {
+ counter_u64_add(rule->evaluations,
+ counter_u64_fetch(tail->evaluations));
+ counter_u64_add(rule->packets[0],
+ counter_u64_fetch(tail->packets[0]));
+ counter_u64_add(rule->packets[1],
+ counter_u64_fetch(tail->packets[1]));
+ counter_u64_add(rule->bytes[0],
+ counter_u64_fetch(tail->bytes[0]));
+ counter_u64_add(rule->bytes[1],
+ counter_u64_fetch(tail->bytes[1]));
+ }
+ }
+ }
+
rs->rules[rs_num].inactive.ptr = old_rules;
rs->rules[rs_num].inactive.ptr_array = old_array;
rs->rules[rs_num].inactive.rcount = old_rcount;
@@ -4948,6 +4988,10 @@
pf_kill_srcnodes((struct pfioc_src_node_kill *)addr);
break;
+ case DIOCKEEPCOUNTERS:
+ error = pf_keepcounters((struct pfioc_nv *)addr);
+ break;
+
case DIOCSETHOSTID: {
u_int32_t *hostid = (u_int32_t *)addr;
@@ -5227,6 +5271,41 @@
psnk->psnk_killed = pf_free_src_nodes(&kill);
}
+static int
+pf_keepcounters(struct pfioc_nv *nv)
+{
+ nvlist_t *nvl = NULL;
+ void *nvlpacked = NULL;
+ int error = 0;
+
+#define ERROUT(x) do { error = (x); goto on_error; } while (0)
+
+ if (nv->len > pf_ioctl_maxcount)
+ ERROUT(ENOMEM);
+
+ nvlpacked = malloc(nv->len, M_TEMP, M_WAITOK);
+ if (nvlpacked == NULL)
+ ERROUT(ENOMEM);
+
+ error = copyin(nv->data, nvlpacked, nv->len);
+ if (error)
+ ERROUT(error);
+
+ nvl = nvlist_unpack(nvlpacked, nv->len, 0);
+ if (nvl == NULL)
+ ERROUT(EBADMSG);
+
+ if (! nvlist_exists_bool(nvl, "keep_counters"))
+ ERROUT(EBADMSG);
+
+ V_pf_status.keep_counters = nvlist_get_bool(nvl, "keep_counters");
+
+on_error:
+ nvlist_destroy(nvl);
+ free(nvlpacked, M_TEMP);
+ return (error);
+}
+
/*
* XXX - Check for version missmatch!!!
*/

File Metadata

Mime Type
text/plain
Expires
Sat, Jul 4, 6:46 AM (9 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34636029
Default Alt Text
D29780.id87706.diff (7 KB)

Event Timeline