The problem was reported around Aug 28. -current was fixed Aug 29 with pf_norm.c 1.75, which is included in 3.4-release.
Backported patches against 3.3-stable and 3.2-stable were sent out shortly after, but required testing. They were commited to their respective branches Sep 24. I'm not allowed to commit to -stable, I don't know the precise rules of what gets listed on errata.html or even sent to security-announce. I supply the patches and, when I'm told they require an errata entry, a description. When, after that, things don't get commited, I send out a reminder or two, but I'm not managing processes. So, here's the description: Three cases of potential access to freed memory have been found in pf. At least one of them could be used to panic pf with active scrub rules remotely. The patches are attached. Daniel
Index: pf_norm.c
===================================================================
RCS file: /cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.55
diff -u -r1.55 pf_norm.c
--- pf_norm.c 18 Feb 2003 08:05:15 -0000 1.55
+++ pf_norm.c 29 Aug 2003 09:36:55 -0000
@@ -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;
}
Index: pf_norm.c
===================================================================
RCS file: /cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.35
diff -u -r1.35 pf_norm.c
--- pf_norm.c 28 Jun 2002 00:08:23 -0000 1.35
+++ pf_norm.c 29 Aug 2003 02:35:46 -0000
@@ -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 *);
@@ -324,7 +324,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;
@@ -335,33 +335,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;
@@ -372,7 +372,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;
@@ -419,45 +419,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);
@@ -479,11 +480,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;
@@ -511,7 +513,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;
@@ -521,41 +523,41 @@
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);
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));
@@ -567,7 +569,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;
@@ -752,21 +754,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);
@@ -775,8 +778,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);
@@ -784,15 +787,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);
@@ -897,12 +900,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 *);
@@ -931,7 +934,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)
@@ -946,7 +949,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;
}
pgp00000.pgp
Description: PGP signature
