This is version two of this patch.

To apply:
   cd /usr/src/sys/netinet
   patch -p0 < maxqueue.patch

Recompile your kernel.

Index: in.h
===================================================================
RCS file: /cvs/src/sys/netinet/in.h,v
retrieving revision 1.12
diff -u -r1.12 in.h
--- in.h        1998/02/11 03:58:31     1.12
+++ in.h        1999/02/18 04:33:56
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in.h,v 1.12 1998/02/11 03:58:31 deraadt Exp $ */
+/*     $OpenBSD: in.h,v 1.18 1999/02/17 23:51:12 deraadt Exp $ */
/*     $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */

/*
@@ -325,7 +325,8 @@
#define IPCTL_IPPORT_LASTAUTO  8
#define IPCTL_IPPORT_HIFIRSTAUTO 9
#define IPCTL_IPPORT_HILASTAUTO        10
-#define        IPCTL_MAXID             11
+#define        IPCTL_IPPORT_MAXQUEUE   11
+#define        IPCTL_MAXID             12

#define        IPCTL_NAMES { \
       { 0, 0 }, \
@@ -339,6 +340,7 @@
       { "portlast", CTLTYPE_INT }, \
       { "porthifirst", CTLTYPE_INT }, \
       { "porthilast", CTLTYPE_INT }, \
+       { "maxqueue", CTLTYPE_INT }, \
}

#ifndef _KERNEL
Index: ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.30
diff -u -r1.30 ip_input.c
--- ip_input.c  1998/02/14 18:50:36     1.30
+++ ip_input.c  1999/02/18 04:33:56
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_input.c,v 1.30 1998/02/14 18:50:36 mickey Exp $    */
+/*     $OpenBSD: ip_input.c,v 1.35 1999/02/17 23:51:12 deraadt Exp $   */
/*     $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $   */

/*
@@ -99,6 +99,10 @@
u_char  ipsec_esp_trans_default_level = IPSEC_ESP_TRANS_LEVEL_DEFAULT;
u_char  ipsec_esp_network_default_level = IPSEC_ESP_NETWORK_LEVEL_DEFAULT;

+/* Keep track of memory used for reassembly */
+int    ip_maxqueue = 300;
+int    ip_frags = 0;
+
/* from in_pcb.c */
extern int ipport_firstauto;
extern int ipport_lastauto;
@@ -117,7 +121,6 @@
                         struct mbuf **));
#endif

-
char *
inet_ntoa(ina)
       struct in_addr ina;
@@ -279,10 +282,10 @@
       }

#if defined(IPFILTER) || defined(IPFILTER_LKM)
-       /*
-       * Check if we want to allow this packet to be processed.
-       * Consider it to be bad if not.
-       */
+        /*
+        * Check if we want to allow this packet to be processed.
+        * Consider it to be bad if not.
+        */
       {
               struct mbuf *m0 = m;
               if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0))
@@ -433,12 +436,19 @@
                */
               if (mff || ip->ip_off) {
                       ipstat.ips_fragments++;
+                       if (ip_frags + 1 > ip_maxqueue) {
+                               ip_flush();
+                               ipstat.ips_rcvmemdrop++;
+                               goto bad;
+                       }
+
                       MALLOC(ipqe, struct ipqent *, sizeof (struct ipqent),
                           M_IPQ, M_NOWAIT);
                       if (ipqe == NULL) {
                               ipstat.ips_rcvmemdrop++;
                               goto bad;
                       }
+                       ip_frags++;
                       ipqe->ipqe_mff = mff;
                       ipqe->ipqe_ip = ip;
                       ip = ip_reass(ipqe, fp);
@@ -580,6 +590,7 @@
               m_freem(dtom(q->ipqe_ip));
               LIST_REMOVE(q, ipqe_q);
               FREE(q, M_IPQ);
+               ip_frags--;
       }

insert:
@@ -619,10 +630,12 @@
       m_cat(m, t);
       nq = q->ipqe_q.le_next;
       FREE(q, M_IPQ);
+       ip_frags--;
       for (q = nq; q != NULL; q = nq) {
               t = dtom(q->ipqe_ip);
               nq = q->ipqe_q.le_next;
               FREE(q, M_IPQ);
+               ip_frags--;
               m_cat(m, t);
       }

@@ -652,6 +665,7 @@
       ipstat.ips_fragdropped++;
       m_freem(m);
       FREE(ipqe, M_IPQ);
+       ip_frags--;
       return (0);
}

@@ -670,6 +684,7 @@
               m_freem(dtom(q->ipqe_ip));
               LIST_REMOVE(q, ipqe_q);
               FREE(q, M_IPQ);
+               ip_frags--;
       }
       LIST_REMOVE(fp, ipq_q);
       (void) m_free(dtom(fp));
@@ -710,6 +725,19 @@
}

/*
+ * Flush a bunch of datagram fragments, till we are down to 75%.
+ */
+void
+ip_flush()
+{
+
+       while (ipq.lh_first != NULL && ip_frags > ip_maxqueue * 3 / 4) {
+               ipstat.ips_fragdropped++;
+               ip_freef(ipq.lh_first);
+       }
+}
+
+/*
 * Do option processing on a datagram,
 * possibly discarding it if bad options are encountered,
 * or forwarding it if source-routed.
@@ -973,9 +1001,9 @@
 */
static int
ip_weadvertise(addr)
-        u_int32_t addr;
+       u_int32_t addr;
{
-        register struct rtentry *rt;
+       register struct rtentry *rt;
       register struct ifnet *ifp;
       register struct ifaddr *ifa;
       struct sockaddr_inarp sin;
@@ -990,21 +1018,21 @@

       RTFREE(rt);

-       if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0
-           || rt->rt_gateway->sa_family != AF_LINK)
+       if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
+           rt->rt_gateway->sa_family != AF_LINK)
         return 0;

       for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
-          for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next)
-         {
-               if (ifa->ifa_addr->sa_family != rt->rt_gateway->sa_family)
-                 continue;
-
-               if (!bcmp(LLADDR((struct sockaddr_dl *)ifa->ifa_addr),
-                         LLADDR((struct sockaddr_dl *)rt->rt_gateway),
-                         ETHER_ADDR_LEN))
-                 return 1;
-         }
+               for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
+                   ifa = ifa->ifa_list.tqe_next) {
+                       if (ifa->ifa_addr->sa_family != rt->rt_gateway->sa_family)
+                               continue;
+
+                       if (!bcmp(LLADDR((struct sockaddr_dl *)ifa->ifa_addr),
+                           LLADDR((struct sockaddr_dl *)rt->rt_gateway),
+                           ETHER_ADDR_LEN))
+                               return 1;
+               }

       return 0;
}
@@ -1313,6 +1341,9 @@
       case IPCTL_IPPORT_HILASTAUTO:
               return (sysctl_int(oldp, oldlenp, newp, newlen,
                   &ipport_hilastauto));
+       case IPCTL_IPPORT_MAXQUEUE:
+               return (sysctl_int(oldp, oldlenp, newp, newlen,
+                   &ip_maxqueue));
       default:
               return (EOPNOTSUPP);
       }
Index: ip_var.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_var.h,v
retrieving revision 1.8
diff -u -r1.8 ip_var.h
--- ip_var.h    1998/02/14 18:50:36     1.8
+++ ip_var.h    1999/02/18 04:33:56
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_var.h,v 1.8 1998/02/14 18:50:36 mickey Exp $       */
+/*     $OpenBSD: ip_var.h,v 1.11 1999/02/17 23:51:12 deraadt Exp $     */
/*     $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $     */

/*
@@ -166,6 +166,7 @@
int     ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
int     ip_dooptions __P((struct mbuf *));
void    ip_drain __P((void));
+void    ip_flush __P((void));
void    ip_forward __P((struct mbuf *, int));
void    ip_freef __P((struct ipq *));
void    ip_freemoptions __P((struct ip_moptions *));