From d67d1f7340b36b5bfebc56f67211501d146fcb91 Mon Sep 17 00:00:00 2001 From: adamdunkels Date: Tue, 9 Feb 2010 12:58:53 +0000 Subject: [PATCH] Major bugfix, found by Raimondas Sasnauskas: the TCP periodic timer was not started when a new connection request arrived. If there were no other active TCP connections, this means that the SYNACK would never be retransmitted, potentially leading to a forever stale TCP connection. --- core/net/tcpip.c | 51 ++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/core/net/tcpip.c b/core/net/tcpip.c index 01d98f173..21d6a9f54 100644 --- a/core/net/tcpip.c +++ b/core/net/tcpip.c @@ -29,7 +29,7 @@ * This file is part of the Contiki operating system. * * - * $Id: tcpip.c,v 1.23 2010/02/05 12:43:36 nifi Exp $ + * $Id: tcpip.c,v 1.24 2010/02/09 12:58:53 adamdunkels Exp $ */ /** * \file @@ -71,6 +71,7 @@ void uip_log(char *msg); #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN + uip_ext_len]) #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_TCP_BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) process_event_t tcpip_event; #if UIP_CONF_ICMP6 @@ -156,6 +157,29 @@ unsigned char tcpip_is_forwarding; /* Forwarding right now? */ PROCESS(tcpip_process, "TCP/IP stack"); +/*---------------------------------------------------------------------------*/ +static void +start_periodic_tcp_timer(void) +{ + if(etimer_expired(&periodic)) { + etimer_restart(&periodic); + } +} +/*---------------------------------------------------------------------------*/ +static void +check_for_tcp_syn(void) +{ + /* This is a hack that is needed to start the periodic TCP timer if + an incoming packet contains a SYN: since uIP does not inform the + application if a SYN arrives, we have no other way of starting + this timer. This function is called for every incoming IP packet + to check for such SYNs. */ +#define TCP_SYN 0x02 + if(UIP_IP_BUF->proto == UIP_PROTO_TCP && + (UIP_TCP_BUF->flags & TCP_SYN) == TCP_SYN) { + start_periodic_tcp_timer(); + } +} /*---------------------------------------------------------------------------*/ static void packet_input(void) @@ -165,6 +189,7 @@ packet_input(void) tcpip_is_forwarding = 1; if(uip_fw_forward() == UIP_FW_LOCAL) { tcpip_is_forwarding = 0; + check_for_tcp_syn(); uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT @@ -183,6 +208,7 @@ packet_input(void) } #else /* UIP_CONF_IP_FORWARD */ if(uip_len > 0) { + check_for_tcp_syn(); uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT @@ -199,12 +225,8 @@ packet_input(void) } #endif /* UIP_CONF_IP_FORWARD */ } - /*---------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ - #if UIP_TCP - #if UIP_ACTIVE_OPEN struct uip_conn * tcp_connect(uip_ipaddr_t *ripaddr, u16_t port, void *appstate) @@ -273,10 +295,7 @@ tcp_attach(struct uip_conn *conn, } #endif /* UIP_TCP */ - /*---------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ - #if UIP_UDP void udp_attach(struct uip_udp_conn *conn, @@ -349,7 +368,6 @@ tcpip_icmp6_call(u8_t type) } #endif /* UIP_CONF_ICMP6 */ /*---------------------------------------------------------------------------*/ - static void eventhandler(process_event_t ev, process_data_t data) { @@ -483,17 +501,14 @@ eventhandler(process_event_t ev, process_data_t data) uip_poll_conn(data); #if UIP_CONF_IPV6 tcpip_ipv6_output(); -#else +#else /* UIP_CONF_IPV6 */ if(uip_len > 0) { PRINTF("tcpip_output from tcp poll len %d\n", uip_len); tcpip_output(); } #endif /* UIP_CONF_IPV6 */ /* Start the periodic polling, if it isn't already active. */ - if(etimer_expired(&periodic)) { - etimer_restart(&periodic); - } - + start_periodic_tcp_timer(); } break; #endif /* UIP_TCP */ @@ -720,12 +735,10 @@ tcpip_uipcall(void) } /* Start the periodic polling, if it isn't already active. */ - if(etimer_expired(&periodic)) { - etimer_restart(&periodic); - } + start_periodic_tcp_timer(); } } -#endif +#endif /* UIP_TCP */ if(ts->p != NULL) { process_post_synch(ts->p, tcpip_event, ts->state); @@ -751,7 +764,7 @@ PROCESS_THREAD(tcpip_process, ev, data) #if UIP_CONF_ICMP6 tcpip_icmp6_event = process_alloc_event(); #endif /* UIP_CONF_ICMP6 */ - etimer_set(&periodic, CLOCK_SECOND/2); + etimer_set(&periodic, CLOCK_SECOND / 2); uip_init();