From f85eed0ab30f8ced3d5c471626ca0ffca17fe5fc Mon Sep 17 00:00:00 2001 From: goldsimon Date: Tue, 28 Feb 2017 12:13:26 +0100 Subject: [PATCH] tcp: fixed bug #50418: LWIP_EVENT_API: fix invalid calbacks for SYN_RCVD pcb --- CHANGELOG | 3 +++ src/core/tcp.c | 8 ++++++-- src/core/tcp_in.c | 4 ++-- src/include/lwip/priv/tcp_priv.h | 13 ++++++++----- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index a637d7c7..656c2109 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -26,6 +26,9 @@ HISTORY ++ Bugfixes: + 2017-02-28: David van Moolenbroek/Simon Goldschmidt + tcp: fixed bug #50418: LWIP_EVENT_API: fix invalid calbacks for SYN_RCVD pcb + 2017-02-24: Simon Goldschmidt * sockets.c: fixed close race conditions in lwip_select (for LWIP_NETCONN_FULLDUPLEX) diff --git a/src/core/tcp.c b/src/core/tcp.c index 79c78394..f073a616 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -482,6 +482,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset) } else { int send_rst = 0; u16_t local_port = 0; + enum tcp_state last_state; seqno = pcb->snd_nxt; ackno = pcb->rcv_nxt; #if LWIP_CALLBACK_API @@ -514,8 +515,9 @@ tcp_abandon(struct tcp_pcb *pcb, int reset) LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port); } + last_state = pcb->state; memp_free(MEMP_TCP_PCB, pcb); - TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); + TCP_EVENT_ERR(last_state, errf, errf_arg, ERR_ABRT); } } @@ -1179,6 +1181,7 @@ tcp_slowtmr_start: tcp_err_fn err_fn = pcb->errf; #endif /* LWIP_CALLBACK_API */ void *err_arg; + enum tcp_state last_state; tcp_pcb_purge(pcb); /* Remove PCB from tcp_active_pcbs list. */ if (prev != NULL) { @@ -1196,12 +1199,13 @@ tcp_slowtmr_start: } err_arg = pcb->callback_arg; + last_state = pcb->state; pcb2 = pcb; pcb = pcb->next; memp_free(MEMP_TCP_PCB, pcb2); tcp_active_pcbs_changed = 0; - TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT); + TCP_EVENT_ERR(last_state, err_fn, err_arg, ERR_ABRT); if (tcp_active_pcbs_changed) { goto tcp_slowtmr_start; } diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 21279e32..324fa48f 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -378,7 +378,7 @@ tcp_input(struct pbuf *p, struct netif *inp) end. We then call the error callback to inform the application that the connection is dead before we deallocate the PCB. */ - TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); + TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_RST); tcp_pcb_remove(&tcp_active_pcbs, pcb); memp_free(MEMP_TCP_PCB, pcb); } else { @@ -413,7 +413,7 @@ tcp_input(struct pbuf *p, struct netif *inp) /* Connection closed although the application has only shut down the tx side: call the PCB's err callback and indicate the closure to ensure the application doesn't continue using the PCB. */ - TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD); + TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD); } tcp_pcb_remove(&tcp_active_pcbs, pcb); memp_free(MEMP_TCP_PCB, pcb); diff --git a/src/include/lwip/priv/tcp_priv.h b/src/include/lwip/priv/tcp_priv.h index cfcce782..3e115b23 100644 --- a/src/include/lwip/priv/tcp_priv.h +++ b/src/include/lwip/priv/tcp_priv.h @@ -170,10 +170,12 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb); LWIP_EVENT_RECV, NULL, 0, ERR_OK) #define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ LWIP_EVENT_CONNECTED, NULL, 0, (err)) -#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ - LWIP_EVENT_POLL, NULL, 0, ERR_OK) -#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \ - LWIP_EVENT_ERR, NULL, 0, (err)) +#define TCP_EVENT_POLL(pcb,ret) do { if ((pcb)->state != SYN_RCVD) { \ + ret = lwip_tcp_event((pcb)->callback_arg, (pcb), LWIP_EVENT_POLL, NULL, 0, ERR_OK); \ + } else { \ + ret = ERR_ARG; } } while(0) +#define TCP_EVENT_ERR(last_state,errf,arg,err) do { if (last_state != SYN_RCVD) { \ + lwip_tcp_event((arg), NULL, LWIP_EVENT_ERR, NULL, 0, (err)); } } while(0) #else /* LWIP_EVENT_API */ @@ -223,8 +225,9 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb); else (ret) = ERR_OK; \ } while (0) -#define TCP_EVENT_ERR(errf,arg,err) \ +#define TCP_EVENT_ERR(last_state,errf,arg,err) \ do { \ + LWIP_UNUSED_ARG(last_state); \ if((errf) != NULL) \ (errf)((arg),(err)); \ } while (0)