summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfgsch <fgsch@openbsd.org>2001-04-07 01:06:27 +0000
committerfgsch <fgsch@openbsd.org>2001-04-07 01:06:27 +0000
commitf55892f14787893533e239f9d825060452804588 (patch)
tree88bb1b0f368b7052f208eef7c4cc5931e3e41721
parentImprove grammar. (diff)
downloadwireguard-openbsd-f55892f14787893533e239f9d825060452804588.tar.xz
wireguard-openbsd-f55892f14787893533e239f9d825060452804588.zip
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.
-rw-r--r--sys/netinet/ip_frag.c35
-rw-r--r--sys/netinet/ip_frag.h10
-rw-r--r--sys/netinet/ip_state.c24
3 files changed, 51 insertions, 18 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
diff --git a/sys/netinet/ip_frag.h b/sys/netinet/ip_frag.h
index 352a4601063..f5e13a4fb30 100644
--- a/sys/netinet/ip_frag.h
+++ b/sys/netinet/ip_frag.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_frag.h,v 1.13 2001/01/17 04:47:14 fgsch Exp $ */
+/* $OpenBSD: ip_frag.h,v 1.14 2001/04/07 01:06:28 fgsch Exp $ */
/*
* Copyright (C) 1993-2000 by Darren Reed.
@@ -8,7 +8,7 @@
* to the original author and the contributors.
*
* @(#)ip_frag.h 1.5 3/24/96
- * $IPFilter: ip_frag.h,v 2.4.2.2 2000/11/10 13:10:54 darrenr Exp $
+ * $IPFilter: ip_frag.h,v 2.4.2.3 2001/04/06 12:31:20 darrenr Exp $
*/
#ifndef __IP_FRAG_H__
@@ -26,7 +26,8 @@ typedef struct ipfr {
u_char ipfr_p;
u_char ipfr_tos;
u_short ipfr_off;
- u_short ipfr_ttl;
+ u_char ipfr_ttl;
+ u_char ipfr_seen0;
frentry_t *ipfr_rule;
} ipfr_t;
@@ -42,7 +43,8 @@ typedef struct ipfrstat {
struct ipfr **ifs_nattab;
} ipfrstat_t;
-#define IPFR_CMPSZ (4 + 4 + 2 + 1 + 1)
+#define IPFR_CMPSZ (offsetof(ipfr_t, ipfr_off) - \
+ offsetof(ipfr_t, ipfr_src))
extern int fr_ipfrttl;
extern int fr_frag_lock;
diff --git a/sys/netinet/ip_state.c b/sys/netinet/ip_state.c
index a17feb9c3f5..6a3f5954138 100644
--- a/sys/netinet/ip_state.c
+++ b/sys/netinet/ip_state.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: ip_state.c,v 1.26 2001/01/30 04:23:56 kjell Exp $ */
+/* $OpenBSD: ip_state.c,v 1.27 2001/04/07 01:06:28 fgsch Exp $ */
/*
- * Copyright (C) 1995-2000 by Darren Reed.
+ * Copyright (C) 1995-2001 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -9,7 +9,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$IPFilter: ip_state.c,v 2.30.2.28 2001/01/08 14:04:46 darrenr Exp $";
+static const char rcsid[] = "@(#)$IPFilter: ip_state.c,v 2.30.2.30 2001/04/06 12:31:21 darrenr Exp $";
#endif
#include <sys/errno.h>
@@ -142,7 +142,9 @@ u_long fr_tcpidletimeout = FIVE_DAYS,
fr_tcpclosed = 120,
fr_tcphalfclosed = 2 * 2 * 3600, /* 2 hours */
fr_udptimeout = 240,
- fr_icmptimeout = 120;
+ fr_udpacktimeout = 24,
+ fr_icmptimeout = 120,
+ fr_icmpacktimeout = 12;
int fr_statemax = IPSTATE_MAX,
fr_statesize = IPSTATE_SIZE;
int fr_state_doflush = 0,
@@ -690,7 +692,7 @@ u_int flags;
#endif
RWLOCK_EXIT(&ipf_state);
fin->fin_rev = IP6NEQ(is->is_dst, fin->fin_fi.fi_dst);
- if (fin->fin_fi.fi_fl & FI_FRAG)
+ if ((fin->fin_fi.fi_fl & FI_FRAG) && (pass & FR_KEEPFRAG))
ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE);
return is;
}
@@ -1256,7 +1258,10 @@ fr_info_t *fin;
if ((is->is_p == pr) && (is->is_v == v) &&
fr_matchsrcdst(is, src, dst, fin, NULL) &&
fr_matchicmpqueryreply(v, is, ic)) {
- is->is_age = fr_icmptimeout;
+ if (fin->fin_rev)
+ is->is_age = fr_icmpacktimeout;
+ else
+ is->is_age = fr_icmptimeout;
break;
}
}
@@ -1304,6 +1309,11 @@ retry_tcpudp:
if (!fr_tcpstate(is, fin, ip, tcp)) {
continue;
}
+ } if ((pr == IPPROTO_UDP)) {
+ if (fin->fin_rev)
+ is->is_age = fr_udpacktimeout;
+ else
+ is->is_age = fr_udptimeout;
}
break;
}
@@ -1347,7 +1357,7 @@ retry_tcpudp:
fr_delstate(is);
#endif
RWLOCK_EXIT(&ipf_state);
- if (fin->fin_fi.fi_fl & FI_FRAG)
+ if ((fin->fin_fi.fi_fl & FI_FRAG) && (pass & FR_KEEPFRAG))
ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE);
return fr;
}