diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2004-07-11 15:54:22 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2004-07-11 15:54:22 +0000 |
commit | 69edafdc30c0ede2371b0e711aa7ed6491d40f2d (patch) | |
tree | 00bee63a80d93ebd3c1162759a7813f1abb23125 | |
parent | 9ea5f5267fff4f5b644f6f036261763f4baac8db (diff) |
backout IPv6 reass-on-scrub patch (more work needs to be done).
requested by deraadt
-rw-r--r-- | sys/net/pf.c | 105 | ||||
-rw-r--r-- | sys/net/pf_norm.c | 137 | ||||
-rw-r--r-- | sys/net/pfvar.h | 4 |
3 files changed, 29 insertions, 217 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c index 1f5a2f3cae5..248b5df7e3e 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.456 2004/06/25 11:04:03 itojun Exp $ */ +/* $OpenBSD: pf.c,v 1.457 2004/07/11 15:54:21 itojun Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -53,7 +53,6 @@ #include <net/if_types.h> #include <net/bpf.h> #include <net/route.h> -#include <net/netisr.h> #include <netinet/in.h> #include <netinet/in_var.h> @@ -1301,7 +1300,7 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af, if (m == NULL) return; if (tag) { - struct m_tag *mtag; + struct m_tag *mtag; mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT); if (mtag == NULL) { @@ -5681,8 +5680,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, { struct pfi_kif *kif; u_short action, reason = 0, log = 0; - struct mbuf *m = *m0, *n; - struct mbuf *frag; + struct mbuf *m = *m0; struct ip6_hdr *h; struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr; struct pf_state *s = NULL; @@ -5711,26 +5709,11 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, goto done; } - /* - * We do IP header normalization and packet reassembly here. - * due to KAME mbuf handling rule, pf_normalize_ip6 may lose mbuf, - * so keep a copy here. - */ - frag = NULL; - n = m_copym(*m0, 0, M_COPYALL, M_DONTWAIT); - m = *m0; - if (pf_normalize_ip6(m0, dir, kif, &reason, &pd, &frag) != PF_PASS) { + /* We do IP header normalization and packet reassembly here */ + if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) { action = PF_DROP; - if (!*m0) - *m0 = n; - else - m_freem(n); goto done; } - if (!*m0) - *m0 = n; - else - m_freem(n); m = *m0; h = mtod(m, struct ip6_hdr *); @@ -5747,6 +5730,12 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, pd.proto = h->ip6_nxt; do { switch (pd.proto) { + case IPPROTO_FRAGMENT: + action = pf_test_fragment(&r, dir, kif, m, h, + &pd, &a, &ruleset); + if (action == PF_DROP) + REASON_SET(&reason, PFRES_FRAG); + goto done; case IPPROTO_AH: case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: @@ -5771,7 +5760,6 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, /* goto the next header */ break; } - case IPPROTO_FRAGMENT: default: terminal++; break; @@ -5999,77 +5987,6 @@ done: /* pf_route6 can free the mbuf causing *m0 to become NULL */ pf_route6(m0, r, dir, ifp, s); - /* - * it's the tricky part - how to return value is different by caller - */ - switch (dir) { - case PF_IN: - if (frag) { - int s; - struct mbuf *q, *r; - struct m_tag *mtag; - - if (action != PF_PASS) { - for (q = frag; q; q = r) { - r = q->m_nextpkt; - q->m_nextpkt = NULL; - m_freem(q); - q = NULL; - } - return (action); - } - - for (q = frag; q; q = r) { - r = q->m_nextpkt; - q->m_nextpkt = NULL; - - mtag = m_tag_get(PACKET_TAG_PF_FRAGCACHE, - 0, M_NOWAIT); - if (mtag == NULL) { - s = splimp(); - IF_DROP(&ip6intrq); - splx(s); - m_freem(q); - q = NULL; - continue; - } - m_tag_prepend(q, mtag); - - s = splimp(); - IF_ENQUEUE(&ip6intrq, q); - q = NULL; - splx(s); - } - schednetisr(NETISR_IPV6); - - m_freem(*m0); - *m0 = NULL; - } - return (PF_PASS); - - case PF_OUT: - if (frag) { - struct mbuf *q, *r; - for (q = frag; q; q = r) { - r = q->m_nextpkt; - q->m_nextpkt = NULL; - m_freem(q); - q = NULL; - } - } - break; - - case PF_FORWARD: - if (action == PF_PASS) { - if (frag) { - m_freem(*m0); - *m0 = NULL; - *m0 = frag; - } else - (*m0)->m_nextpkt = NULL; - } - break; - } return (action); } #endif /* INET6 */ diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c index db8ac4c802b..8a6b2a4aa5b 100644 --- a/sys/net/pf_norm.c +++ b/sys/net/pf_norm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_norm.c,v 1.94 2004/07/05 00:15:20 henning Exp $ */ +/* $OpenBSD: pf_norm.c,v 1.95 2004/07/11 15:54:21 itojun Exp $ */ /* * Copyright 2001 Niels Provos <provos@citi.umich.edu> @@ -56,7 +56,6 @@ #ifdef INET6 #include <netinet/ip6.h> -#include <netinet6/ip6_var.h> #endif /* INET6 */ #include <net/pfvar.h> @@ -105,25 +104,6 @@ RB_HEAD(pf_frag_tree, pf_fragment) pf_frag_tree, pf_cache_tree; RB_PROTOTYPE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare); RB_GENERATE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare); -#ifdef INET6 -struct pf_fragment6 { - TAILQ_ENTRY(pf_fragment6) next; - - /* packets received, connected by m->m_nextpkt */ - struct mbuf *m; - - /* search key */ - struct in6_addr src, dst; - u_int32_t ident; - - struct timeout lifetime; -}; - -TAILQ_HEAD(pf_frag_tree6, pf_fragment6) pf_frag_tree6; - -struct pool pf_fragment6_pl; -#endif - /* Private prototypes */ void pf_ip2key(struct pf_fragment *, struct ip *); void pf_remove_fragment(struct pf_fragment *); @@ -136,13 +116,6 @@ struct mbuf *pf_fragcache(struct mbuf **, struct ip*, struct pf_fragment **, int, int, int *); int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *, struct tcphdr *, int); -#ifdef INET6 -void pf_ip2key6(struct pf_fragment6 *, struct ip6_hdr *, - struct ip6_frag *); -struct pf_fragment6 *pf_find_fragment6(u_int32_t, struct in6_addr *, - struct in6_addr *); -static void pf_frag6_expire(void *); -#endif #define DPFPRINTF(x) do { \ if (pf_status.debug >= PF_DEBUG_MISC) { \ @@ -170,11 +143,6 @@ pf_normalize_init(void) pool_init(&pf_state_scrub_pl, sizeof(struct pf_state_scrub), 0, 0, 0, "pfstscr", NULL); -#ifdef INET6 - pool_init(&pf_fragment6_pl, sizeof(struct pf_fragment6), 0, 0, 0, - "pffrag6", NULL); -#endif - pool_sethiwat(&pf_frag_pl, PFFRAG_FRAG_HIWAT); pool_sethardlimit(&pf_frent_pl, PFFRAG_FRENT_HIWAT, NULL, 0); pool_sethardlimit(&pf_cache_pl, PFFRAG_FRCACHE_HIWAT, NULL, 0); @@ -1058,24 +1026,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason, } #ifdef INET6 -struct pf_fragment6 * -pf_find_fragment6(u_int32_t ident, struct in6_addr *src, struct in6_addr *dst) -{ - struct pf_fragment6 *p; - - TAILQ_FOREACH(p, &pf_frag_tree6, next) { - if (p->ident == ident && IN6_ARE_ADDR_EQUAL(&p->src, src) && - IN6_ARE_ADDR_EQUAL(&p->dst, dst)) - return p; - } - return NULL; -} - int pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif, - u_short *reason, struct pf_pdesc *pd, struct mbuf **tree) + u_short *reason, struct pf_pdesc *pd) { - struct mbuf *m = *m0, *n; + struct mbuf *m = *m0; struct pf_rule *r; struct ip6_hdr *h = mtod(m, struct ip6_hdr *); int off; @@ -1084,18 +1039,11 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif, struct ip6_opt_jumbo jumbo; struct ip6_frag frag; u_int32_t jumbolen = 0, plen; + u_int16_t fragoff = 0; int optend; int ooff; u_int8_t proto; - int protooff; int terminal; - int nxt; - struct pf_fragment6 *frag6; - -#if 1 - if (dir == PF_FORWARD) - return (PF_PASS); -#endif r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr); while (r != NULL) { @@ -1132,19 +1080,10 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif, off = sizeof(struct ip6_hdr); proto = h->ip6_nxt; - protooff = offsetof(struct ip6_hdr, ip6_nxt); terminal = 0; do { switch (proto) { case IPPROTO_FRAGMENT: - if (m_tag_find(m, PACKET_TAG_PF_FRAGCACHE, NULL) - != NULL) { - /* - * the fragment have already passed the - * "scrub in". no need to go to reass code - */ - goto frag_scrub; - } goto fragment; break; case IPPROTO_AH: @@ -1158,7 +1097,6 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif, else off += (ext.ip6e_len + 1) * 8; proto = ext.ip6e_nxt; - protooff = off + offsetof(struct ip6_ext, ip6e_nxt); break; case IPPROTO_HOPOPTS: if (!pf_pull_hdr(m, off, &ext, sizeof(ext), NULL, @@ -1205,7 +1143,6 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif, off = optend; proto = ext.ip6e_nxt; - protooff = off + offsetof(struct ip6_ext, ip6e_nxt); break; default: terminal = 1; @@ -1227,53 +1164,21 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif, if (r->min_ttl && h->ip6_hlim < r->min_ttl) h->ip6_hlim = r->min_ttl; - frag_scrub: return (PF_PASS); fragment: - /* jumbo payload packets cannot be fragmented */ - plen = ntohs(h->ip6_plen); - if (plen == 0 || jumbolen) + if (ntohs(h->ip6_plen) == 0 || jumbolen) goto drop; - - m->m_nextpkt = NULL; + plen = ntohs(h->ip6_plen); if (!pf_pull_hdr(m, off, &frag, sizeof(frag), NULL, NULL, AF_INET6)) goto shortpkt; + fragoff = ntohs(frag.ip6f_offlg & IP6F_OFF_MASK); + if (fragoff + (plen - off - sizeof(frag)) > IPV6_MAXPACKET) + goto badfrag; - frag6 = pf_find_fragment6(frag.ip6f_ident, &h->ip6_src, &h->ip6_dst); - if (frag6 == NULL) { - /* fresh fragment id/src/dst tuple */ - frag6 = pool_get(&pf_fragment6_pl, PR_NOWAIT); - bzero(frag6, sizeof(*frag6)); - frag6->ident = frag.ip6f_ident; - frag6->src = h->ip6_src; - frag6->dst = h->ip6_dst; - timeout_set(&frag6->lifetime, pf_frag6_expire, frag6); - timeout_add(&frag6->lifetime, hz * 60); - TAILQ_INSERT_HEAD(&pf_frag_tree6, frag6, next); - } else - ; /* i saw this id/src/dst tuple in the past */ - - /* to be passed to the caller as is */ - n = m_copym(m, 0, M_COPYALL, M_DONTWAIT); - if (n) { - n->m_nextpkt = frag6->m; - frag6->m = n; - } - n = NULL; - - nxt = frag6_input(m0, &off, IPPROTO_FRAGMENT); - if (nxt == IPPROTO_DONE) { - *m0 = m = NULL; - goto drop; - } - - TAILQ_REMOVE(&pf_frag_tree6, frag6, next); - *tree = frag6->m; - timeout_del(&frag6->lifetime); - pool_put(&pf_fragment6_pl, frag6); - + /* do something about it */ + /* remember to set pd->flags |= PFDESC_IP_REAS */ return (PF_PASS); shortpkt: @@ -1287,22 +1192,12 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif, if (r != NULL && r->log) PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL); return (PF_DROP); -} - -static void -pf_frag6_expire(void *arg) -{ - struct pf_fragment6 *frag6 = (struct pf_fragment6 *)arg; - struct mbuf *n; - - TAILQ_REMOVE(&pf_frag_tree6, frag6, next); - for (; frag6->m; frag6->m = n) { - n = frag6->m->m_nextpkt; - frag6->m->m_nextpkt = NULL; - m_freem(frag6->m); - } - pool_put(&pf_fragment6_pl, frag6); + badfrag: + REASON_SET(reason, PFRES_FRAG); + if (r != NULL && r->log) + PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL); + return (PF_DROP); } #endif /* INET6 */ diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 1e76d254781..74fa7161d5e 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.200 2004/06/25 10:10:14 itojun Exp $ */ +/* $OpenBSD: pfvar.h,v 1.201 2004/07/11 15:54:21 itojun Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1367,7 +1367,7 @@ void pf_normalize_init(void); int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *, struct pf_pdesc *); int pf_normalize_ip6(struct mbuf **, int, struct pfi_kif *, u_short *, - struct pf_pdesc *, struct mbuf **); + struct pf_pdesc *); int pf_normalize_tcp(int, struct pfi_kif *, struct mbuf *, int, int, void *, struct pf_pdesc *); void pf_normalize_tcp_cleanup(struct pf_state *); |