Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F161379121
D29780.id87706.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D29780.id87706.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D29780: pf: Optionally attempt to preserve rule counter values across ruleset updates
Attached
Detach File
Event Timeline
Log In to Comment