Index: FreeBSD/sys/netinet/tcp_reass.c =================================================================== --- FreeBSD/sys/netinet/tcp_reass.c +++ FreeBSD/sys/netinet/tcp_reass.c @@ -164,6 +164,10 @@ if (th == NULL) goto present; + KASSERT(SEQ_GEQ(th->th_seq, tp->rcv_nxt), + ("Attempt to add old entry to reassembly queue (th=%p, tp=%p)", + th, tp)); + /* * Limit the number of segments that can be queued to reduce the * potential for mbuf exhaustion. For best performance, we want to be @@ -245,10 +249,11 @@ int i; /* conversion to int (in i) handles seq wraparound */ i = p->tqe_th->th_seq + p->tqe_len - th->th_seq; - if (i > 0) { + if (i >= 0) { if (i >= *tlenp) { TCPSTAT_INC(tcps_rcvduppack); TCPSTAT_ADD(tcps_rcvdupbyte, *tlenp); + p->tqe_th->th_flags |= (th->th_seq & TH_FIN); m_freem(m); if (te != &tqs) uma_zfree(tcp_reass_zone, te); @@ -261,9 +266,11 @@ */ goto present; /* ??? */ } - m_adj(m, i); - *tlenp -= i; - th->th_seq += i; + if (i > 0) { + m_adj(m, i); + *tlenp -= i; + th->th_seq += i; + } } } tp->t_rcvoopack++; @@ -303,7 +310,10 @@ } else { KASSERT(te != &tqs, ("%s: temporary stack based entry not " "first element in queue", __func__)); - LIST_INSERT_AFTER(p, te, tqe_q); + if (te == &tqs) + tp->t_segqlen--; + else + LIST_INSERT_AFTER(p, te, tqe_q); } present: @@ -314,6 +324,8 @@ if (!TCPS_HAVEESTABLISHED(tp->t_state)) return (0); q = LIST_FIRST(&tp->t_segq); + KASSERT(q == NULL || SEQ_GEQ(q->tqe_th->th_seq, tp->rcv_nxt), + ("Reassembly queue for %p has stale entry at head", tp)); if (!q || q->tqe_th->th_seq != tp->rcv_nxt) return (0); SOCKBUF_LOCK(&so->so_rcv);