tcp: fixed bug #50418: LWIP_EVENT_API: fix invalid calbacks for SYN_RCVD pcb

This commit is contained in:
goldsimon 2017-02-28 12:13:26 +01:00
parent d3fc398580
commit f85eed0ab3
4 changed files with 19 additions and 9 deletions

View File

@ -26,6 +26,9 @@ HISTORY
++ Bugfixes: ++ 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 2017-02-24: Simon Goldschmidt
* sockets.c: fixed close race conditions in lwip_select (for LWIP_NETCONN_FULLDUPLEX) * sockets.c: fixed close race conditions in lwip_select (for LWIP_NETCONN_FULLDUPLEX)

View File

@ -482,6 +482,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
} else { } else {
int send_rst = 0; int send_rst = 0;
u16_t local_port = 0; u16_t local_port = 0;
enum tcp_state last_state;
seqno = pcb->snd_nxt; seqno = pcb->snd_nxt;
ackno = pcb->rcv_nxt; ackno = pcb->rcv_nxt;
#if LWIP_CALLBACK_API #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")); 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); 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); 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; tcp_err_fn err_fn = pcb->errf;
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
void *err_arg; void *err_arg;
enum tcp_state last_state;
tcp_pcb_purge(pcb); tcp_pcb_purge(pcb);
/* Remove PCB from tcp_active_pcbs list. */ /* Remove PCB from tcp_active_pcbs list. */
if (prev != NULL) { if (prev != NULL) {
@ -1196,12 +1199,13 @@ tcp_slowtmr_start:
} }
err_arg = pcb->callback_arg; err_arg = pcb->callback_arg;
last_state = pcb->state;
pcb2 = pcb; pcb2 = pcb;
pcb = pcb->next; pcb = pcb->next;
memp_free(MEMP_TCP_PCB, pcb2); memp_free(MEMP_TCP_PCB, pcb2);
tcp_active_pcbs_changed = 0; 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) { if (tcp_active_pcbs_changed) {
goto tcp_slowtmr_start; goto tcp_slowtmr_start;
} }

View File

@ -378,7 +378,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
end. We then call the error callback to inform the end. We then call the error callback to inform the
application that the connection is dead before we application that the connection is dead before we
deallocate the PCB. */ 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); tcp_pcb_remove(&tcp_active_pcbs, pcb);
memp_free(MEMP_TCP_PCB, pcb); memp_free(MEMP_TCP_PCB, pcb);
} else { } else {
@ -413,7 +413,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Connection closed although the application has only shut down the /* Connection closed although the application has only shut down the
tx side: call the PCB's err callback and indicate the closure to tx side: call the PCB's err callback and indicate the closure to
ensure the application doesn't continue using the PCB. */ 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); tcp_pcb_remove(&tcp_active_pcbs, pcb);
memp_free(MEMP_TCP_PCB, pcb); memp_free(MEMP_TCP_PCB, pcb);

View File

@ -170,10 +170,12 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb);
LWIP_EVENT_RECV, NULL, 0, ERR_OK) LWIP_EVENT_RECV, NULL, 0, ERR_OK)
#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ #define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
LWIP_EVENT_CONNECTED, NULL, 0, (err)) LWIP_EVENT_CONNECTED, NULL, 0, (err))
#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ #define TCP_EVENT_POLL(pcb,ret) do { if ((pcb)->state != SYN_RCVD) { \
LWIP_EVENT_POLL, NULL, 0, ERR_OK) 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, \ } else { \
LWIP_EVENT_ERR, NULL, 0, (err)) 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 */ #else /* LWIP_EVENT_API */
@ -223,8 +225,9 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb);
else (ret) = ERR_OK; \ else (ret) = ERR_OK; \
} while (0) } while (0)
#define TCP_EVENT_ERR(errf,arg,err) \ #define TCP_EVENT_ERR(last_state,errf,arg,err) \
do { \ do { \
LWIP_UNUSED_ARG(last_state); \
if((errf) != NULL) \ if((errf) != NULL) \
(errf)((arg),(err)); \ (errf)((arg),(err)); \
} while (0) } while (0)