summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormohans <mohans@FreeBSD.org>2006-08-11 21:15:23 +0000
committermohans <mohans@FreeBSD.org>2006-08-11 21:15:23 +0000
commit707c86ce464655cc21368747d6d2380c3a45d907 (patch)
tree79bc8d154909be166e8a4c6f574e46e753772107
parentce9f8963fd6c7fcb782d8b9eebf51fb108d847f8 (diff)
downloadFreeBSD-src-707c86ce464655cc21368747d6d2380c3a45d907.zip
FreeBSD-src-707c86ce464655cc21368747d6d2380c3a45d907.tar.gz
Fixes an edge case bug in timewait handling where ticks rolling over causing
the timewait expiry to be exactly 0 corrupts the timewait queues (and that entry). Reviewed by: silby
-rw-r--r--sys/netinet/tcp_input.c2
-rw-r--r--sys/netinet/tcp_reass.c2
-rw-r--r--sys/netinet/tcp_subr.c2
-rw-r--r--sys/netinet/tcp_timer.c7
-rw-r--r--sys/netinet/tcp_timer.h2
-rw-r--r--sys/netinet/tcp_timewait.c2
6 files changed, 8 insertions, 9 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index ddea86f..86f9325 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -3251,7 +3251,7 @@ tcp_timewait(inp, to, th, m, tlen)
if (thflags & TH_FIN) {
seq = th->th_seq + tlen + (thflags & TH_SYN ? 1 : 0);
if (seq + 1 == tw->rcv_nxt)
- tcp_timer_2msl_reset(tw, 2 * tcp_msl);
+ tcp_timer_2msl_reset(tw, 2 * tcp_msl, 1);
}
/*
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index ddea86f..86f9325 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -3251,7 +3251,7 @@ tcp_timewait(inp, to, th, m, tlen)
if (thflags & TH_FIN) {
seq = th->th_seq + tlen + (thflags & TH_SYN ? 1 : 0);
if (seq + 1 == tw->rcv_nxt)
- tcp_timer_2msl_reset(tw, 2 * tcp_msl);
+ tcp_timer_2msl_reset(tw, 2 * tcp_msl, 1);
}
/*
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 2a95f7c..fe8e4b5 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1763,7 +1763,7 @@ tcp_twstart(struct tcpcb *tp)
tcp_twrespond(tw, TH_ACK);
inp->inp_ppcb = tw;
inp->inp_vflag |= INP_TIMEWAIT;
- tcp_timer_2msl_reset(tw, tw_time);
+ tcp_timer_2msl_reset(tw, tw_time, 0);
/*
* If the inpcb owns the sole reference to the socket, then we can
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 6b8698c..5c105b4 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -257,14 +257,14 @@ tcp_timer_init(void)
}
void
-tcp_timer_2msl_reset(struct tcptw *tw, int timeo)
+tcp_timer_2msl_reset(struct tcptw *tw, int timeo, int rearm)
{
int i;
struct tcptw *tw_tail;
INP_INFO_WLOCK_ASSERT(&tcbinfo);
INP_LOCK_ASSERT(tw->tw_inpcb);
- if (tw->tw_time != 0)
+ if (rearm)
LIST_REMOVE(tw, tw_2msl);
tw->tw_time = timeo + ticks;
i = timeo > tcp_msl ? 1 : 0;
@@ -277,8 +277,7 @@ tcp_timer_2msl_stop(struct tcptw *tw)
{
INP_INFO_WLOCK_ASSERT(&tcbinfo);
- if (tw->tw_time != 0)
- LIST_REMOVE(tw, tw_2msl);
+ LIST_REMOVE(tw, tw_2msl);
}
struct tcptw *
diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h
index d3d7c94..815a757 100644
--- a/sys/netinet/tcp_timer.h
+++ b/sys/netinet/tcp_timer.h
@@ -156,7 +156,7 @@ void tcp_timer_init(void);
void tcp_timer_2msl(void *xtp);
struct tcptw *
tcp_timer_2msl_tw(int _reuse); /* XXX temporary */
-void tcp_timer_2msl_reset(struct tcptw *_tw, int _timeo);
+void tcp_timer_2msl_reset(struct tcptw *_tw, int _timeo, int rearm);
void tcp_timer_2msl_stop(struct tcptw *_tw);
void tcp_timer_keep(void *xtp);
void tcp_timer_persist(void *xtp);
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 2a95f7c..fe8e4b5 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -1763,7 +1763,7 @@ tcp_twstart(struct tcpcb *tp)
tcp_twrespond(tw, TH_ACK);
inp->inp_ppcb = tw;
inp->inp_vflag |= INP_TIMEWAIT;
- tcp_timer_2msl_reset(tw, tw_time);
+ tcp_timer_2msl_reset(tw, tw_time, 0);
/*
* If the inpcb owns the sole reference to the socket, then we can
OpenPOWER on IntegriCloud