diff options
author | 2001-04-07 01:06:27 +0000 | |
---|---|---|
committer | 2001-04-07 01:06:27 +0000 | |
commit | f55892f14787893533e239f9d825060452804588 (patch) | |
tree | 88bb1b0f368b7052f208eef7c4cc5931e3e41721 | |
parent | Improve grammar. (diff) | |
download | wireguard-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.c | 35 | ||||
-rw-r--r-- | sys/netinet/ip_frag.h | 10 | ||||
-rw-r--r-- | sys/netinet/ip_state.c | 24 |
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; } |