Apply by doing: cd /usr/src patch -p0 < 027_ipf-frag.patch And then rebuild your kernel. Index: sys/netinet/ip_frag.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_frag.c,v retrieving revision 1.19 diff -u -r1.19 ip_frag.c --- sys/netinet/ip_frag.c 2000/09/07 19:45:04 1.19 +++ sys/netinet/ip_frag.c 2001/04/23 21:35:14 @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_frag.c,v 1.19 2000/09/07 19:45:04 art Exp $ */ +/* $OpenBSD: ip_frag.c,v 1.19.2.1 2001/04/18 01:02:44 jason Exp $ */ /* * Copyright (C) 1993-1998 by Darren Reed. @@ -141,11 +141,14 @@ ipfr_t *table[]; { ipfr_t **fp, *fra, frag; - u_int idx; + 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; @@ -198,7 +201,10 @@ /* * 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_INC(ipfr_stats.ifs_new); ATOMIC_INC(ipfr_inuse); return fra; @@ -250,6 +256,9 @@ 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). @@ -276,6 +285,19 @@ 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 @@ -288,7 +310,6 @@ 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 Index: sys/netinet/ip_frag.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_frag.h,v retrieving revision 1.12 diff -u -r1.12 ip_frag.h --- sys/netinet/ip_frag.h 2000/03/13 23:40:18 1.12 +++ sys/netinet/ip_frag.h 2001/04/23 21:35:14 @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_frag.h,v 1.12 2000/03/13 23:40:18 kjell Exp $ */ +/* $OpenBSD: ip_frag.h,v 1.12.4.1 2001/04/18 01:02:44 jason Exp $ */ /* * Copyright (C) 1993-1998 by Darren Reed. @@ -25,7 +25,8 @@ 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; @@ -41,7 +42,8 @@ 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 ipfrstat_t *ipfr_fragstats __P((void)); Index: sys/netinet/ip_state.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_state.c,v retrieving revision 1.23 diff -u -r1.23 ip_state.c --- sys/netinet/ip_state.c 2000/08/10 05:50:26 1.23 +++ sys/netinet/ip_state.c 2001/04/23 21:35:15 @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_state.c,v 1.23 2000/08/10 05:50:26 kjell Exp $ */ +/* $OpenBSD: ip_state.c,v 1.23.2.1 2001/04/18 01:02:45 jason Exp $ */ /* * Copyright (C) 1995-1998 by Darren Reed. @@ -429,7 +429,7 @@ #endif RWLOCK_EXIT(&ipf_state); fin->fin_rev = (is->is_dst.s_addr != ip->ip_dst.s_addr); - 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; } @@ -1023,7 +1023,7 @@ 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; }