There is a problem that when an active open request (connect()) changes state from SYN_SENT to SYN_RECEIVED and the TCB is closed on error (perhaps due to send timeout) the connect request is not removed from the OPENS list. So the TCB closes, but the request stays in the OPENS list, TCP_PARM in next connect() has the same address (as it would be when TCP_PARM is on stack) we have the problem. The same issue would occur if application request closes the connecting socket (connect() in SYN_RECEIVED state).
What can help - make sure the TCB, that is being deallocated, is not left in the OPENS list - lines 62-95:
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TCP_Free_TCB
* Returned Values : None.
* Comments :
*
* Deallocate TCB; must only be done when TCB has been closed and released.
*
*END*-----------------------------------------------------------------*/
void TCP_Free_TCB
(
TCB_STRUCT_PTR tcb, /* IN/OUT - TCP context */
TCP_CFG_STRUCT_PTR tcp_cfg /* IN/OUT - TCP layer data */
)
{ /* Body */
TCB_STRUCT_PTR tmp;
if(NULL==tcb) return;
/*
** Free everything which wasn't freed in TCP_Close_TCB() ...
*/
TCP_Truncate_receive_chunks(tcb, tcp_cfg, tcb->rcvlen); /* delete all chunk nodes */
if ( tcb->rcvringbuf != NULL ) {
_mem_free(tcb->rcvringbuf);
tcb->rcvringbuf = NULL;
} /* Endif */
/*
** Deallocate TCB itself
*/
if ( tcb != NULL ) {
if ( tcb == tcp_cfg->TCBhead ) {
tcp_cfg->TCBhead = tcb->next;
} else {
tmp = tcp_cfg->TCBhead;
while ( tmp != NULL && tmp->next != tcb ) {
tmp = tmp->next;
} /* Endwhile */
if ( tmp != NULL ) {
tmp->next = tcb->next;
} /* Endif */
} /* Endif */
} /* Endif */
if (tcb->SOCKET) {
((SOCKET_STRUCT_PTR)tcb->SOCKET)->TCB_PTR = NULL;
} /* Endif */
tcb->VALID = TCB_INVALID_ID;
tcp_cfg->CONN_COUNT--;
#if RTCSCFG_TCP_MAX_HALF_OPEN
TCB_HALF_OPEN_DROP
#endif
_mem_free(tcb);
/* double check OPENS list.
* if the tcb is in OPENS list now, just return with error,
* so that application is aware.
* normally it should not happen, as accept()/connect() request
* if removed from OPENS list during ESTABLISHED and FINWAIT_1 states.
*/
{
TCP_PARM_PTR req_ptr; /* upper layer request */
TCP_PARM_PTR prev_ptr; /* previous upper layer request */
prev_ptr = NULL;
req_ptr = tcp_cfg->OPENS;
while (req_ptr != NULL &&
tcb != req_ptr->TCB_PTR)
{
prev_ptr = req_ptr;
req_ptr = req_ptr->NEXT;
}
if (req_ptr != NULL)
{
if (prev_ptr == NULL)
{
tcp_cfg->OPENS = req_ptr->NEXT;
}
else
{
prev_ptr->NEXT = req_ptr->NEXT;
} /* Endif */
req_ptr->NEXT = NULL;
req_ptr->TCB_PTR = tcb;
RTCSCMD_complete(req_ptr, RTCSERR_TCP_CONN_RLSD);
}
}
} /* Endbody */