Page MenuHomeFreeBSD

D36066.diff
No OneTemporary

D36066.diff

diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -833,8 +833,9 @@
* PCB, be it a listening one or a synchronized one. The packet
* shall not modify its state.
*/
- lookupflag = (thflags & (TH_ACK|TH_SYN)) == TH_SYN ?
- INPLOOKUP_RLOCKPCB : INPLOOKUP_WLOCKPCB;
+ lookupflag = INPLOOKUP_WILDCARD |
+ ((thflags & (TH_ACK|TH_SYN)) == TH_SYN ?
+ INPLOOKUP_RLOCKPCB : INPLOOKUP_WLOCKPCB);
findpcb:
#ifdef INET6
if (isipv6 && fwd_tag != NULL) {
@@ -857,13 +858,12 @@
inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_src,
th->th_sport, &next_hop6->sin6_addr,
next_hop6->sin6_port ? ntohs(next_hop6->sin6_port) :
- th->th_dport, INPLOOKUP_WILDCARD | lookupflag,
- m->m_pkthdr.rcvif);
+ th->th_dport, lookupflag, m->m_pkthdr.rcvif);
}
} else if (isipv6) {
inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src,
- th->th_sport, &ip6->ip6_dst, th->th_dport,
- INPLOOKUP_WILDCARD | lookupflag, m->m_pkthdr.rcvif, m);
+ th->th_sport, &ip6->ip6_dst, th->th_dport, lookupflag,
+ m->m_pkthdr.rcvif, m);
}
#endif /* INET6 */
#if defined(INET6) && defined(INET)
@@ -889,13 +889,12 @@
inp = in_pcblookup(&V_tcbinfo, ip->ip_src,
th->th_sport, next_hop->sin_addr,
next_hop->sin_port ? ntohs(next_hop->sin_port) :
- th->th_dport, INPLOOKUP_WILDCARD | lookupflag,
- m->m_pkthdr.rcvif);
+ th->th_dport, lookupflag, m->m_pkthdr.rcvif);
}
} else
inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src,
- th->th_sport, ip->ip_dst, th->th_dport,
- INPLOOKUP_WILDCARD | lookupflag, m->m_pkthdr.rcvif, m);
+ th->th_sport, ip->ip_dst, th->th_dport, lookupflag,
+ m->m_pkthdr.rcvif, m);
#endif /* INET */
/*
@@ -904,6 +903,11 @@
* XXX MRT Send RST using which routing table?
*/
if (inp == NULL) {
+ if (rstreason != 0) {
+ /* We came here after second (safety) lookup. */
+ MPASS((lookupflag & INPLOOKUP_WILDCARD) == 0);
+ goto dropwithreset;
+ }
/*
* Log communication attempts to ports that are not
* in use.
@@ -1095,13 +1099,26 @@
goto dropunlock;
} else if (rstreason == 0) {
/*
- * No syncache entry or ACK was not
- * for our SYN/ACK. Send a RST.
+ * No syncache entry, or ACK was not for our
+ * SYN/ACK. Do our protection against double
+ * ACK. If peer sent us 2 ACKs, then for the
+ * first one syncache_expand() successfully
+ * converted syncache entry into a socket,
+ * while we were waiting on the inpcb lock. We
+ * don't want to sent RST for the second ACK,
+ * so we perform second lookup without wildcard
+ * match, hoping to find the new socket. If
+ * the ACK is stray indeed, rstreason would
+ * hint the above code that the lookup was a
+ * second attempt.
+ *
* NB: syncache did its own logging
* of the failure cause.
*/
+ INP_WUNLOCK(inp);
rstreason = BANDLIM_RST_OPENPORT;
- goto dropwithreset;
+ lookupflag &= ~INPLOOKUP_WILDCARD;
+ goto findpcb;
}
tfo_socket_result:
if (so == NULL) {
@@ -1390,7 +1407,7 @@
* to upgrade the lock, because calling convention for stacks is
* write-lock on PCB. If upgrade fails, drop the SYN.
*/
- if (lookupflag == INPLOOKUP_RLOCKPCB && INP_TRY_UPGRADE(inp) == 0)
+ if ((lookupflag & INPLOOKUP_RLOCKPCB) && INP_TRY_UPGRADE(inp) == 0)
goto dropunlock;
tp->t_fb->tfb_tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, iptos);

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 17, 3:36 PM (22 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14681638
Default Alt Text
D36066.diff (3 KB)

Event Timeline