Apply by doing:
        cd /usr/src
        patch -p0 < 018_tcp.patch

Rebuild your kernel.

Update headers.
        make includes

Then rebuild and install sysctl:
        cd sbin/sysctl
        make depend
        make
        make install

Index: sys/netinet/tcp_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_input.c,v
retrieving revision 1.125
retrieving revision 1.125.2.2
diff -u -p -r1.125 -r1.125.2.2
--- sys/netinet/tcp_input.c	14 Feb 2003 17:54:46 -0000	1.125
+++ sys/netinet/tcp_input.c	3 Mar 2004 08:40:07 -0000	1.125.2.2
@@ -204,11 +204,23 @@ tcp_reass(tp, th, m, tlen)
 	 * Allocate a new queue entry, before we throw away any data.
 	 * If we can't, just drop the packet.  XXX
 	 */
-	tiqe =  pool_get(&ipqent_pool, PR_NOWAIT);
+	tiqe = pool_get(&tcpqe_pool, PR_NOWAIT);
 	if (tiqe == NULL) {
-		tcpstat.tcps_rcvmemdrop++;
-		m_freem(m);
-		return (0);
+		tiqe = LIST_FIRST(&tp->segq);
+		if (tiqe != NULL && th->th_seq == tp->rcv_nxt) {
+			/* Reuse last entry since new segment fills a hole */
+			while ((p = LIST_NEXT(tiqe, ipqe_q)) != NULL)
+				tiqe = p;
+			m_freem(tiqe->ipqe_m);
+			LIST_REMOVE(tiqe, ipqe_q);
+		}
+		if (tiqe == NULL || th->th_seq != tp->rcv_nxt) {
+			/* Flush fragments for this connection */
+			tcp_freeq(tp);
+			tcpstat.tcps_rcvmemdrop++;
+			m_freem(m);
+			return (0);
+		}
 	}
 
 	/*
@@ -235,7 +247,7 @@ tcp_reass(tp, th, m, tlen)
 				tcpstat.tcps_rcvduppack++;
 				tcpstat.tcps_rcvdupbyte += *tlen;
 				m_freem(m);
-				pool_put(&ipqent_pool, tiqe);
+				pool_put(&tcpqe_pool, tiqe);
 				return (0);
 			}
 			m_adj(m, i);
@@ -265,7 +277,7 @@ tcp_reass(tp, th, m, tlen)
 		nq = q->ipqe_q.le_next;
 		m_freem(q->ipqe_m);
 		LIST_REMOVE(q, ipqe_q);
-		pool_put(&ipqent_pool, q);
+		pool_put(&tcpqe_pool, q);
 	}
 
 	/* Insert the new fragment queue entry into place. */
@@ -301,7 +313,7 @@ present:
 			m_freem(q->ipqe_m);
 		else
 			sbappendstream(&so->so_rcv, q->ipqe_m);
-		pool_put(&ipqent_pool, q);
+		pool_put(&tcpqe_pool, q);
 		q = nq;
 	} while (q != NULL && q->ipqe_tcp->th_seq == tp->rcv_nxt);
 	sorwakeup(so);
@@ -1388,8 +1400,10 @@ findpcb:
 				tp->snd_scale = tp->requested_s_scale;
 				tp->rcv_scale = tp->request_r_scale;
 			}
+			tcp_reass_lock(tp);
 			(void) tcp_reass(tp, (struct tcphdr *)0,
 				(struct mbuf *)0, &tlen);
+			tcp_reass_unlock(tp);
 			/*
 			 * if we didn't have to retransmit the SYN,
 			 * use its rtt as our initial srtt & rtt var.
@@ -1648,8 +1662,10 @@ trimthenstep6:
 			tp->snd_scale = tp->requested_s_scale;
 			tp->rcv_scale = tp->request_r_scale;
 		}
+		tcp_reass_lock(tp);
 		(void) tcp_reass(tp, (struct tcphdr *)0, (struct mbuf *)0,
 				 &tlen);
+		tcp_reass_unlock(tp);
 		tp->snd_wl1 = th->th_seq - 1;
 		/* fall into ... */
 
@@ -2152,8 +2168,10 @@ dodata:							/* XXX */
 	 */
 	if ((tlen || (tiflags & TH_FIN)) &&
 	    TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+		tcp_reass_lock(tp);
 		if (th->th_seq == tp->rcv_nxt && tp->segq.lh_first == NULL &&
 		    tp->t_state == TCPS_ESTABLISHED) {
+			tcp_reass_unlock(tp);
 			TCP_SETUP_ACK(tp, tiflags);
 			tp->rcv_nxt += tlen;
 			tiflags = th->th_flags & TH_FIN;
@@ -2170,6 +2188,7 @@ dodata:							/* XXX */
 		} else {
 			m_adj(m, hdroptlen);
 			tiflags = tcp_reass(tp, th, m, &tlen);
+			tcp_reass_unlock(tp);
 			tp->t_flags |= TF_ACKNOW;
 		}
 #ifdef TCP_SACK
Index: sys/netinet/tcp_subr.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.65
retrieving revision 1.65.4.2
diff -u -p -r1.65 -r1.65.4.2
--- sys/netinet/tcp_subr.c	28 Aug 2002 15:43:03 -0000	1.65
+++ sys/netinet/tcp_subr.c	3 Mar 2004 08:40:07 -0000	1.65.4.2
@@ -141,17 +141,18 @@ int	tcp_do_ecn = 0;		/* RFC3168 ECN enab
 #endif
 int	tcbhashsize = TCBHASHSIZE;
 
+int tcp_reass_limit = NMBCLUSTERS / 2; /* hardlimit for tcpqe_pool */
+
 #ifdef INET6
 extern int ip6_defhlim;
 #endif /* INET6 */
 
 struct pool tcpcb_pool;
+struct pool tcpqe_pool;
 #ifdef TCP_SACK
 struct pool sackhl_pool;
 #endif
 
-int	tcp_freeq(struct tcpcb *);
-
 struct tcpstat tcpstat;		/* tcp statistics */
 
 /*
@@ -165,6 +166,9 @@ tcp_init()
 #endif /* TCP_COMPAT_42 */
 	pool_init(&tcpcb_pool, sizeof(struct tcpcb), 0, 0, 0, "tcpcbpl",
 	    NULL);
+	pool_init(&tcpqe_pool, sizeof(struct ipqent), 0, 0, 0, "tcpqepl",
+	    NULL);
+	pool_sethardlimit(&tcpqe_pool, tcp_reass_limit, NULL, 0);
 #ifdef TCP_SACK
 	pool_init(&sackhl_pool, sizeof(struct sackhole), 0, 0, 0, "sackhlpl",
 	    NULL);
@@ -670,7 +674,9 @@ tcp_close(struct tcpcb *tp)
 #endif /* RTV_RTT */
 
 	/* free the reassembly queue, if any */
+	tcp_reass_lock(tp);
 	tcp_freeq(tp);
+	tcp_reass_unlock(tp);
 
 	tcp_canceltimers(tp);
 	TCP_CLEAR_DELACK(tp);
@@ -703,7 +709,7 @@ tcp_freeq(struct tcpcb *tp)
 	while ((qe = LIST_FIRST(&tp->segq)) != NULL) {
 		LIST_REMOVE(qe, ipqe_q);
 		m_freem(qe->ipqe_m);
-		pool_put(&ipqent_pool, qe);
+		pool_put(&tcpqe_pool, qe);
 		rv = 1;
 	}
 	return (rv);
@@ -712,7 +718,20 @@ tcp_freeq(struct tcpcb *tp)
 void
 tcp_drain()
 {
-
+	struct inpcb *inp;
+ 
+	/* called at splimp() */
+	CIRCLEQ_FOREACH(inp, &tcbtable.inpt_queue, inp_queue) {
+		struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;
+
+		if (tp != NULL) {
+			if (tcp_reass_lock_try(tp) == 0)
+				continue;
+			if (tcp_freeq(tp))
+				tcpstat.tcps_conndrained++;
+			tcp_reass_unlock(tp);
+		}
+	}
 }
 
 /*
Index: sys/netinet/tcp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.68
retrieving revision 1.68.2.1
diff -u -p -r1.68 -r1.68.2.1
--- sys/netinet/tcp_usrreq.c	12 Feb 2003 14:41:08 -0000	1.68
+++ sys/netinet/tcp_usrreq.c	3 Mar 2004 08:40:07 -0000	1.68.2.1
@@ -877,6 +877,7 @@ tcp_sysctl(name, namelen, oldp, oldlenp,
 	void *newp;
 	size_t newlen;
 {
+	int error, nval;
 
 	/* All sysctl names at this level are terminal. */
 	if (namelen != 1)
@@ -931,6 +932,18 @@ tcp_sysctl(name, namelen, oldp, oldlenp,
 		return (sysctl_int(oldp, oldlenp, newp, newlen,
 		   &tcp_do_ecn));
 #endif
+	case TCPCTL_REASS_LIMIT:
+		nval = tcp_reass_limit;
+		error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
+		if (error)
+			return (error);
+		if (nval != tcp_reass_limit) {
+			error = pool_sethardlimit(&tcpqe_pool, nval, NULL, 0);
+			if (error)
+				return (error);
+			tcp_reass_limit = nval;
+		}
+		return (0);
 	default:
 		return (ENOPROTOOPT);
 	}
Index: sys/netinet/tcp_var.h
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_var.h,v
retrieving revision 1.45
retrieving revision 1.45.2.3
diff -u -p -r1.45 -r1.45.2.3
--- sys/netinet/tcp_var.h	12 Feb 2003 14:41:08 -0000	1.45
+++ sys/netinet/tcp_var.h	4 Mar 2004 03:35:15 -0000	1.45.2.3
@@ -86,6 +86,7 @@ struct tcpcb {
 #define TF_SEND_CWR	0x00020000	/* send CWR in next seg */
 #define TF_DISABLE_ECN	0x00040000	/* disable ECN for this connection */
 #endif
+#define TF_REASSLOCK	0x00080000	/* reassembling or draining */
 
 	struct	mbuf *t_template;	/* skeletal packet for transmit */
 	struct	inpcb *t_inpcb;		/* back pointer to internet pcb */
@@ -209,6 +210,35 @@ do {									\
 		timeout_del(&(tp)->t_delack_to);			\
 	}								\
 } while (/*CONSTCOND*/0)
+
+static __inline int tcp_reass_lock_try(struct tcpcb *);
+static __inline void tcp_reass_unlock(struct tcpcb *);
+#define tcp_reass_lock(tp) tcp_reass_lock_try(tp)
+
+static __inline int
+tcp_reass_lock_try(struct tcpcb *tp)
+{
+	int s;
+
+	s = splimp();
+	if (tp->t_flags & TF_REASSLOCK) {
+		splx(s);
+		return (0);
+	}
+	tp->t_flags |= TF_REASSLOCK;
+	splx(s);
+	return (1);
+}
+
+static __inline void
+tcp_reass_unlock(struct tcpcb *tp)
+{
+	int s;
+
+	s = splimp();
+	tp->t_flags &= ~TF_REASSLOCK;
+	splx(s);
+}
 #endif /* _KERNEL */
 
 /*
@@ -323,6 +353,8 @@ struct	tcpstat {
 	u_int32_t tcps_cwr_ecn;		/* # of cwnd reduced by ecn */
 	u_int32_t tcps_cwr_frecovery;	/* # of cwnd reduced by fastrecovery */
 	u_int32_t tcps_cwr_timeout;	/* # of cwnd reduced by timeout */
+
+	u_int64_t tcps_conndrained;	/* # of connections drained */
 };
 
 /*
@@ -343,7 +375,8 @@ struct	tcpstat {
 #define	TCPCTL_RSTPPSLIMIT     12 /* RST pps limit */
 #define	TCPCTL_ACK_ON_PUSH     13 /* ACK immediately on PUSH */
 #define	TCPCTL_ECN	       14 /* RFC3168 ECN */
-#define	TCPCTL_MAXID	       15
+#define	TCPCTL_REASS_LIMIT     15 /* max entries for tcp reass queues */
+#define	TCPCTL_MAXID	       16
 
 #define	TCPCTL_NAMES { \
 	{ 0, 0 }, \
@@ -361,6 +394,7 @@ struct	tcpstat {
 	{ "rstppslimit",	CTLTYPE_INT }, \
 	{ "ackonpush",	CTLTYPE_INT }, \
 	{ "ecn", 	CTLTYPE_INT }, \
+	{ "reasslimit",	CTLTYPE_INT }, \
 }
 
 struct tcp_ident_mapping {
@@ -381,10 +415,14 @@ extern	struct pool sackhl_pool;
 #endif
 extern	int tcp_do_ecn;		/* RFC3168 ECN enabled/disabled? */
 
+extern	struct pool tcpqe_pool;
+extern	int tcp_reass_limit;	/* max entries for tcp reass queues */
+
 int	 tcp_attach(struct socket *);
 void	 tcp_canceltimers(struct tcpcb *);
 struct tcpcb *
 	 tcp_close(struct tcpcb *);
+int	 tcp_freeq(struct tcpcb *);
 #if defined(INET6) && !defined(TCP6)
 void	 tcp6_ctlinput(int, struct sockaddr *, void *);
 #endif
