diff options
author | rwatson <rwatson@FreeBSD.org> | 2006-06-03 19:37:08 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2006-06-03 19:37:08 +0000 |
commit | 8d3568ae0be8d4f8b0f415366e93bfc52de32dbe (patch) | |
tree | ff22778b3a233a1cacac21148c53f4ba9015179e /sys/netinet/tcp_timer.c | |
parent | 133fd236d101c0bcc7a0d460848ed4ea4c15a47b (diff) | |
download | FreeBSD-src-8d3568ae0be8d4f8b0f415366e93bfc52de32dbe.zip FreeBSD-src-8d3568ae0be8d4f8b0f415366e93bfc52de32dbe.tar.gz |
When entering a timer on a tcpcb, don't continue processing if it has been
dropped. This prevents a bug introduced during the socket/pcb refcounting
work from occuring, in which occasionally the retransmit timer may fire
after a connection has been reset, resulting in the resulting R|A TCP
packet having a source port of 0, as the port reservation has been
released.
While here, fixing up some RUNLOCK->WUNLOCK bugs.
MFC after: 1 month
Diffstat (limited to 'sys/netinet/tcp_timer.c')
-rw-r--r-- | sys/netinet/tcp_timer.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 6dfc8df..6b8698c 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -156,7 +156,8 @@ tcp_timer_delack(xtp) } INP_LOCK(inp); INP_INFO_RUNLOCK(&tcbinfo); - if (callout_pending(tp->tt_delack) || !callout_active(tp->tt_delack)) { + if ((inp->inp_vflag & INP_DROPPED) || callout_pending(tp->tt_delack) + || !callout_active(tp->tt_delack)) { INP_UNLOCK(inp); return; } @@ -193,12 +194,13 @@ tcp_timer_2msl(xtp) */ if (inp == NULL) { tcp_timer_race++; - INP_INFO_RUNLOCK(&tcbinfo); + INP_INFO_WUNLOCK(&tcbinfo); return; } INP_LOCK(inp); tcp_free_sackholes(tp); - if (callout_pending(tp->tt_2msl) || !callout_active(tp->tt_2msl)) { + if ((inp->inp_vflag & INP_DROPPED) || callout_pending(tp->tt_2msl) || + !callout_active(tp->tt_2msl)) { INP_UNLOCK(tp->t_inpcb); INP_INFO_WUNLOCK(&tcbinfo); return; @@ -323,11 +325,12 @@ tcp_timer_keep(xtp) */ if (inp == NULL) { tcp_timer_race++; - INP_INFO_RUNLOCK(&tcbinfo); + INP_INFO_WUNLOCK(&tcbinfo); return; } INP_LOCK(inp); - if (callout_pending(tp->tt_keep) || !callout_active(tp->tt_keep)) { + if ((inp->inp_vflag & INP_DROPPED) || callout_pending(tp->tt_keep) + || !callout_active(tp->tt_keep)) { INP_UNLOCK(inp); INP_INFO_WUNLOCK(&tcbinfo); return; @@ -413,11 +416,12 @@ tcp_timer_persist(xtp) */ if (inp == NULL) { tcp_timer_race++; - INP_INFO_RUNLOCK(&tcbinfo); + INP_INFO_WUNLOCK(&tcbinfo); return; } INP_LOCK(inp); - if (callout_pending(tp->tt_persist) || !callout_active(tp->tt_persist)){ + if ((inp->inp_vflag & INP_DROPPED) || callout_pending(tp->tt_persist) + || !callout_active(tp->tt_persist)) { INP_UNLOCK(inp); INP_INFO_WUNLOCK(&tcbinfo); return; @@ -482,11 +486,12 @@ tcp_timer_rexmt(xtp) */ if (inp == NULL) { tcp_timer_race++; - INP_INFO_RUNLOCK(&tcbinfo); + INP_INFO_WUNLOCK(&tcbinfo); return; } INP_LOCK(inp); - if (callout_pending(tp->tt_rexmt) || !callout_active(tp->tt_rexmt)) { + if ((inp->inp_vflag & INP_DROPPED) || callout_pending(tp->tt_rexmt) + || !callout_active(tp->tt_rexmt)) { INP_UNLOCK(inp); INP_INFO_WUNLOCK(&tcbinfo); return; |