Dangling inseg.p pointer fix by Pedro Alves.

This commit is contained in:
likewise 2006-04-08 00:13:49 +00:00
parent ef0575a26d
commit 6cb19d7e34

View File

@ -3,10 +3,10 @@
* *
* Transmission Control Protocol, incoming traffic * Transmission Control Protocol, incoming traffic
* *
* The input processing functions of TCP. * The input processing functions of the TCP layer.
* *
* These functions are generally called in the order (ip_input() ->) tcp_input() -> * These functions are generally called in the order (ip_input() ->)
* tcp_process() -> tcp_receive() (-> application). * tcp_input() -> * tcp_process() -> tcp_receive() (-> application).
* *
*/ */
@ -80,7 +80,6 @@ static void tcp_parseopt(struct tcp_pcb *pcb);
static err_t tcp_listen_input(struct tcp_pcb_listen *pcb); static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
static err_t tcp_timewait_input(struct tcp_pcb *pcb); static err_t tcp_timewait_input(struct tcp_pcb *pcb);
/* tcp_input: /* tcp_input:
* *
* The initial input processing of TCP. It verifies the TCP header, demultiplexes * The initial input processing of TCP. It verifies the TCP header, demultiplexes
@ -174,13 +173,13 @@ tcp_input(struct pbuf *p, struct netif *inp)
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) { ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
/* Move this PCB to the front of the list so that subsequent /* Move this PCB to the front of the list so that subsequent
lookups will be faster (we exploit locality in TCP segment lookups will be faster (we exploit locality in TCP segment
arrivals). */ arrivals). */
LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
if (prev != NULL) { if (prev != NULL) {
prev->next = pcb->next; prev->next = pcb->next;
pcb->next = tcp_active_pcbs; pcb->next = tcp_active_pcbs;
tcp_active_pcbs = pcb; tcp_active_pcbs = pcb;
} }
LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
break; break;
@ -191,20 +190,19 @@ tcp_input(struct pbuf *p, struct netif *inp)
if (pcb == NULL) { if (pcb == NULL) {
/* If it did not go to an active connection, we check the connections /* If it did not go to an active connection, we check the connections
in the TIME-WAIT state. */ in the TIME-WAIT state. */
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
if (pcb->remote_port == tcphdr->src && if (pcb->remote_port == tcphdr->src &&
pcb->local_port == tcphdr->dest && pcb->local_port == tcphdr->dest &&
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) && ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) { ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
/* We don't really care enough to move this PCB to the front /* We don't really care enough to move this PCB to the front
of the list since we are not very likely to receive that of the list since we are not very likely to receive that
many segments for connections in TIME-WAIT. */ many segments for connections in TIME-WAIT. */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
tcp_timewait_input(pcb); tcp_timewait_input(pcb);
pbuf_free(p); pbuf_free(p);
return; return;
} }
} }
@ -213,23 +211,23 @@ tcp_input(struct pbuf *p, struct netif *inp)
prev = NULL; prev = NULL;
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
if ((ip_addr_isany(&(lpcb->local_ip)) || if ((ip_addr_isany(&(lpcb->local_ip)) ||
ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) && ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
lpcb->local_port == tcphdr->dest) { lpcb->local_port == tcphdr->dest) {
/* Move this PCB to the front of the list so that subsequent /* Move this PCB to the front of the list so that subsequent
lookups will be faster (we exploit locality in TCP segment lookups will be faster (we exploit locality in TCP segment
arrivals). */ arrivals). */
if (prev != NULL) { if (prev != NULL) {
((struct tcp_pcb_listen *)prev)->next = lpcb->next; ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
/* our successor is the remainder of the listening list */ /* our successor is the remainder of the listening list */
lpcb->next = tcp_listen_pcbs.listen_pcbs; lpcb->next = tcp_listen_pcbs.listen_pcbs;
/* put this listening pcb at the head of the listening list */ /* put this listening pcb at the head of the listening list */
tcp_listen_pcbs.listen_pcbs = lpcb; tcp_listen_pcbs.listen_pcbs = lpcb;
} }
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
tcp_listen_input(lpcb); tcp_listen_input(lpcb);
pbuf_free(p); pbuf_free(p);
return; return;
} }
prev = (struct tcp_pcb *)lpcb; prev = (struct tcp_pcb *)lpcb;
} }
@ -267,51 +265,51 @@ tcp_input(struct pbuf *p, struct netif *inp)
and that the pcb has been freed. If so, we don't do anything. */ and that the pcb has been freed. If so, we don't do anything. */
if (err != ERR_ABRT) { if (err != ERR_ABRT) {
if (recv_flags & TF_RESET) { if (recv_flags & TF_RESET) {
/* TF_RESET means that the connection was reset by the other /* TF_RESET means that the connection was reset by the other
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->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 if (recv_flags & TF_CLOSED) { } else if (recv_flags & TF_CLOSED) {
/* The connection has been closed and we will deallocate the /* The connection has been closed and we will deallocate the
PCB. */ PCB. */
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 {
err = ERR_OK; err = ERR_OK;
/* If the application has registered a "sent" function to be /* If the application has registered a "sent" function to be
called when new send buffer space is available, we call it called when new send buffer space is available, we call it
now. */ now. */
if (pcb->acked > 0) { if (pcb->acked > 0) {
TCP_EVENT_SENT(pcb, pcb->acked, err); TCP_EVENT_SENT(pcb, pcb->acked, err);
} }
if (recv_data != NULL) { if (recv_data != NULL) {
/* Notify application that data has been received. */ /* Notify application that data has been received. */
TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
} }
/* If a FIN segment was received, we call the callback /* If a FIN segment was received, we call the callback
function with a NULL buffer to indicate EOF. */ function with a NULL buffer to indicate EOF. */
if (recv_flags & TF_GOT_FIN) { if (recv_flags & TF_GOT_FIN) {
TCP_EVENT_RECV(pcb, NULL, ERR_OK, err); TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
} }
/* If there were no errors, we try to send something out. */ /* If there were no errors, we try to send something out. */
if (err == ERR_OK) { if (err == ERR_OK) {
tcp_output(pcb); tcp_output(pcb);
} }
} }
} }
/* We deallocate the incoming pbuf. If it was buffered by the /* give up our reference to inseg.p */
application, the application should have called pbuf_ref() to if (inseg.p != NULL)
increase the reference counter in the pbuf. If so, the buffer {
isn't actually deallocated by the call to pbuf_free(), only the pbuf_free(inseg.p);
reference count is decreased. */ inseg.p = NULL;
if (inseg.p != NULL) pbuf_free(inseg.p); }
#if TCP_INPUT_DEBUG #if TCP_INPUT_DEBUG
#if TCP_DEBUG #if TCP_DEBUG
tcp_debug_print_state(pcb->state); tcp_debug_print_state(pcb->state);