aboutsummaryrefslogtreecommitdiffstats
path: root/sys/contrib/pf/net/pf_norm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/pf/net/pf_norm.c')
-rw-r--r--sys/contrib/pf/net/pf_norm.c143
1 files changed, 93 insertions, 50 deletions
diff --git a/sys/contrib/pf/net/pf_norm.c b/sys/contrib/pf/net/pf_norm.c
index 3c3dbc062ca4..df339ae6f691 100644
--- a/sys/contrib/pf/net/pf_norm.c
+++ b/sys/contrib/pf/net/pf_norm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_norm.c,v 1.97 2004/09/21 16:59:12 aaron Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.107 2006/04/16 00:59:52 pascoe Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -412,7 +412,7 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
break;
}
- /* This fragment is completely overlapped, loose it */
+ /* This fragment is completely overlapped, lose it */
next = LIST_NEXT(frea, fr_next);
m_freem(frea->fr_m);
LIST_REMOVE(frea, fr_next);
@@ -704,7 +704,7 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
} else {
hosed++;
}
- } else {
+ } else if (frp == NULL) {
/* There is a gap between fragments */
DPFPRINTF(("fragcache[%d]: gap %d %d-%d (%d-%d)\n",
h->ip_id, -aftercut, off, max, fra->fr_off,
@@ -831,8 +831,7 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -841,19 +840,23 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
else if (r->proto && r->proto != h->ip_p)
r = r->skip[PF_SKIP_PROTO].ptr;
else if (PF_MISMATCHAW(&r->src.addr,
- (struct pf_addr *)&h->ip_src.s_addr, AF_INET, r->src.neg))
+ (struct pf_addr *)&h->ip_src.s_addr, AF_INET,
+ r->src.neg, kif))
r = r->skip[PF_SKIP_SRC_ADDR].ptr;
else if (PF_MISMATCHAW(&r->dst.addr,
- (struct pf_addr *)&h->ip_dst.s_addr, AF_INET, r->dst.neg))
+ (struct pf_addr *)&h->ip_dst.s_addr, AF_INET,
+ r->dst.neg, NULL))
r = r->skip[PF_SKIP_DST_ADDR].ptr;
else
break;
}
- if (r == NULL)
+ if (r == NULL || r->action == PF_NOSCRUB)
return (PF_PASS);
- else
- r->packets++;
+ else {
+ r->packets[dir == PF_OUT]++;
+ r->bytes[dir == PF_OUT] += pd->tot_len;
+ }
/* Check for illegal packets */
if (hlen < (int)sizeof(struct ip))
@@ -863,8 +866,12 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
goto drop;
/* Clear IP_DF if the rule uses the no-df option */
- if (r->rule_flag & PFRULE_NODF)
+ if (r->rule_flag & PFRULE_NODF && h->ip_off & htons(IP_DF)) {
+ u_int16_t ip_off = h->ip_off;
+
h->ip_off &= htons(~IP_DF);
+ h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_off, h->ip_off, 0);
+ }
/* We will need other tests here */
if (!fragoff && !mff)
@@ -922,6 +929,18 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
if (m == NULL)
return (PF_DROP);
+ /* use mtag from concatenated mbuf chain */
+ pd->pf_mtag = pf_find_mtag(m);
+#ifdef DIAGNOSTIC
+ if (pd->pf_mtag == NULL) {
+ printf("%s: pf_find_mtag returned NULL(1)\n", __func__);
+ if ((pd->pf_mtag = pf_get_mtag(m)) == NULL) {
+ m_freem(m);
+ *m0 = NULL;
+ goto no_mem;
+ }
+ }
+#endif
if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
goto drop;
@@ -930,15 +949,13 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
/* non-buffering fragment cache (drops or masks overlaps) */
int nomem = 0;
- if (dir == PF_OUT) {
- if (m_tag_find(m, PACKET_TAG_PF_FRAGCACHE, NULL) !=
- NULL) {
- /* Already passed the fragment cache in the
- * input direction. If we continued, it would
- * appear to be a dup and would be dropped.
- */
- goto fragment_pass;
- }
+ if (dir == PF_OUT && pd->pf_mtag->flags & PF_TAG_FRAGCACHE) {
+ /*
+ * Already passed the fragment cache in the
+ * input direction. If we continued, it would
+ * appear to be a dup and would be dropped.
+ */
+ goto fragment_pass;
}
frag = pf_find_fragment(h, &pf_cache_tree);
@@ -959,14 +976,21 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
goto drop;
}
- if (dir == PF_IN) {
- struct m_tag *mtag;
-
- mtag = m_tag_get(PACKET_TAG_PF_FRAGCACHE, 0, M_NOWAIT);
- if (mtag == NULL)
+ /* use mtag from copied and trimmed mbuf chain */
+ pd->pf_mtag = pf_find_mtag(m);
+#ifdef DIAGNOSTIC
+ if (pd->pf_mtag == NULL) {
+ printf("%s: pf_find_mtag returned NULL(2)\n", __func__);
+ if ((pd->pf_mtag = pf_get_mtag(m)) == NULL) {
+ m_freem(m);
+ *m0 = NULL;
goto no_mem;
- m_tag_prepend(m, mtag);
+ }
}
+#endif
+ if (dir == PF_IN)
+ pd->pf_mtag->flags |= PF_TAG_FRAGCACHE;
+
if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
goto drop;
goto fragment_pass;
@@ -974,11 +998,20 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
no_fragment:
/* At this point, only IP_DF is allowed in ip_off */
- h->ip_off &= htons(IP_DF);
+ if (h->ip_off & ~htons(IP_DF)) {
+ u_int16_t ip_off = h->ip_off;
+
+ h->ip_off &= htons(IP_DF);
+ h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_off, h->ip_off, 0);
+ }
/* Enforce a minimum ttl, may cause endless packet loops */
- if (r->min_ttl && h->ip_ttl < r->min_ttl)
+ if (r->min_ttl && h->ip_ttl < r->min_ttl) {
+ u_int16_t ip_ttl = h->ip_ttl;
+
h->ip_ttl = r->min_ttl;
+ h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
+ }
if (r->rule_flag & PFRULE_RANDOMID) {
u_int16_t ip_id = h->ip_id;
@@ -993,8 +1026,12 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
fragment_pass:
/* Enforce a minimum ttl, may cause endless packet loops */
- if (r->min_ttl && h->ip_ttl < r->min_ttl)
+ if (r->min_ttl && h->ip_ttl < r->min_ttl) {
+ u_int16_t ip_ttl = h->ip_ttl;
+
h->ip_ttl = r->min_ttl;
+ h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
+ }
if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
pd->flags |= PFDESC_IP_REAS;
return (PF_PASS);
@@ -1002,13 +1039,13 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
no_mem:
REASON_SET(reason, PFRES_MEMORY);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
drop:
REASON_SET(reason, PFRES_NORM);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
bad:
@@ -1020,7 +1057,7 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
REASON_SET(reason, PFRES_FRAG);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
}
@@ -1048,8 +1085,7 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -1060,19 +1096,23 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
r = r->skip[PF_SKIP_PROTO].ptr;
#endif
else if (PF_MISMATCHAW(&r->src.addr,
- (struct pf_addr *)&h->ip6_src, AF_INET6, r->src.neg))
+ (struct pf_addr *)&h->ip6_src, AF_INET6,
+ r->src.neg, kif))
r = r->skip[PF_SKIP_SRC_ADDR].ptr;
else if (PF_MISMATCHAW(&r->dst.addr,
- (struct pf_addr *)&h->ip6_dst, AF_INET6, r->dst.neg))
+ (struct pf_addr *)&h->ip6_dst, AF_INET6,
+ r->dst.neg, NULL))
r = r->skip[PF_SKIP_DST_ADDR].ptr;
else
break;
}
- if (r == NULL)
+ if (r == NULL || r->action == PF_NOSCRUB)
return (PF_PASS);
- else
- r->packets++;
+ else {
+ r->packets[dir == PF_OUT]++;
+ r->bytes[dir == PF_OUT] += pd->tot_len;
+ }
/* Check for illegal packets */
if (sizeof(struct ip6_hdr) + IPV6_MAXPACKET < m->m_pkthdr.len)
@@ -1184,19 +1224,19 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
shortpkt:
REASON_SET(reason, PFRES_SHORT);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
drop:
REASON_SET(reason, PFRES_NORM);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
badfrag:
REASON_SET(reason, PFRES_FRAG);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
}
#endif /* INET6 */
@@ -1215,8 +1255,7 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -1224,12 +1263,14 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
r = r->skip[PF_SKIP_AF].ptr;
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))
+ else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
+ r->src.neg, kif))
r = r->skip[PF_SKIP_SRC_ADDR].ptr;
else if (r->src.port_op && !pf_match_port(r->src.port_op,
r->src.port[0], r->src.port[1], th->th_sport))
r = r->skip[PF_SKIP_SRC_PORT].ptr;
- else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af, r->dst.neg))
+ else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
+ r->dst.neg, NULL))
r = r->skip[PF_SKIP_DST_ADDR].ptr;
else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
r->dst.port[0], r->dst.port[1], th->th_dport))
@@ -1246,8 +1287,10 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
if (rm == NULL || rm->action == PF_NOSCRUB)
return (PF_PASS);
- else
- r->packets++;
+ else {
+ r->packets[dir == PF_OUT]++;
+ r->bytes[dir == PF_OUT] += pd->tot_len;
+ }
if (rm->rule_flag & PFRULE_REASSEMBLE_TCP)
pd->flags |= PFDESC_TCP_NORM;
@@ -1309,7 +1352,7 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
tcp_drop:
REASON_SET(&reason, PFRES_NORM);
if (rm != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, NULL, NULL);
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, NULL, NULL, pd);
return (PF_DROP);
}
@@ -1743,7 +1786,7 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
* timestamps. And require all data packets to contain a timestamp
* if the first does. PAWS implicitly requires that all data packets be
* timestamped. But I think there are middle-man devices that hijack
- * TCP streams immedietly after the 3whs and don't timestamp their
+ * TCP streams immediately after the 3whs and don't timestamp their
* packets (seen in a WWW accelerator or cache).
*/
if (pd->p_len > 0 && src->scrub && (src->scrub->pfss_flags &