summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_frag.c
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>2001-04-07 01:06:29 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>2001-04-07 01:06:29 +0000
commit09589279a774f40eebc1453c937f2bee169e6d14 (patch)
treecf3c67b966633119b84290eca52d6e5fd8b6efa7 /sys/netinet/ip_frag.c
parente018dc20c3eb4f628f1f3c1607473966a4a9dc4e (diff)
Partial update to IPF 3.4.17; this fixes the *VERY* serious fragment
caching bug recently discussed in the ipfilter list. People using IPF is urged to sync with these changes.
Diffstat (limited to 'sys/netinet/ip_frag.c')
-rw-r--r--sys/netinet/ip_frag.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/sys/netinet/ip_frag.c b/sys/netinet/ip_frag.c
index 37af2b1de4c..e86ad0175cd 100644
--- a/sys/netinet/ip_frag.c
+++ b/sys/netinet/ip_frag.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_frag.c,v 1.21 2001/01/30 04:23:56 kjell Exp $ */
+/* $OpenBSD: ip_frag.c,v 1.22 2001/04/07 01:06:27 fgsch Exp $ */
/*
* Copyright (C) 1993-2000 by Darren Reed.
@@ -9,7 +9,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$IPFilter: ip_frag.c,v 2.10.2.7 2000/11/27 10:26:56 darrenr Exp $";
+static const char rcsid[] = "@(#)$IPFilter: ip_frag.c,v 2.10.2.8 2001/04/06 12:31:20 darrenr Exp $";
#endif
#if defined(KERNEL) && !defined(_KERNEL)
@@ -83,7 +83,7 @@ static const char rcsid[] = "@(#)$IPFilter: ip_frag.c,v 2.10.2.7 2000/11/27 10:2
# ifndef IPFILTER_LKM
# include <sys/libkern.h>
# include <sys/systm.h>
-# endif
+# endif
extern struct callout_handle ipfr_slowtimer_ch;
# endif
#endif
@@ -146,12 +146,15 @@ fr_info_t *fin;
u_int pass;
ipfr_t *table[];
{
- ipfr_t **fp, *fra, frag;
- u_int idx;
+ ipfr_t **fp, *fra, frag;
+ u_int idx, off;
if (ipfr_inuse >= IPFT_SIZE)
return NULL;
+ if (!(fin->fin_fi.fi_fl & FI_FRAG))
+ return NULL;
+
frag.ipfr_p = ip->ip_p;
idx = ip->ip_p;
frag.ipfr_id = ip->ip_id;
@@ -205,7 +208,10 @@ ipfr_t *table[];
/*
* Compute the offset of the expected start of the next packet.
*/
- fra->ipfr_off = (ip->ip_off & IP_OFFMASK) + (fin->fin_dlen >> 3);
+ off = ip->ip_off & IP_OFFMASK;
+ if (!off)
+ fra->ipfr_seen0 = 1;
+ fra->ipfr_off = off + (fin->fin_dlen >> 3);
ATOMIC_INCL(ipfr_stats.ifs_new);
ATOMIC_INC32(ipfr_inuse);
return fra;
@@ -261,6 +267,9 @@ ipfr_t *table[];
ipfr_t *f, frag;
u_int idx;
+ if (!(fin->fin_fi.fi_fl & FI_FRAG))
+ return NULL;
+
/*
* For fragments, we record protocol, packet id, TOS and both IP#'s
* (these should all be the same for all fragments of a packet).
@@ -288,6 +297,19 @@ ipfr_t *table[];
IPFR_CMPSZ)) {
u_short atoff, off;
+ /*
+ * XXX - We really need to be guarding against the
+ * retransmission of (src,dst,id,offset-range) here
+ * because a fragmented packet is never resent with
+ * the same IP ID#.
+ */
+ off = ip->ip_off & IP_OFFMASK;
+ if (f->ipfr_seen0) {
+ if (!off || (fin->fin_fi.fi_fl & FI_SHORT))
+ continue;
+ } else if (!off)
+ f->ipfr_seen0 = 1;
+
if (f != table[idx]) {
/*
* move fragment info. to the top of the list
@@ -300,7 +322,6 @@ ipfr_t *table[];
f->ipfr_prev = NULL;
table[idx] = f;
}
- off = ip->ip_off & IP_OFFMASK;
atoff = off + (fin->fin_dlen >> 3);
/*
* If we've follwed the fragments, and this is the