diff --git a/CHANGELOG b/CHANGELOG index 77f898c8..b6cad20b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,7 +6,7 @@ HISTORY ++ New features: - 2015-02-22: patch by TabascoEye + 2015-02-26: patch by TabascoEye * netif.c, udp.h/.c: fixed bug #40753 (re-bind UDP pcbs on change of IP address) 2015-02-22: chrysn, Simon Goldschmidt @@ -205,6 +205,10 @@ HISTORY ++ Bugfixes: + 2015-02-26: Simon Goldschmidt + * netif.c, tcp.h/.c: fixed bug #44378 (TCP connections are not aborted on netif + remove) + 2015-02-25: Simon Goldschmidt * ip4.c, etharp.c: fixed bug #40177 (System hangs when dealing with corrupted packets), implemented task #12357 (Ensure that malicious packets don't diff --git a/src/core/netif.c b/src/core/netif.c index 822bc836..2d556a5f 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -297,6 +297,13 @@ netif_remove(struct netif *netif) return; } + if (!ip_addr_isany(&netif->ip_addr)) { +#if LWIP_TCP + tcp_netif_ipv4_addr_changed(&netif->ip_addr, NULL); +#endif /* LWIP_TCP */ + /* cannot do this for UDP, as there is no 'err' callback in udp pcbs */ + } + #if LWIP_IGMP /* stop IGMP processing */ if (netif->flags & NETIF_FLAG_IGMP) { @@ -314,27 +321,28 @@ netif_remove(struct netif *netif) snmp_delete_ipaddridx_tree(netif); - /* is it the first netif? */ - if (netif_list == netif) { - netif_list = netif->next; - } else { - /* look for netif further down the list */ - struct netif * tmpNetif; - for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) { - if (tmpNetif->next == netif) { - tmpNetif->next = netif->next; - break; - } - } - if (tmpNetif == NULL) - return; /* we didn't find any netif today */ - } - snmp_dec_iflist(); /* this netif is default? */ if (netif_default == netif) { /* reset default netif */ netif_set_default(NULL); } + /* is it the first netif? */ + if (netif_list == netif) { + netif_list = netif->next; + } else { + /* look for netif further down the list */ + struct netif * tmp_netif; + for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) { + if (tmp_netif->next == netif) { + tmp_netif->next = netif->next; + break; + } + } + if (tmp_netif == NULL) { + return; /* netif is not on the list */ + } + } + snmp_dec_iflist(); #if LWIP_NETIF_REMOVE_CALLBACK if (netif->remove_callback) { netif->remove_callback(netif); @@ -385,45 +393,11 @@ netif_find(char *name) void netif_set_ipaddr(struct netif *netif, const ip_addr_t *ipaddr) { - /* TODO: Handling of obsolete pcbs */ - /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ -#if LWIP_TCP - struct tcp_pcb *pcb; - struct tcp_pcb_listen *lpcb; -#endif /* LWIP_TCP */ - /* address is actually being changed? */ if (ipaddr && (ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) { -#if LWIP_TCP - /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); - pcb = tcp_active_pcbs; - while (pcb != NULL) { - /* PCB bound to current local interface address? */ - if (ip_addr_cmp(ipX_2_ip(&pcb->local_ip), &(netif->ip_addr)) -#if LWIP_AUTOIP - /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ - && !ip_addr_islinklocal(ipX_2_ip(&pcb->local_ip)) -#endif /* LWIP_AUTOIP */ - ) { - /* this connection must be aborted */ - struct tcp_pcb *next = pcb->next; - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); - tcp_abort(pcb); - pcb = next; - } else { - pcb = pcb->next; - } - } - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { - /* PCB bound to current local interface address? */ - if ((!(ip_addr_isany(ipX_2_ip(&lpcb->local_ip)))) && - (ip_addr_cmp(ipX_2_ip(&lpcb->local_ip), &(netif->ip_addr)))) { - /* The PCB is listening to the old ipaddr and - * is set to listen to the new one instead */ - ip_addr_set(ipX_2_ip(&lpcb->local_ip), ipaddr); - } - } +#if LWIP_TCP + tcp_netif_ipv4_addr_changed(&netif->ip_addr, ipaddr); #endif /* LWIP_TCP */ #if LWIP_UDP udp_netif_ipv4_addr_changed(&netif->ip_addr, ipaddr); @@ -431,11 +405,11 @@ netif_set_ipaddr(struct netif *netif, const ip_addr_t *ipaddr) } snmp_delete_ipaddridx_tree(netif); - snmp_delete_iprteidx_tree(0,netif); + snmp_delete_iprteidx_tree(0, netif); /* set new IP address to netif */ ip_addr_set(&(netif->ip_addr), ipaddr); snmp_insert_ipaddridx_tree(netif); - snmp_insert_iprteidx_tree(0,netif); + snmp_insert_iprteidx_tree(0, netif); LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", netif->name[0], netif->name[1], diff --git a/src/core/tcp.c b/src/core/tcp.c index 31333a51..a323a270 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -357,7 +357,7 @@ void tcp_abandon(struct tcp_pcb *pcb, int reset) { u32_t seqno, ackno; -#if LWIP_CALLBACK_API +#if LWIP_CALLBACK_API tcp_err_fn errf; #endif /* LWIP_CALLBACK_API */ void *errf_arg; @@ -1806,6 +1806,58 @@ tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest } #endif /* TCP_CALCULATE_EFF_SEND_MSS */ +/** Helper function for tcp_netif_ipv4_addr_changed() that iterates a pcb list */ +static void +tcp_netif_ipv4_addr_changed_pcblist(const ip_addr_t* old_addr, struct tcp_pcb* pcb_list) +{ + struct tcp_pcb *pcb; + pcb = pcb_list; + while (pcb != NULL) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(ipX_2_ip(&pcb->local_ip), old_addr) +#if LWIP_AUTOIP + /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ + && !ip_addr_islinklocal(ipX_2_ip(&pcb->local_ip)) +#endif /* LWIP_AUTOIP */ + ) { + /* this connection must be aborted */ + struct tcp_pcb *next = pcb->next; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); + tcp_abort(pcb); + pcb = next; + } else { + pcb = pcb->next; + } + } +} + +/** This function is called from netif.c when address is changed or netif is removed + * + * @param old_addr IPv4 address of the netif before change + * @param new_addr IPv4 address of the netif after change or NULL if netif has been removed + */ +void tcp_netif_ipv4_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) +{ + struct tcp_pcb_listen *lpcb, *next; + + tcp_netif_ipv4_addr_changed_pcblist(old_addr, tcp_active_pcbs); + tcp_netif_ipv4_addr_changed_pcblist(old_addr, tcp_bound_pcbs); + + /* PCB bound to current local interface address? */ + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) { + next = lpcb->next; + /* PCB bound to current local interface address? */ + if ((!(ip_addr_isany(ipX_2_ip(&lpcb->local_ip)))) && + (ip_addr_cmp(ipX_2_ip(&lpcb->local_ip), old_addr))) { + if (new_addr != NULL) { + /* The PCB is listening to the old ipaddr and + * is set to listen to the new one instead */ + ip_addr_set(ipX_2_ip(&lpcb->local_ip), new_addr); + } + } + } +} + const char* tcp_debug_state_str(enum tcp_state s) { @@ -1922,7 +1974,7 @@ tcp_debug_print_pcbs(void) pcb->local_port, pcb->remote_port, pcb->snd_nxt, pcb->rcv_nxt)); tcp_debug_print_state(pcb->state); - } + } } /** diff --git a/src/include/lwip/tcp_impl.h b/src/include/lwip/tcp_impl.h index f3e9470c..ada8b2c3 100644 --- a/src/include/lwip/tcp_impl.h +++ b/src/include/lwip/tcp_impl.h @@ -533,6 +533,7 @@ s16_t tcp_pcbs_sane(void); * that a timer is needed (i.e. active- or time-wait-pcb found). */ void tcp_timer_needed(void); +void tcp_netif_ipv4_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); #ifdef __cplusplus }