If a rule is set up to tag a packet, then a host sending a packet with TTL of 1 TTL 1 results in a state being created on the input interface only. Any subsequent packet sent that matches that state entry is not tagged. This means that output rules that depend on a particular tag being set (queuing rules, perhaps?) can be circumvented by generating an initial state with TTL 1 and then increasing the ttl. This patch makes packets that match a state entry unconditionally get tagged with the tag of the rule that created the state entry, so such an output rule cannot be circumvented. Note: STATE_LOOKUP() probably isn't the correct place to tag the packets - we can't report the reason for the drop if we are out of memory, but it is a minimal code change to demonstrate the problem/solution. Chris Pascoe 2004/03/09 Index: pf.c =================================================================== RCS file: /cvs/src/sys/net/pf.c,v retrieving revision 1.428 diff -u -r1.428 pf.c --- pf.c 24 Feb 2004 12:09:34 -0000 1.428 +++ pf.c 9 Mar 2004 03:17:36 -0000 @@ -171,7 +171,8 @@ struct pfi_kif *, struct mbuf *, int, void *, struct pf_pdesc *); int pf_test_state_other(struct pf_state **, int, - struct pfi_kif *, struct pf_pdesc *); + struct pfi_kif *, struct mbuf *, + struct pf_pdesc *); struct pf_tag *pf_get_tag(struct mbuf *); int pf_match_tag(struct mbuf *, struct pf_rule *, struct pf_rule *, struct pf_tag *, int *); @@ -222,6 +223,9 @@ kif, &key, PF_LAN_EXT); \ if (*state == NULL) \ return (PF_DROP); \ + if (direction == PF_IN && \ + pf_tag_packet(m, NULL, (*state)->rule.ptr->tag)) \ + return (PF_DROP); \ if (direction == PF_OUT && \ (((*state)->rule.ptr->rt == PF_ROUTETO && \ (*state)->rule.ptr->direction == PF_OUT) || \ @@ -4658,7 +4662,7 @@ int pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif, - struct pf_pdesc *pd) + struct mbuf *m, struct pf_pdesc *pd) { struct pf_state_peer *src, *dst; struct pf_state key; @@ -5396,7 +5400,7 @@ } default: - action = pf_test_state_other(&s, dir, kif, &pd); + action = pf_test_state_other(&s, dir, kif, m, &pd); if (action == PF_PASS) { #if NPFSYNC pfsync_update_state(s); @@ -5724,7 +5728,7 @@ } default: - action = pf_test_state_other(&s, dir, kif, &pd); + action = pf_test_state_other(&s, dir, kif, m, &pd); if (action == PF_PASS) { r = s->rule.ptr; a = s->anchor.ptr;