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;
}