This patch is provided to fix a couple of deployment issues observed

in the field. In one situation, one end of the TCP connection sends
a back-to-back RST packet, with delayed ack, the last_ack_sent variable
has not been update yet. When tcp_insecure_rst is turned off, the code
treats the RST as invalid because last_ack_sent instead of rcv_nxt is
compared against th_seq. Apparently there is some kind of firewall that
sits in between the two ends and that RST packet is the only RST
packet received. With short lived HTTP connections, the symptom is
a large accumulation of connections over a short period of time .

The +/-(1) factor is to take care of implementations out there that
generate RST packets with these types of sequence numbers. This
behavior has also been observed in live environments.

Reviewed by:	silby, Mike Karels
MFC after:	1 week
This commit is contained in:
qingli 2007-03-07 23:21:59 +00:00
parent b533eb28f1
commit fb4a7a64bd
2 changed files with 14 additions and 10 deletions

View File

@ -1655,9 +1655,8 @@ tcp_input(m, off0)
* RFC 1337.
*/
if (thflags & TH_RST) {
if ((SEQ_GEQ(th->th_seq, tp->last_ack_sent) &&
SEQ_LT(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) ||
(tp->rcv_wnd == 0 && tp->last_ack_sent == th->th_seq)) {
if (SEQ_GEQ(th->th_seq, tp->last_ack_sent - 1) &&
SEQ_LEQ(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) {
switch (tp->t_state) {
case TCPS_SYN_RECEIVED:
@ -1665,8 +1664,11 @@ tcp_input(m, off0)
goto close;
case TCPS_ESTABLISHED:
if (tp->last_ack_sent != th->th_seq &&
tcp_insecure_rst == 0) {
if (tcp_insecure_rst == 0 &&
!(SEQ_GEQ(th->th_seq, tp->rcv_nxt - 1) &&
SEQ_LEQ(th->th_seq, tp->rcv_nxt + 1)) &&
!(SEQ_GEQ(th->th_seq, tp->last_ack_sent - 1) &&
SEQ_LEQ(th->th_seq, tp->last_ack_sent + 1))) {
tcpstat.tcps_badrst++;
goto drop;
}

View File

@ -1655,9 +1655,8 @@ tcp_input(m, off0)
* RFC 1337.
*/
if (thflags & TH_RST) {
if ((SEQ_GEQ(th->th_seq, tp->last_ack_sent) &&
SEQ_LT(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) ||
(tp->rcv_wnd == 0 && tp->last_ack_sent == th->th_seq)) {
if (SEQ_GEQ(th->th_seq, tp->last_ack_sent - 1) &&
SEQ_LEQ(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) {
switch (tp->t_state) {
case TCPS_SYN_RECEIVED:
@ -1665,8 +1664,11 @@ tcp_input(m, off0)
goto close;
case TCPS_ESTABLISHED:
if (tp->last_ack_sent != th->th_seq &&
tcp_insecure_rst == 0) {
if (tcp_insecure_rst == 0 &&
!(SEQ_GEQ(th->th_seq, tp->rcv_nxt - 1) &&
SEQ_LEQ(th->th_seq, tp->rcv_nxt + 1)) &&
!(SEQ_GEQ(th->th_seq, tp->last_ack_sent - 1) &&
SEQ_LEQ(th->th_seq, tp->last_ack_sent + 1))) {
tcpstat.tcps_badrst++;
goto drop;
}