summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMike Frantzen <frantzen@cvs.openbsd.org>2003-07-17 16:25:53 +0000
committerMike Frantzen <frantzen@cvs.openbsd.org>2003-07-17 16:25:53 +0000
commit8f60c79e25a21361122abc4f36368f9e59107c36 (patch)
tree23ef35cef47a1f8bec279bcb26bd573be5dee02d /sys
parent697c978c9589b5d256576781d6e84074e4e1abb9 (diff)
fix scrub frag reassembly after the stack's ip_len/ip_off flip correction
ok itojun@ and dhartmei@. heckling from henning@
Diffstat (limited to 'sys')
-rw-r--r--sys/net/pf_norm.c45
1 files changed, 25 insertions, 20 deletions
diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c
index d9418fc2e54..5765cd379d8 100644
--- a/sys/net/pf_norm.c
+++ b/sys/net/pf_norm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_norm.c,v 1.69 2003/07/12 09:33:32 dhartmei Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.70 2003/07/17 16:25:52 frantzen Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -313,6 +313,7 @@ pf_remove_fragment(struct pf_fragment *frag)
}
}
+#define FR_IP_OFF(fr) ((ntohs((fr)->fr_ip->ip_off) & IP_OFFMASK) << 3)
struct mbuf *
pf_reassemble(struct mbuf **m0, struct pf_fragment *frag,
struct pf_frent *frent, int mff)
@@ -322,8 +323,9 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment *frag,
struct pf_frent *frep = NULL;
struct ip *ip = frent->fr_ip;
int hlen = ip->ip_hl << 2;
- u_int16_t off = ntohs(ip->ip_off);
- u_int16_t max = ntohs(ip->ip_len) + off;
+ u_int16_t off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
+ u_int16_t ip_len = ntohs(ip->ip_len) - ip->ip_hl * 4;
+ u_int16_t max = ip_len + off;
KASSERT(frag == NULL || BUFFER_FRAGMENTS(frag));
@@ -363,7 +365,7 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment *frag,
* - off contains the real shifted offset.
*/
LIST_FOREACH(frea, &frag->fr_queue, fr_next) {
- if (ntohs(frea->fr_ip->ip_off) > off)
+ if (FR_IP_OFF(frea) > off)
break;
frep = frea;
}
@@ -371,35 +373,38 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment *frag,
KASSERT(frep != NULL || frea != NULL);
if (frep != NULL &&
- ntohs(frep->fr_ip->ip_off) + ntohs(frep->fr_ip->ip_len) > off)
+ FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl *
+ 4 > off)
{
u_int16_t precut;
- precut = ntohs(frep->fr_ip->ip_off) +
- ntohs(frep->fr_ip->ip_len) - off;
- if (precut >= ntohs(ip->ip_len))
+ precut = FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) -
+ frep->fr_ip->ip_hl * 4 - off;
+ if (precut >= ip_len)
goto drop_fragment;
m_adj(frent->fr_m, precut);
DPFPRINTF(("overlap -%d\n", precut));
/* Enforce 8 byte boundaries */
- ip->ip_off = htons(ntohs(ip->ip_off) + precut);
- off = ntohs(ip->ip_off);
- ip->ip_len = htons(ntohs(ip->ip_len) - precut);
+ ip->ip_off = htons(ntohs(ip->ip_off) + (precut >> 3));
+ off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
+ ip_len -= precut;
+ ip->ip_len = htons(ip_len);
}
- for (; frea != NULL && ntohs(ip->ip_len) + off > ntohs(frea->fr_ip->ip_off);
+ for (; frea != NULL && ip_len + off > FR_IP_OFF(frea);
frea = next)
{
u_int16_t aftercut;
- aftercut = (ntohs(ip->ip_len) + off) - ntohs(frea->fr_ip->ip_off);
+ aftercut = ip_len + off - FR_IP_OFF(frea);
DPFPRINTF(("adjust overlap %d\n", aftercut));
- if (aftercut < ntohs(frea->fr_ip->ip_len))
+ if (aftercut < ntohs(frea->fr_ip->ip_len) - frea->fr_ip->ip_hl
+ * 4)
{
frea->fr_ip->ip_len =
htons(ntohs(frea->fr_ip->ip_len) - aftercut);
- frea->fr_ip->ip_off =
- htons(ntohs(frea->fr_ip->ip_off) + aftercut);
+ frea->fr_ip->ip_off = htons(ntohs(frea->fr_ip->ip_off) +
+ (aftercut >> 3));
m_adj(frea->fr_m, aftercut);
break;
}
@@ -434,12 +439,12 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment *frag,
for (frep = LIST_FIRST(&frag->fr_queue); frep; frep = next) {
next = LIST_NEXT(frep, fr_next);
- off += ntohs(frep->fr_ip->ip_len);
+ off += ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl * 4;
if (off < frag->fr_max &&
- (next == NULL || ntohs(next->fr_ip->ip_off) != off))
+ (next == NULL || FR_IP_OFF(next) != off))
{
DPFPRINTF(("missing fragment at %d, next %d, max %d\n",
- off, next == NULL ? -1 : ntohs(next->fr_ip->ip_off),
+ off, next == NULL ? -1 : FR_IP_OFF(next),
frag->fr_max));
return (NULL);
}
@@ -863,7 +868,7 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
}
ip_len = ntohs(h->ip_len) - hlen;
- ip_off = ntohs(h->ip_off) << 3;
+ ip_off = (ntohs(h->ip_off) & IP_OFFMASK) << 3;
/* All fragments are 8 byte aligned */
if (mff && (ip_len & 0x7)) {