Hello tech@
I've noticed different behavior of pf rule counters between IPv4 and
IPv6. The easiest ruleset would look like:

block
match on em0 inet6 tag potazmo
match on em0 inet tag ausfahrt
pass on em0 from any to any tagged potazmo
pass on em0 from any to any tagged ausfahrt

where ping4s are counted to both rules, ping6s are counted only to the
last rule.
I noticed the code repeats, so made a function from it. Please report
if it's alright and of any use. Apologies for possible spaces instead
of tabs :-(

Index: pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.696
diff -u -p -r1.696 pf.c
--- pf.c        5 Aug 2010 17:21:19 -0000       1.696
+++ pf.c        1 Sep 2010 12:49:59 -0000
@@ -5517,6 +5517,62 @@ pf_get_divert(struct mbuf *m)
        return ((struct pf_divert *)(mtag + 1));
 }

+void
+pf_increase_counters(int dir, int action, struct pf_pdesc *pd,
+    struct pfi_kif *kif, struct pf_state *s,
+    struct pf_rule *r, struct pf_rule *a)
+{
+       int dirndx;
+       kif->pfik_bytes[pd->af == AF_INET6][dir == PF_OUT][action != PF_PASS]
+           += pd->tot_len;
+       kif->pfik_packets[pd->af == AF_INET6][dir == PF_OUT][action !=
PF_PASS]++;
+
+       if (action == PF_PASS || r->action == PF_DROP) {
+               dirndx = (dir == PF_OUT);
+               r->packets[dirndx]++;
+               r->bytes[dirndx] += pd->tot_len;
+               if (a != NULL) {
+                       a->packets[dirndx]++;
+                       a->bytes[dirndx] += pd->tot_len;
+               }
+               if (s != NULL) {
+                       struct pf_rule_item     *ri;
+                       struct pf_sn_item       *sni;
+
+                       SLIST_FOREACH(sni, &s->src_nodes, next) {
+                               sni->sn->packets[dirndx]++;
+                               sni->sn->bytes[dirndx] += pd->tot_len;
+                       }
+                       dirndx = (dir == s->direction) ? 0 : 1;
+                       s->packets[dirndx]++;
+                       s->bytes[dirndx] += pd->tot_len;
+
+                       /*
+                        * We want to increase counters on _all_ rules
+                        * that were matched during processing.
+                        */
+                       SLIST_FOREACH(ri, &s->match_rules, entry) {
+                               ri->r->packets[dirndx]++;
+                               ri->r->bytes[dirndx] += pd->tot_len;
+                       }
+               }
+               if (r->src.addr.type == PF_ADDR_TABLE)
+                       pfr_update_stats(r->src.addr.p.tbl,
+                           (s == NULL) ? pd->src :
+                           &s->key[(s->direction == PF_IN)]->
+                               addr[(s->direction == PF_OUT)],
+                           pd->af, pd->tot_len, dir == PF_OUT,
+                           r->action == PF_PASS, r->src.neg);
+               if (r->dst.addr.type == PF_ADDR_TABLE)
+                       pfr_update_stats(r->dst.addr.p.tbl,
+                           (s == NULL) ? pd->dst :
+                           &s->key[(s->direction == PF_IN)]->
+                               addr[(s->direction == PF_IN)],
+                           pd->af, pd->tot_len, dir == PF_OUT,
+                           r->action == PF_PASS, r->dst.neg);
+       }
+}
+
 #ifdef INET
 int
 pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
@@ -5530,7 +5586,7 @@ pf_test(int dir, struct ifnet *ifp, stru
        struct pf_state         *s = NULL;
        struct pf_ruleset       *ruleset = NULL;
        struct pf_pdesc          pd;
-       int                      off, dirndx, pqid = 0;
+       int                      off, pqid = 0;
        u_int16_t                qid;

        if (!pf_status.running)
@@ -5812,48 +5868,7 @@ done:
                }
        }

-       kif->pfik_bytes[0][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
-       kif->pfik_packets[0][dir == PF_OUT][action != PF_PASS]++;
-
-       if (action == PF_PASS || r->action == PF_DROP) {
-               dirndx = (dir == PF_OUT);
-               r->packets[dirndx]++;
-               r->bytes[dirndx] += pd.tot_len;
-               if (a != NULL) {
-                       a->packets[dirndx]++;
-                       a->bytes[dirndx] += pd.tot_len;
-               }
-               if (s != NULL) {
-                       struct pf_rule_item     *ri;
-                       struct pf_sn_item       *sni;
-
-                       SLIST_FOREACH(sni, &s->src_nodes, next) {
-                               sni->sn->packets[dirndx]++;
-                               sni->sn->bytes[dirndx] += pd.tot_len;
-                       }
-                       dirndx = (dir == s->direction) ? 0 : 1;
-                       s->packets[dirndx]++;
-                       s->bytes[dirndx] += pd.tot_len;
-                       SLIST_FOREACH(ri, &s->match_rules, entry) {
-                               ri->r->packets[dirndx]++;
-                               ri->r->bytes[dirndx] += pd.tot_len;
-                       }
-               }
-               if (r->src.addr.type == PF_ADDR_TABLE)
-                       pfr_update_stats(r->src.addr.p.tbl,
-                           (s == NULL) ? pd.src :
-                           &s->key[(s->direction == PF_IN)]->
-                               addr[(s->direction == PF_OUT)],
-                           pd.af, pd.tot_len, dir == PF_OUT,
-                           r->action == PF_PASS, r->src.neg);
-               if (r->dst.addr.type == PF_ADDR_TABLE)
-                       pfr_update_stats(r->dst.addr.p.tbl,
-                           (s == NULL) ? pd.dst :
-                           &s->key[(s->direction == PF_IN)]->
-                               addr[(s->direction == PF_IN)],
-                           pd.af, pd.tot_len, dir == PF_OUT,
-                           r->action == PF_PASS, r->dst.neg);
-       }
+       pf_increase_counters(dir, action, &pd, kif, s, r, a);

        switch (action) {
        case PF_SYNPROXY_DROP:
@@ -5891,7 +5906,7 @@ pf_test6(int dir, struct ifnet *ifp, str
        struct pf_state         *s = NULL;
        struct pf_ruleset       *ruleset = NULL;
        struct pf_pdesc          pd;
-       int                      off, terminal = 0, dirndx, rh_cnt = 0;
+       int                      off, terminal = 0, rh_cnt = 0;

        if (!pf_status.running)
                return (PF_PASS);
@@ -6255,41 +6270,7 @@ done:
                }
        }

-       kif->pfik_bytes[1][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
-       kif->pfik_packets[1][dir == PF_OUT][action != PF_PASS]++;
-
-       if (action == PF_PASS || r->action == PF_DROP) {
-               dirndx = (dir == PF_OUT);
-               r->packets[dirndx]++;
-               r->bytes[dirndx] += pd.tot_len;
-               if (a != NULL) {
-                       a->packets[dirndx]++;
-                       a->bytes[dirndx] += pd.tot_len;
-               }
-               if (s != NULL) {
-                       struct pf_sn_item       *sni;
-
-                       SLIST_FOREACH(sni, &s->src_nodes, next) {
-                               sni->sn->packets[dirndx]++;
-                               sni->sn->bytes[dirndx] += pd.tot_len;
-                       }
-                       dirndx = (dir == s->direction) ? 0 : 1;
-                       s->packets[dirndx]++;
-                       s->bytes[dirndx] += pd.tot_len;
-               }
-               if (r->src.addr.type == PF_ADDR_TABLE)
-                       pfr_update_stats(r->src.addr.p.tbl,
-                           (s == NULL) ? pd.src :
-                           &s->key[(s->direction == PF_IN)]->addr[0],
-                           pd.af, pd.tot_len, dir == PF_OUT,
-                           r->action == PF_PASS, r->src.neg);
-               if (r->dst.addr.type == PF_ADDR_TABLE)
-                       pfr_update_stats(r->dst.addr.p.tbl,
-                           (s == NULL) ? pd.dst :
-                           &s->key[(s->direction == PF_IN)]->addr[1],
-                           pd.af, pd.tot_len, dir == PF_OUT,
-                           r->action == PF_PASS, r->dst.neg);
-       }
+       pf_increase_counters(dir, action, &pd, kif, s, r, a);

        switch (action) {
        case PF_SYNPROXY_DROP:
Index: pfvar.h
===================================================================
RCS file: /cvs/src/sys/net/pfvar.h,v
retrieving revision 1.311
diff -u -p -r1.311 pfvar.h
--- pfvar.h     28 Jun 2010 23:21:41 -0000      1.311
+++ pfvar.h     1 Sep 2010 12:49:59 -0000
@@ -1735,6 +1735,10 @@ extern void
pf_addrcpy(struct pf_addr
 void                            pf_rm_rule(struct pf_rulequeue *,
                                    struct pf_rule *);
 struct pf_divert               *pf_find_divert(struct mbuf *);
+void                            pf_increase_counters(int, int,
+                                   struct pf_pdesc *, struct pfi_kif *,
+                                   struct pf_state *, struct pf_rule *,
+                                   struct pf_rule *);

 #ifdef INET
 int    pf_test(int, struct ifnet *, struct mbuf **, struct ether_header *);



-- 
Martin Pelikan

Reply via email to