fix input window test again (accept acks from FINS at left edge and responses
to keepalives, but dropafterack otherwise; also fixes Phil Karn's problem
with failure to respond to new SYN to left of window); can't use tcp_drop
after RST, or we'll send RST in response
SCCS-vsn: sys/netinet/tcp_input.c 7.17
SCCS-vsn: sys/netinet/tcp_timer.c 7.12
SCCS-vsn: sys/netinet/tcp_timer.h 7.5
SCCS-vsn: sys/netinet/tcp_usrreq.c 7.8
- * Copyright (c) 1982, 1986 Regents of the University of California.
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*
- * @(#)tcp_input.c 7.16 (Berkeley) %G%
+ * @(#)tcp_input.c 7.17 (Berkeley) %G%
* Reset idle time and keep-alive timer.
*/
tp->t_idle = 0;
* Reset idle time and keep-alive timer.
*/
tp->t_idle = 0;
- tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
+ tp->t_timer[TCPT_KEEP] = tcp_keepidle;
/*
* Process options if not in LISTEN state,
/*
* Process options if not in LISTEN state,
tcp_rcvseqinit(tp);
tp->t_flags |= TF_ACKNOW;
tp->t_state = TCPS_SYN_RECEIVED;
tcp_rcvseqinit(tp);
tp->t_flags |= TF_ACKNOW;
tp->t_state = TCPS_SYN_RECEIVED;
- tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
+ tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
dropsocket = 0; /* committed to socket */
tcpstat.tcps_accepts++;
goto trimthenstep6;
dropsocket = 0; /* committed to socket */
tcpstat.tcps_accepts++;
goto trimthenstep6;
}
if (todrop > ti->ti_len ||
todrop == ti->ti_len && (tiflags&TH_FIN) == 0) {
}
if (todrop > ti->ti_len ||
todrop == ti->ti_len && (tiflags&TH_FIN) == 0) {
+ tcpstat.tcps_rcvduppack++;
+ tcpstat.tcps_rcvdupbyte += ti->ti_len;
- * Don't toss RST in response to 4.2-style keepalive.
+ * If segment is just one to the left of the window,
+ * check two special cases:
+ * 1. Don't toss RST in response to 4.2-style keepalive.
+ * 2. If the only thing to drop is a FIN, we can drop
+ * it, but check the ACK or we will get into FIN
+ * wars if our FINs crossed (both CLOSING).
+ * In either case, send ACK to resynchronize,
+ * but keep on processing for RST or ACK.
- if (ti->ti_seq == tp->rcv_nxt - 1 && tiflags & TH_RST)
- goto do_rst;
+ if ((tiflags & TH_FIN && todrop == ti->ti_len + 1)
+#ifdef TCP_COMPAT_42
+ || (tiflags & TH_RST && ti->ti_seq == tp->rcv_nxt - 1)
- tcpstat.tcps_rcvduppack++;
- tcpstat.tcps_rcvdupbyte += ti->ti_len;
- todrop = ti->ti_len;
- tiflags &= ~TH_FIN;
- tp->t_flags |= TF_ACKNOW;
+ ) {
+ todrop = ti->ti_len;
+ tiflags &= ~TH_FIN;
+ tp->t_flags |= TF_ACKNOW;
+ } else
+ goto dropafterack;
} else {
tcpstat.tcps_rcvpartduppack++;
tcpstat.tcps_rcvpartdupbyte += todrop;
} else {
tcpstat.tcps_rcvpartduppack++;
tcpstat.tcps_rcvpartdupbyte += todrop;
- * If new data is received on a connection after the
+ * If new data are received on a connection after the
* user processes are gone, then RST the other end.
*/
if ((so->so_state & SS_NOFDREF) &&
* user processes are gone, then RST the other end.
*/
if ((so->so_state & SS_NOFDREF) &&
tiflags &= ~(TH_PUSH|TH_FIN);
}
tiflags &= ~(TH_PUSH|TH_FIN);
}
-#ifdef TCP_COMPAT_42
-do_rst:
-#endif
/*
* If the RST bit is set examine the state:
* SYN_RECEIVED STATE:
/*
* If the RST bit is set examine the state:
* SYN_RECEIVED STATE:
if (tiflags&TH_RST) switch (tp->t_state) {
case TCPS_SYN_RECEIVED:
if (tiflags&TH_RST) switch (tp->t_state) {
case TCPS_SYN_RECEIVED:
- tp = tcp_drop(tp, ECONNREFUSED);
- goto drop;
+ so->so_error = ECONNREFUSED;
+ goto close;
case TCPS_ESTABLISHED:
case TCPS_FIN_WAIT_1:
case TCPS_FIN_WAIT_2:
case TCPS_CLOSE_WAIT:
case TCPS_ESTABLISHED:
case TCPS_FIN_WAIT_1:
case TCPS_FIN_WAIT_2:
case TCPS_CLOSE_WAIT:
- tp = tcp_drop(tp, ECONNRESET);
+ so->so_error = ECONNRESET;
+ close:
+ tp->t_state = TCPS_CLOSED;
+ tcpstat.tcps_drops++;
+ tp = tcp_close(tp);
goto drop;
case TCPS_CLOSING:
goto drop;
case TCPS_CLOSING:
* (srtt = rtt/8 + srtt*7/8 in fixed point).
* Adjust t_rtt to origin 0.
*/
* (srtt = rtt/8 + srtt*7/8 in fixed point).
* Adjust t_rtt to origin 0.
*/
- tp->t_rtt--;
- delta = tp->t_rtt - (tp->t_srtt >> 3);
+ delta = tp->t_rtt - 1 - (tp->t_srtt >> 3);
if ((tp->t_srtt += delta) <= 0)
tp->t_srtt = 1;
/*
if ((tp->t_srtt += delta) <= 0)
tp->t_srtt = 1;
/*
*/
if (so->so_state & SS_CANTRCVMORE) {
soisdisconnected(so);
*/
if (so->so_state & SS_CANTRCVMORE) {
soisdisconnected(so);
- tp->t_timer[TCPT_2MSL] = TCPTV_MAXIDLE;
+ tp->t_timer[TCPT_2MSL] = tcp_maxidle;
}
tp->t_state = TCPS_FIN_WAIT_2;
}
}
tp->t_state = TCPS_FIN_WAIT_2;
}
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*
- * @(#)tcp_timer.c 7.11.1.1 (Berkeley) %G%
+ * @(#)tcp_timer.c 7.12 (Berkeley) %G%
#include "tcpip.h"
int tcpnodelack = 0;
#include "tcpip.h"
int tcpnodelack = 0;
+int tcp_keepidle = TCPTV_KEEP_IDLE;
+int tcp_keepintvl = TCPTV_KEEPINTVL;
+int tcp_maxidle;
/*
* Fast timeout routine for processing delayed acks
*/
/*
* Fast timeout routine for processing delayed acks
*/
int s = splnet();
register int i;
int s = splnet();
register int i;
+ tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
/*
* Search through tcb's and update active timers.
*/
/*
* Search through tcb's and update active timers.
*/
*/
case TCPT_2MSL:
if (tp->t_state != TCPS_TIME_WAIT &&
*/
case TCPT_2MSL:
if (tp->t_state != TCPS_TIME_WAIT &&
- tp->t_idle <= TCPTV_MAXIDLE)
- tp->t_timer[TCPT_2MSL] = TCPTV_KEEP;
+ tp->t_idle <= tcp_maxidle)
+ tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
else
tp = tcp_close(tp);
break;
else
tp = tcp_close(tp);
break;
goto dropit;
if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE &&
tp->t_state <= TCPS_CLOSE_WAIT) {
goto dropit;
if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE &&
tp->t_state <= TCPS_CLOSE_WAIT) {
- if (tp->t_idle >= TCPTV_MAXIDLE)
+ if (tp->t_idle >= tcp_keepidle + tcp_maxidle)
goto dropit;
/*
* Send a packet designed to force a response
goto dropit;
/*
* Send a packet designed to force a response
tcp_respond(tp, tp->t_template,
tp->rcv_nxt, tp->snd_una - 1, 0);
#endif
tcp_respond(tp, tp->t_template,
tp->rcv_nxt, tp->snd_una - 1, 0);
#endif
- }
- tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
+ tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
+ } else
+ tp->t_timer[TCPT_KEEP] = tcp_keepidle;
break;
dropit:
tcpstat.tcps_keepdrops++;
break;
dropit:
tcpstat.tcps_keepdrops++;
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*
- * @(#)tcp_timer.h 7.4 (Berkeley) %G%
+ * @(#)tcp_timer.h 7.5 (Berkeley) %G%
* a window update from the peer.
*
* The TCPT_KEEP timer is used to keep connections alive. If an
* a window update from the peer.
*
* The TCPT_KEEP timer is used to keep connections alive. If an
- * connection is idle (no segments received) for TCPTV_KEEP amount of time,
- * but not yet established, then we drop the connection. If the connection
- * is established, then we force the peer to send us a segment by sending:
+ * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time,
+ * but not yet established, then we drop the connection. Once the connection
+ * is established, if the connection is idle for TCPTV_KEEP_IDLE time
+ * (and keepalives have been enabled on the socket), we begin to probe
+ * the connection. We force the peer to send us a segment by sending:
* <SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK>
* This segment is (deliberately) outside the window, and should elicit
* an ack segment in response from the peer. If, despite the TCPT_KEEP
* initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE
* <SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK>
* This segment is (deliberately) outside the window, and should elicit
* an ack segment in response from the peer. If, despite the TCPT_KEEP
* initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE
- * amount of time, then we drop the connection.
+ * amount of time probing, then we drop the connection.
*/
#define TCP_TTL 30 /* default time to live for TCP segs */
*/
#define TCP_TTL 30 /* default time to live for TCP segs */
-int tcp_ttl; /* time to live for TCP segs */
-#define TCPTV_MSL ( 15*PR_SLOWHZ) /* max seg lifetime */
+#define TCPTV_MSL ( 30*PR_SLOWHZ) /* max seg lifetime (hah!) */
#define TCPTV_SRTTBASE 0 /* base roundtrip time;
if 0, no idea yet */
#define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */
#define TCPTV_SRTTBASE 0 /* base roundtrip time;
if 0, no idea yet */
#define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */
#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistance */
#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */
#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistance */
#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */
-#define TCPTV_KEEP ( 75*PR_SLOWHZ) /* keep alive - 75 secs */
-#define TCPTV_MAXIDLE ( 8*TCPTV_KEEP) /* maximum allowable idle
- time before drop conn */
+#define TCPTV_KEEP_INIT ( 75*PR_SLOWHZ) /* initial connect keep alive */
+#define TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ) /* dflt time before probing */
+#define TCPTV_KEEPINTVL ( 75*PR_SLOWHZ) /* default probe interval */
+#define TCPTV_KEEPCNT 8 /* max probes before drop */
#define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */
#define TCPTV_REXMTMAX ( 64*PR_SLOWHZ) /* max allowable REXMT value */
#define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */
#define TCPTV_REXMTMAX ( 64*PR_SLOWHZ) /* max allowable REXMT value */
+extern int tcp_keepidle; /* time before keepalive probes begin */
+extern int tcp_keepintvl; /* time between keepalive probes */
+extern int tcp_maxidle; /* time to drop after starting probes */
+extern int tcp_ttl; /* time to live for TCP segs */
extern int tcp_backoff[];
#endif
extern int tcp_backoff[];
#endif
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*
- * @(#)tcp_usrreq.c 7.7.1.1 (Berkeley) %G%
+ * @(#)tcp_usrreq.c 7.8 (Berkeley) %G%
soisconnecting(so);
tcpstat.tcps_connattempt++;
tp->t_state = TCPS_SYN_SENT;
soisconnecting(so);
tcpstat.tcps_connattempt++;
tp->t_state = TCPS_SYN_SENT;
- tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
+ tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
tcp_sendseqinit(tp);
error = tcp_output(tp);
tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
tcp_sendseqinit(tp);
error = tcp_output(tp);