diff --git a/CHANGELOG b/CHANGELOG index d07be8af..ce1c1f18 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -76,7 +76,11 @@ HISTORY ++ Bugfixes: 2009-03-26 Kieran Mansley - * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes + * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping + connections where no reset required (bug #25622) + + * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes + (bug #20779) 2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach) * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be diff --git a/src/core/tcp.c b/src/core/tcp.c index 91fca5d7..f996b6b7 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -186,14 +186,15 @@ tcp_close(struct tcp_pcb *pcb) } /** - * Aborts a connection by sending a RST to the remote host and deletes - * the local protocol control block. This is done when a connection is - * killed because of shortage of memory. + * Abandons a connection and optionally sends a RST to the remote + * host. Deletes the local protocol control block. This is done when + * a connection is killed because of shortage of memory. * * @param pcb the tcp_pcb to abort + * @param reset boolean to indicate whether a reset should be sent */ void -tcp_abort(struct tcp_pcb *pcb) +tcp_abandon(struct tcp_pcb *pcb, int reset) { u32_t seqno, ackno; u16_t remote_port, local_port; @@ -235,8 +236,10 @@ tcp_abort(struct tcp_pcb *pcb) #endif /* TCP_QUEUE_OOSEQ */ memp_free(MEMP_TCP_PCB, pcb); TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abort: sending RST\n")); - tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port); + if (reset) { + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); + tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port); + } } } diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index d58420c4..a1e52fcd 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -394,6 +394,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) { struct tcp_pcb *npcb; u32_t optdata; + err_t rc; /* In the LISTEN state, we check for incoming SYN segments, creates a new PCB, and responds with a SYN|ACK. */ @@ -454,7 +455,11 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) /* Build an MSS option. */ optdata = TCP_BUILD_MSS_OPTION(); /* Send a SYN|ACK together with the MSS option. */ - tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4); + rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4); + if (rc != ERR_OK) { + tcp_abandon(npcb, 0); + return rc; + } return tcp_output(npcb); } return ERR_OK; diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h index 60d46ccc..745054e6 100644 --- a/src/include/lwip/tcp.h +++ b/src/include/lwip/tcp.h @@ -96,7 +96,8 @@ err_t tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr, struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); #define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) -void tcp_abort (struct tcp_pcb *pcb); +void tcp_abandon (struct tcp_pcb *pcb, int reset); +#define tcp_abort(pcb) tcp_abandon((pcb), 1) err_t tcp_close (struct tcp_pcb *pcb); /* Flags for "apiflags" parameter in tcp_write and tcp_enqueue */