Hello, this is a new version based on corrections by henning@ with few more things added. I'm not sure whether the type changes in pfvar.h won't break anything, but it would be nice to have the types uniform. Any comments or suggestions?
-- Martin Pelikan Index: net/pf.c =================================================================== RCS file: /cvs/src/sys/net/pf.c,v retrieving revision 1.696 diff -u -p -r1.696 pf.c --- net/pf.c 5 Aug 2010 17:21:19 -0000 1.696 +++ net/pf.c 1 Sep 2010 22:04:03 -0000 @@ -231,6 +231,10 @@ struct pf_state *pf_find_state(struct p int pf_src_connlimit(struct pf_state **); int pf_check_congestion(struct ifqueue *); int pf_match_rcvif(struct mbuf *, struct pf_rule *); +void pf_inc_counters(int, int, + struct pf_pdesc *, struct pfi_kif *, + struct pf_state *, struct pf_rule *, + struct pf_rule *); extern struct pool pfr_ktable_pl; extern struct pool pfr_kentry_pl; @@ -3413,10 +3417,10 @@ pf_test_fragment(struct pf_rule **rm, in else if (r->proto && r->proto != pd->proto) r = r->skip[PF_SKIP_PROTO].ptr; else if (PF_MISMATCHAW(&r->src.addr, pd->src, af, - r->src.neg, kif, /* XXX rdomain */ 0)) + r->src.neg, kif, r->rtableid)) r = r->skip[PF_SKIP_SRC_ADDR].ptr; else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af, - r->dst.neg, NULL, /* XXX rdomain */ 0)) + r->dst.neg, NULL, r->rtableid)) r = r->skip[PF_SKIP_DST_ADDR].ptr; else if (r->tos && !(r->tos == pd->tos)) r = TAILQ_NEXT(r, entries); @@ -5517,6 +5521,64 @@ pf_get_divert(struct mbuf *m) return ((struct pf_divert *)(mtag + 1)); } +void +pf_inc_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. + * XXX This does NOT affect pass rules! + * XXX Change this in pf_test_rule()? + */ + 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,8 +5592,8 @@ 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; - u_int16_t qid; + int off; + u_int32_t qid, pqid = 0; if (!pf_status.running) return (PF_PASS); @@ -5749,8 +5811,6 @@ done: qid = s->qid; } else { pf_scrub_ip(&m, r->scrub_flags, r->min_ttl, r->set_tos); - /* XXX tag not needed since it is done in pf_test_rule ??? */ - pf_tag_packet(m, r->tag, r->rtableid); if (pqid || (pd.tos & IPTOS_LOWDELAY)) qid = r->pqid; else @@ -5812,48 +5872,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_inc_counters(dir, action, &pd, kif, s, r, a); switch (action) { case PF_SYNPROXY_DROP: @@ -5891,7 +5910,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 +6274,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_inc_counters(dir, action, &pd, kif, s, r, a); switch (action) { case PF_SYNPROXY_DROP: Index: net/pfvar.h =================================================================== RCS file: /cvs/src/sys/net/pfvar.h,v retrieving revision 1.311 diff -u -p -r1.311 pfvar.h --- net/pfvar.h 28 Jun 2010 23:21:41 -0000 1.311 +++ net/pfvar.h 1 Sep 2010 22:04:03 -0000 @@ -519,8 +519,8 @@ struct pf_osfp_ioctl { struct pf_rule_actions { int rtableid; - u_int16_t qid; - u_int16_t pqid; + u_int32_t qid; + u_int32_t pqid; u_int16_t max_mss; u_int8_t log; u_int8_t set_tos; @@ -810,8 +810,8 @@ struct pf_state { u_int32_t creation; u_int32_t expire; u_int32_t pfsync_time; - u_int16_t qid; - u_int16_t pqid; + u_int32_t qid; + u_int32_t pqid; u_int16_t tag; u_int16_t state_flags; #define PFSTATE_ALLOWOPTS 0x0001