From e207f800392a350bd09109fc07d767a1a6e520dd Mon Sep 17 00:00:00 2001 From: Andre Oppermann Date: Fri, 20 Apr 2007 13:51:34 +0000 Subject: [PATCH] Simplifly syncache_expand() and clarify its semantics. Zero is returned when the ACK is invalid and doesn't belong to any registered connection, either in syncache or through SYN cookies. True but a NULL struct socket is returned when the 3WHS completed but the socket could not be created due to insufficient resources or limits reached. For both cases an RST is sent back in tcp_input(). A logic error leading to a panic is fixed where syncache_expand() would free the mbuf on socket allocation failure but tcp_input() later supplies it to tcp_dropwithreset() to issue a RST to the peer. Reported by: kris (the panic) --- sys/netinet/tcp_input.c | 16 ++++++++-------- sys/netinet/tcp_reass.c | 16 ++++++++-------- sys/netinet/tcp_syncache.c | 21 ++++----------------- 3 files changed, 20 insertions(+), 33 deletions(-) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index e6022b454f96..bf8df6aad53f 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -832,22 +832,22 @@ tcp_input(struct mbuf *m, int off0) tcp_dooptions(&to, optp, optlen, 0); if (!syncache_expand(&inc, &to, th, &so, m)) { /* - * No syncache entry, or ACK was not + * No syncache entry or ACK was not * for our SYN/ACK. Send a RST. */ - tcpstat.tcps_badsyn++; rstreason = BANDLIM_RST_OPENPORT; goto dropwithreset; } if (so == NULL) { /* - * Could not complete 3-way handshake, - * connection is being closed down, and - * syncache has free'd mbuf. + * We completed the 3-way handshake + * but could not allocate a socket + * either due to memory shortage, + * listen queue length limits or + * global socket limits. */ - INP_UNLOCK(inp); - INP_INFO_WUNLOCK(&tcbinfo); - return; + rstreason = BANDLIM_UNLIMITED; + goto dropwithreset; } /* * Socket is created in state SYN_RECEIVED. diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index e6022b454f96..bf8df6aad53f 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -832,22 +832,22 @@ tcp_input(struct mbuf *m, int off0) tcp_dooptions(&to, optp, optlen, 0); if (!syncache_expand(&inc, &to, th, &so, m)) { /* - * No syncache entry, or ACK was not + * No syncache entry or ACK was not * for our SYN/ACK. Send a RST. */ - tcpstat.tcps_badsyn++; rstreason = BANDLIM_RST_OPENPORT; goto dropwithreset; } if (so == NULL) { /* - * Could not complete 3-way handshake, - * connection is being closed down, and - * syncache has free'd mbuf. + * We completed the 3-way handshake + * but could not allocate a socket + * either due to memory shortage, + * listen queue length limits or + * global socket limits. */ - INP_UNLOCK(inp); - INP_INFO_WUNLOCK(&tcbinfo); - return; + rstreason = BANDLIM_UNLIMITED; + goto dropwithreset; } /* * Socket is created in state SYN_RECEIVED. diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 939a49cece11..6d1d1a208f7f 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -758,7 +758,6 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, { struct syncache *sc; struct syncache_head *sch; - struct socket *so; struct syncache scs; /* @@ -803,25 +802,12 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, if (th->th_ack != sc->sc_iss + 1) goto failed; - so = syncache_socket(sc, *lsop, m); + *lsop = syncache_socket(sc, *lsop, m); - if (so == NULL) { -#if 0 -resetandabort: - /* XXXjlemon check this - is this correct? */ - (void) tcp_respond(NULL, m, m, th, - th->th_seq + tlen, (tcp_seq)0, TH_RST|TH_ACK); -#endif - m_freem(m); /* XXX: only needed for above */ + if (*lsop == NULL) tcpstat.tcps_sc_aborted++; - if (sc != &scs) { - syncache_insert(sc, sch); /* try again later */ - sc = NULL; - } - goto failed; - } else + else tcpstat.tcps_sc_completed++; - *lsop = so; if (sc != &scs) syncache_free(sc); @@ -829,6 +815,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, failed: if (sc != NULL && sc != &scs) syncache_free(sc); + *lsop = NULL; return (0); }