Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102826545
D17595.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D17595.diff
View Options
Index: head/sys/netinet/tcp_input.c
===================================================================
--- head/sys/netinet/tcp_input.c
+++ head/sys/netinet/tcp_input.c
@@ -1165,7 +1165,7 @@
* causes.
*/
if (thflags & TH_RST) {
- syncache_chkrst(&inc, th);
+ syncache_chkrst(&inc, th, m);
goto dropunlock;
}
/*
Index: head/sys/netinet/tcp_syncache.h
===================================================================
--- head/sys/netinet/tcp_syncache.h
+++ head/sys/netinet/tcp_syncache.h
@@ -46,7 +46,7 @@
int syncache_add(struct in_conninfo *, struct tcpopt *,
struct tcphdr *, struct inpcb *, struct socket **, struct mbuf *,
void *, void *);
-void syncache_chkrst(struct in_conninfo *, struct tcphdr *);
+void syncache_chkrst(struct in_conninfo *, struct tcphdr *, struct mbuf *);
void syncache_badack(struct in_conninfo *);
int syncache_pcblist(struct sysctl_req *req, int max_pcbs, int *pcbs_exported);
Index: head/sys/netinet/tcp_syncache.c
===================================================================
--- head/sys/netinet/tcp_syncache.c
+++ head/sys/netinet/tcp_syncache.c
@@ -131,7 +131,7 @@
static void syncache_free(struct syncache *);
static void syncache_insert(struct syncache *, struct syncache_head *);
static int syncache_respond(struct syncache *, struct syncache_head *,
- const struct mbuf *);
+ const struct mbuf *, int);
static struct socket *syncache_socket(struct syncache *, struct socket *,
struct mbuf *m);
static void syncache_timeout(struct syncache *sc, struct syncache_head *sch,
@@ -489,7 +489,7 @@
free(s, M_TCPLOG);
}
- syncache_respond(sc, sch, NULL);
+ syncache_respond(sc, sch, NULL, TH_SYN|TH_ACK);
TCPSTAT_INC(tcps_sc_retransmitted);
syncache_timeout(sc, sch, 0);
}
@@ -537,9 +537,10 @@
* This function is called when we get a RST for a
* non-existent connection, so that we can see if the
* connection is in the syn cache. If it is, zap it.
+ * If required send a challenge ACK.
*/
void
-syncache_chkrst(struct in_conninfo *inc, struct tcphdr *th)
+syncache_chkrst(struct in_conninfo *inc, struct tcphdr *th, struct mbuf *m)
{
struct syncache *sc;
struct syncache_head *sch;
@@ -590,19 +591,36 @@
* send a reset with the sequence number at the rightmost edge
* of our receive window, and we have to handle this case.
*/
- if (SEQ_GEQ(th->th_seq, sc->sc_irs) &&
- SEQ_LEQ(th->th_seq, sc->sc_irs + sc->sc_wnd)) {
- syncache_drop(sc, sch);
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
- log(LOG_DEBUG, "%s; %s: Our SYN|ACK was rejected, "
- "connection attempt aborted by remote endpoint\n",
- s, __func__);
- TCPSTAT_INC(tcps_sc_reset);
+ if ((SEQ_GEQ(th->th_seq, sc->sc_irs + 1) &&
+ SEQ_LT(th->th_seq, sc->sc_irs + 1 + sc->sc_wnd)) ||
+ (sc->sc_wnd == 0 && th->th_seq == sc->sc_irs + 1)) {
+ if (V_tcp_insecure_rst ||
+ th->th_seq == sc->sc_irs + 1) {
+ syncache_drop(sc, sch);
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ log(LOG_DEBUG,
+ "%s; %s: Our SYN|ACK was rejected, "
+ "connection attempt aborted by remote "
+ "endpoint\n",
+ s, __func__);
+ TCPSTAT_INC(tcps_sc_reset);
+ } else {
+ TCPSTAT_INC(tcps_badrst);
+ /* Send challenge ACK. */
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ log(LOG_DEBUG, "%s; %s: RST with invalid "
+ " SEQ %u != NXT %u (+WND %u), "
+ "sending challenge ACK\n",
+ s, __func__,
+ th->th_seq, sc->sc_irs + 1, sc->sc_wnd);
+ syncache_respond(sc, sch, m, TH_ACK);
+ }
} else {
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
log(LOG_DEBUG, "%s; %s: RST with invalid SEQ %u != "
- "IRS %u (+WND %u), segment ignored\n",
- s, __func__, th->th_seq, sc->sc_irs, sc->sc_wnd);
+ "NXT %u (+WND %u), segment ignored\n",
+ s, __func__,
+ th->th_seq, sc->sc_irs + 1, sc->sc_wnd);
TCPSTAT_INC(tcps_badrst);
}
@@ -1413,7 +1431,7 @@
s, __func__);
free(s, M_TCPLOG);
}
- if (syncache_respond(sc, sch, m) == 0) {
+ if (syncache_respond(sc, sch, m, TH_SYN|TH_ACK) == 0) {
sc->sc_rxmits = 0;
syncache_timeout(sc, sch, 1);
TCPSTAT_INC(tcps_sndacks);
@@ -1577,7 +1595,7 @@
/*
* Do a standard 3-way handshake.
*/
- if (syncache_respond(sc, sch, m) == 0) {
+ if (syncache_respond(sc, sch, m, TH_SYN|TH_ACK) == 0) {
if (V_tcp_syncookies && V_tcp_syncookiesonly && sc != &scs)
syncache_free(sc);
else if (sc != &scs)
@@ -1618,12 +1636,12 @@
}
/*
- * Send SYN|ACK to the peer. Either in response to the peer's SYN,
+ * Send SYN|ACK or ACK to the peer. Either in response to a peer's segment,
* i.e. m0 != NULL, or upon 3WHS ACK timeout, i.e. m0 == NULL.
*/
static int
syncache_respond(struct syncache *sc, struct syncache_head *sch,
- const struct mbuf *m0)
+ const struct mbuf *m0, int flags)
{
struct ip *ip = NULL;
struct mbuf *m;
@@ -1709,15 +1727,18 @@
th->th_sport = sc->sc_inc.inc_lport;
th->th_dport = sc->sc_inc.inc_fport;
- th->th_seq = htonl(sc->sc_iss);
+ if (flags & TH_SYN)
+ th->th_seq = htonl(sc->sc_iss);
+ else
+ th->th_seq = htonl(sc->sc_iss + 1);
th->th_ack = htonl(sc->sc_irs + 1);
th->th_off = sizeof(struct tcphdr) >> 2;
th->th_x2 = 0;
- th->th_flags = TH_SYN|TH_ACK;
+ th->th_flags = flags;
th->th_win = htons(sc->sc_wnd);
th->th_urp = 0;
- if (sc->sc_flags & SCF_ECN) {
+ if ((flags & TH_SYN) && (sc->sc_flags & SCF_ECN)) {
th->th_flags |= TH_ECE;
TCPSTAT_INC(tcps_ecn_shs);
}
@@ -1726,29 +1747,31 @@
if ((sc->sc_flags & SCF_NOOPT) == 0) {
to.to_flags = 0;
- to.to_mss = mssopt;
- to.to_flags = TOF_MSS;
- if (sc->sc_flags & SCF_WINSCALE) {
- to.to_wscale = sc->sc_requested_r_scale;
- to.to_flags |= TOF_SCALE;
+ if (flags & TH_SYN) {
+ to.to_mss = mssopt;
+ to.to_flags = TOF_MSS;
+ if (sc->sc_flags & SCF_WINSCALE) {
+ to.to_wscale = sc->sc_requested_r_scale;
+ to.to_flags |= TOF_SCALE;
+ }
+ if (sc->sc_flags & SCF_SACK)
+ to.to_flags |= TOF_SACKPERM;
+#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
+ if (sc->sc_flags & SCF_SIGNATURE)
+ to.to_flags |= TOF_SIGNATURE;
+#endif
+ if (sc->sc_tfo_cookie) {
+ to.to_flags |= TOF_FASTOPEN;
+ to.to_tfo_len = TCP_FASTOPEN_COOKIE_LEN;
+ to.to_tfo_cookie = sc->sc_tfo_cookie;
+ /* don't send cookie again when retransmitting response */
+ sc->sc_tfo_cookie = NULL;
+ }
}
if (sc->sc_flags & SCF_TIMESTAMP) {
to.to_tsval = sc->sc_tsoff + tcp_ts_getticks();
to.to_tsecr = sc->sc_tsreflect;
to.to_flags |= TOF_TS;
- }
- if (sc->sc_flags & SCF_SACK)
- to.to_flags |= TOF_SACKPERM;
-#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
- if (sc->sc_flags & SCF_SIGNATURE)
- to.to_flags |= TOF_SIGNATURE;
-#endif
- if (sc->sc_tfo_cookie) {
- to.to_flags |= TOF_FASTOPEN;
- to.to_tfo_len = TCP_FASTOPEN_COOKIE_LEN;
- to.to_tfo_cookie = sc->sc_tfo_cookie;
- /* don't send cookie again when retransmitting response */
- sc->sc_tfo_cookie = NULL;
}
optlen = tcp_addoptions(&to, (u_char *)(th + 1));
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 18, 4:58 PM (21 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14701229
Default Alt Text
D17595.diff (6 KB)
Attached To
Mode
D17595: Fix handling of RST segments in SYN-RCVD state via the syn cache code path
Attached
Detach File
Event Timeline
Log In to Comment