diff options
author | rwatson <rwatson@FreeBSD.org> | 2006-04-09 16:59:19 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2006-04-09 16:59:19 +0000 |
commit | e194ddde243c3305592a9f5b8085cbedc87a9cb4 (patch) | |
tree | fc07b90db4c9ecf85366bbc3fb22dbbe8160fc22 /sys/netinet | |
parent | 9fbf53f0d048171e070fa8b051fddf64573108f8 (diff) | |
download | FreeBSD-src-e194ddde243c3305592a9f5b8085cbedc87a9cb4.zip FreeBSD-src-e194ddde243c3305592a9f5b8085cbedc87a9cb4.tar.gz |
Modify tcp_timewait() to accept an inpcb reference, not a tcptw
reference. For now, we allow the possibility that the in_ppcb
pointer in the inpcb may be NULL if a timewait socket has had its
tcptw structure recycled. This allows tcp_timewait() to
consistently unlock the inpcb.
Reported by: Kazuaki Oda <kaakun at highway dot ne dot jp>
MFC after: 3 months
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/tcp_input.c | 23 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 23 |
2 files changed, 24 insertions, 22 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 0532f71..c31892c 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -173,7 +173,7 @@ static int tcp_reass(struct tcpcb *, struct tcphdr *, int *, struct mbuf *); static void tcp_xmit_timer(struct tcpcb *, int); static void tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *); -static int tcp_timewait(struct tcptw *, struct tcpopt *, +static int tcp_timewait(struct inpcb *, struct tcpopt *, struct tcphdr *, struct mbuf *, int); /* Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint. */ @@ -760,7 +760,7 @@ findpcb: */ if (thflags & TH_SYN) tcp_dooptions(&to, optp, optlen, 1); - if (tcp_timewait(intotw(inp), &to, th, m, tlen)) + if (tcp_timewait(inp, &to, th, m, tlen)) goto findpcb; /* * tcp_timewait unlocks inp. @@ -3141,13 +3141,14 @@ tcp_newreno_partial_ack(tp, th) * looking for a pcb in the listen state. Returns 0 otherwise. */ static int -tcp_timewait(tw, to, th, m, tlen) - struct tcptw *tw; +tcp_timewait(inp, to, th, m, tlen) + struct inpcb *inp; struct tcpopt *to; struct tcphdr *th; struct mbuf *m; int tlen; { + struct tcptw *tw; int thflags; tcp_seq seq; #ifdef INET6 @@ -3156,19 +3157,20 @@ tcp_timewait(tw, to, th, m, tlen) const int isipv6 = 0; #endif + /* tcbinfo lock required for tcp_twclose(), tcp_2msl_reset. */ + INP_INFO_WLOCK_ASSERT(&tcbinfo); + INP_LOCK_ASSERT(inp); + /* * XXXRW: Time wait state for inpcb has been recycled, but inpcb is * still present. This is undesirable, but temporarily necessary * until we work out how to handle inpcb's who's timewait state has * been removed. */ + tw = intotw(inp); if (tw == NULL) goto drop; - /* tcbinfo lock required for tcp_twclose(), tcp_2msl_reset. */ - INP_INFO_WLOCK_ASSERT(&tcbinfo); - INP_LOCK_ASSERT(tw->tw_inpcb); - thflags = th->th_flags; /* @@ -3268,12 +3270,11 @@ tcp_timewait(tw, to, th, m, tlen) tcp_respond(NULL, mtod(m, void *), th, m, seq, 0, TH_RST|TH_ACK); } - INP_UNLOCK(tw->tw_inpcb); + INP_UNLOCK(inp); return (0); drop: - if (tw != NULL) - INP_UNLOCK(tw->tw_inpcb); + INP_UNLOCK(inp); m_freem(m); return (0); } diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 0532f71..c31892c 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -173,7 +173,7 @@ static int tcp_reass(struct tcpcb *, struct tcphdr *, int *, struct mbuf *); static void tcp_xmit_timer(struct tcpcb *, int); static void tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *); -static int tcp_timewait(struct tcptw *, struct tcpopt *, +static int tcp_timewait(struct inpcb *, struct tcpopt *, struct tcphdr *, struct mbuf *, int); /* Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint. */ @@ -760,7 +760,7 @@ findpcb: */ if (thflags & TH_SYN) tcp_dooptions(&to, optp, optlen, 1); - if (tcp_timewait(intotw(inp), &to, th, m, tlen)) + if (tcp_timewait(inp, &to, th, m, tlen)) goto findpcb; /* * tcp_timewait unlocks inp. @@ -3141,13 +3141,14 @@ tcp_newreno_partial_ack(tp, th) * looking for a pcb in the listen state. Returns 0 otherwise. */ static int -tcp_timewait(tw, to, th, m, tlen) - struct tcptw *tw; +tcp_timewait(inp, to, th, m, tlen) + struct inpcb *inp; struct tcpopt *to; struct tcphdr *th; struct mbuf *m; int tlen; { + struct tcptw *tw; int thflags; tcp_seq seq; #ifdef INET6 @@ -3156,19 +3157,20 @@ tcp_timewait(tw, to, th, m, tlen) const int isipv6 = 0; #endif + /* tcbinfo lock required for tcp_twclose(), tcp_2msl_reset. */ + INP_INFO_WLOCK_ASSERT(&tcbinfo); + INP_LOCK_ASSERT(inp); + /* * XXXRW: Time wait state for inpcb has been recycled, but inpcb is * still present. This is undesirable, but temporarily necessary * until we work out how to handle inpcb's who's timewait state has * been removed. */ + tw = intotw(inp); if (tw == NULL) goto drop; - /* tcbinfo lock required for tcp_twclose(), tcp_2msl_reset. */ - INP_INFO_WLOCK_ASSERT(&tcbinfo); - INP_LOCK_ASSERT(tw->tw_inpcb); - thflags = th->th_flags; /* @@ -3268,12 +3270,11 @@ tcp_timewait(tw, to, th, m, tlen) tcp_respond(NULL, mtod(m, void *), th, m, seq, 0, TH_RST|TH_ACK); } - INP_UNLOCK(tw->tw_inpcb); + INP_UNLOCK(inp); return (0); drop: - if (tw != NULL) - INP_UNLOCK(tw->tw_inpcb); + INP_UNLOCK(inp); m_freem(m); return (0); } |