Apply by doing: cd /usr/src patch -p0 < 006_pfnorm.patch And then rebuild your kernel. Index: sys/net/pf_norm.c =================================================================== RCS file: /cvs/src/sys/net/pf_norm.c,v retrieving revision 1.55 retrieving revision 1.55.2.1 diff -u -r1.55 -r1.55.2.1 --- sys/net/pf_norm.c 18 Feb 2003 08:05:15 -0000 1.55 +++ sys/net/pf_norm.c 24 Sep 2003 19:31:19 -0000 1.55.2.1 @@ -105,10 +105,10 @@ void pf_flush_fragments(void); void pf_free_fragment(struct pf_fragment *); struct pf_fragment *pf_find_fragment(struct ip *, struct pf_frag_tree *); -struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment *, +struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment **, struct pf_frent *, int); struct mbuf *pf_fragcache(struct mbuf **, struct ip*, - struct pf_fragment *, int, int, int *); + struct pf_fragment **, int, int, int *); u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t); int pf_normalize_tcp(int, struct ifnet *, struct mbuf *, int, int, void *, struct pf_pdesc *); @@ -308,7 +308,7 @@ } struct mbuf * -pf_reassemble(struct mbuf **m0, struct pf_fragment *frag, +pf_reassemble(struct mbuf **m0, struct pf_fragment **frag, struct pf_frent *frent, int mff) { struct mbuf *m = *m0, *m2; @@ -319,33 +319,33 @@ u_int16_t off = ip->ip_off; u_int16_t max = ip->ip_len + off; - KASSERT(frag == NULL || BUFFER_FRAGMENTS(frag)); + KASSERT(*frag == NULL || BUFFER_FRAGMENTS(*frag)); /* Strip off ip header */ m->m_data += hlen; m->m_len -= hlen; /* Create a new reassembly queue for this packet */ - if (frag == NULL) { - frag = pool_get(&pf_frag_pl, PR_NOWAIT); - if (frag == NULL) { + if (*frag == NULL) { + *frag = pool_get(&pf_frag_pl, PR_NOWAIT); + if (*frag == NULL) { pf_flush_fragments(); - frag = pool_get(&pf_frag_pl, PR_NOWAIT); - if (frag == NULL) + *frag = pool_get(&pf_frag_pl, PR_NOWAIT); + if (*frag == NULL) goto drop_fragment; } - frag->fr_flags = 0; - frag->fr_max = 0; - frag->fr_src = frent->fr_ip->ip_src; - frag->fr_dst = frent->fr_ip->ip_dst; - frag->fr_p = frent->fr_ip->ip_p; - frag->fr_id = frent->fr_ip->ip_id; - frag->fr_timeout = time.tv_sec; - LIST_INIT(&frag->fr_queue); + (*frag)->fr_flags = 0; + (*frag)->fr_max = 0; + (*frag)->fr_src = frent->fr_ip->ip_src; + (*frag)->fr_dst = frent->fr_ip->ip_dst; + (*frag)->fr_p = frent->fr_ip->ip_p; + (*frag)->fr_id = frent->fr_ip->ip_id; + (*frag)->fr_timeout = time.tv_sec; + LIST_INIT(&(*frag)->fr_queue); - RB_INSERT(pf_frag_tree, &pf_frag_tree, frag); - TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next); + RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag); + TAILQ_INSERT_HEAD(&pf_fragqueue, *frag, frag_next); /* We do not have a previous fragment */ frep = NULL; @@ -356,7 +356,7 @@ * Find a fragment after the current one: * - off contains the real shifted offset. */ - LIST_FOREACH(frea, &frag->fr_queue, fr_next) { + LIST_FOREACH(frea, &(*frag)->fr_queue, fr_next) { if (frea->fr_ip->ip_off > off) break; frep = frea; @@ -400,45 +400,46 @@ insert: /* Update maximum data size */ - if (frag->fr_max < max) - frag->fr_max = max; + if ((*frag)->fr_max < max) + (*frag)->fr_max = max; /* This is the last segment */ if (!mff) - frag->fr_flags |= PFFRAG_SEENLAST; + (*frag)->fr_flags |= PFFRAG_SEENLAST; if (frep == NULL) - LIST_INSERT_HEAD(&frag->fr_queue, frent, fr_next); + LIST_INSERT_HEAD(&(*frag)->fr_queue, frent, fr_next); else LIST_INSERT_AFTER(frep, frent, fr_next); /* Check if we are completely reassembled */ - if (!(frag->fr_flags & PFFRAG_SEENLAST)) + if (!((*frag)->fr_flags & PFFRAG_SEENLAST)) return (NULL); /* Check if we have all the data */ off = 0; - for (frep = LIST_FIRST(&frag->fr_queue); frep; frep = next) { + for (frep = LIST_FIRST(&(*frag)->fr_queue); frep; frep = next) { next = LIST_NEXT(frep, fr_next); off += frep->fr_ip->ip_len; - if (off < frag->fr_max && + if (off < (*frag)->fr_max && (next == NULL || next->fr_ip->ip_off != off)) { DPFPRINTF(("missing fragment at %d, next %d, max %d\n", off, next == NULL ? -1 : next->fr_ip->ip_off, - frag->fr_max)); + (*frag)->fr_max)); return (NULL); } } - DPFPRINTF(("%d < %d?\n", off, frag->fr_max)); - if (off < frag->fr_max) + DPFPRINTF(("%d < %d?\n", off, (*frag)->fr_max)); + if (off < (*frag)->fr_max) return (NULL); /* We have all the data */ - frent = LIST_FIRST(&frag->fr_queue); + frent = LIST_FIRST(&(*frag)->fr_queue); KASSERT(frent != NULL); if ((frent->fr_ip->ip_hl << 2) + off > IP_MAXPACKET) { DPFPRINTF(("drop: too big: %d\n", off)); - pf_free_fragment(frag); + pf_free_fragment(*frag); + *frag = NULL; return (NULL); } next = LIST_NEXT(frent, fr_next); @@ -460,11 +461,12 @@ m_cat(m, m2); } - ip->ip_src = frag->fr_src; - ip->ip_dst = frag->fr_dst; + ip->ip_src = (*frag)->fr_src; + ip->ip_dst = (*frag)->fr_dst; /* Remove from fragment queue */ - pf_remove_fragment(frag); + pf_remove_fragment(*frag); + *frag = NULL; hlen = ip->ip_hl << 2; ip->ip_len = off + hlen; @@ -492,7 +494,7 @@ } struct mbuf * -pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment *frag, int mff, +pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff, int drop, int *nomem) { struct mbuf *m = *m0; @@ -502,41 +504,42 @@ u_int16_t max = ip_len + off; int hosed = 0; - KASSERT(frag == NULL || !BUFFER_FRAGMENTS(frag)); + KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag)); /* Create a new range queue for this packet */ - if (frag == NULL) { - frag = pool_get(&pf_cache_pl, PR_NOWAIT); - if (frag == NULL) { + if (*frag == NULL) { + *frag = pool_get(&pf_cache_pl, PR_NOWAIT); + if (*frag == NULL) { pf_flush_fragments(); - frag = pool_get(&pf_cache_pl, PR_NOWAIT); - if (frag == NULL) + *frag = pool_get(&pf_cache_pl, PR_NOWAIT); + if (*frag == NULL) goto no_mem; } /* Get an entry for the queue */ cur = pool_get(&pf_cent_pl, PR_NOWAIT); if (cur == NULL) { - pool_put(&pf_cache_pl, frag); + pool_put(&pf_cache_pl, *frag); + *frag = NULL; goto no_mem; } pf_ncache++; - frag->fr_flags = PFFRAG_NOBUFFER; - frag->fr_max = 0; - frag->fr_src = h->ip_src; - frag->fr_dst = h->ip_dst; - frag->fr_p = h->ip_p; - frag->fr_id = h->ip_id; - frag->fr_timeout = time.tv_sec; + (*frag)->fr_flags = PFFRAG_NOBUFFER; + (*frag)->fr_max = 0; + (*frag)->fr_src = h->ip_src; + (*frag)->fr_dst = h->ip_dst; + (*frag)->fr_p = h->ip_p; + (*frag)->fr_id = h->ip_id; + (*frag)->fr_timeout = time.tv_sec; cur->fr_off = off; cur->fr_end = max; - LIST_INIT(&frag->fr_cache); - LIST_INSERT_HEAD(&frag->fr_cache, cur, fr_next); + LIST_INIT(&(*frag)->fr_cache); + LIST_INSERT_HEAD(&(*frag)->fr_cache, cur, fr_next); - RB_INSERT(pf_frag_tree, &pf_cache_tree, frag); - TAILQ_INSERT_HEAD(&pf_cachequeue, frag, frag_next); + RB_INSERT(pf_frag_tree, &pf_cache_tree, *frag); + TAILQ_INSERT_HEAD(&pf_cachequeue, *frag, frag_next); DPFPRINTF(("fragcache[%d]: new %d-%d\n", h->ip_id, off, max)); @@ -548,7 +551,7 @@ * - off contains the real shifted offset. */ frp = NULL; - LIST_FOREACH(fra, &frag->fr_cache, fr_next) { + LIST_FOREACH(fra, &(*frag)->fr_cache, fr_next) { if (fra->fr_off > off) break; frp = fra; @@ -735,21 +738,22 @@ pass: /* Update maximum data size */ - if (frag->fr_max < max) - frag->fr_max = max; + if ((*frag)->fr_max < max) + (*frag)->fr_max = max; /* This is the last segment */ if (!mff) - frag->fr_flags |= PFFRAG_SEENLAST; + (*frag)->fr_flags |= PFFRAG_SEENLAST; /* Check if we are completely reassembled */ - if ((frag->fr_flags & PFFRAG_SEENLAST) && - LIST_FIRST(&frag->fr_cache)->fr_off == 0 && - LIST_FIRST(&frag->fr_cache)->fr_end == frag->fr_max) { + if (((*frag)->fr_flags & PFFRAG_SEENLAST) && + LIST_FIRST(&(*frag)->fr_cache)->fr_off == 0 && + LIST_FIRST(&(*frag)->fr_cache)->fr_end == (*frag)->fr_max) { /* Remove from fragment queue */ DPFPRINTF(("fragcache[%d]: done 0-%d\n", h->ip_id, - frag->fr_max)); - pf_free_fragment(frag); + (*frag)->fr_max)); + pf_free_fragment(*frag); + *frag = NULL; } return (m); @@ -758,8 +762,8 @@ *nomem = 1; /* Still need to pay attention to !IP_MF */ - if (!mff && frag) - frag->fr_flags |= PFFRAG_SEENLAST; + if (!mff && *frag != NULL) + (*frag)->fr_flags |= PFFRAG_SEENLAST; m_freem(m); return (NULL); @@ -767,15 +771,15 @@ drop_fragment: /* Still need to pay attention to !IP_MF */ - if (!mff && frag) - frag->fr_flags |= PFFRAG_SEENLAST; + if (!mff && *frag != NULL) + (*frag)->fr_flags |= PFFRAG_SEENLAST; if (drop) { /* This fragment has been deemed bad. Don't reass */ - if ((frag->fr_flags & PFFRAG_DROP) == 0) + if (((*frag)->fr_flags & PFFRAG_DROP) == 0) DPFPRINTF(("fragcache[%d]: dropping overall fragment\n", h->ip_id)); - frag->fr_flags |= PFFRAG_DROP; + (*frag)->fr_flags |= PFFRAG_DROP; } m_freem(m); @@ -887,12 +891,12 @@ /* Might return a completely reassembled mbuf, or NULL */ DPFPRINTF(("reass frag %d @ %d-%d\n", h->ip_id, fragoff, max)); - *m0 = m = pf_reassemble(m0, frag, frent, mff); + *m0 = m = pf_reassemble(m0, &frag, frent, mff); if (m == NULL) return (PF_DROP); - if (frag && (frag->fr_flags & PFFRAG_DROP)) + if (frag != NULL && (frag->fr_flags & PFFRAG_DROP)) goto drop; h = mtod(m, struct ip *); @@ -921,7 +925,7 @@ goto bad; } - *m0 = m = pf_fragcache(m0, h, frag, mff, + *m0 = m = pf_fragcache(m0, h, &frag, mff, (r->rule_flag & PFRULE_FRAGDROP) ? 1 : 0, &nomem); if (m == NULL) { if (nomem) @@ -937,7 +941,7 @@ goto no_mem; m_tag_prepend(m, mtag); } - if (frag && (frag->fr_flags & PFFRAG_DROP)) + if (frag != NULL && (frag->fr_flags & PFFRAG_DROP)) goto drop; goto fragment_pass; }