From be75c483d0adae9ce786e3e2d5760f8e37005ac7 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Sun, 6 Apr 2014 20:32:37 +0200 Subject: [PATCH 1/5] Fixed bug #41787 DHCP Discovery is invalid when an IP is set to thet netif (send discover, request and decline from 'any'). Addd functions to send udp/ipv4/ipv6 packets with source address 'any' although netif has an address assigned --- CHANGELOG | 4 ++ src/core/dhcp.c | 6 +- src/core/ipv4/ip4.c | 41 ++++++++++++- src/core/ipv6/ip6.c | 32 ++++++++--- src/core/udp.c | 112 +++++++++++++++++++----------------- src/include/ipv4/lwip/ip4.h | 8 ++- src/include/ipv6/lwip/ip6.h | 2 + src/include/lwip/ip.h | 6 ++ src/include/lwip/udp.h | 6 ++ 9 files changed, 148 insertions(+), 69 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f86f5d9b..c217efb9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -100,6 +100,10 @@ HISTORY ++ Bugfixes: + 2014-04-06: Simon Goldschmidt + * dhcp.c, ip4.c/.h, ip6.c/.h, udp.c/.h, ip.h: Fixed bug #41787 DHCP Discovery + is invalid when an IP is set to thet netif. + 2014-03-14: Simon Goldschmidt * tcp_out.c: Fixed bug #36153 TCP Cheksum error if LWIP_CHECKSUM_ON_COPY=1 diff --git a/src/core/dhcp.c b/src/core/dhcp.c index 4c605212..32307461 100644 --- a/src/core/dhcp.c +++ b/src/core/dhcp.c @@ -317,7 +317,7 @@ dhcp_select(struct netif *netif) pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); /* send broadcast to any DHCP server */ - udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + udp_sendto_if_src(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); dhcp_delete_msg(dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); } else { @@ -845,7 +845,7 @@ dhcp_decline(struct netif *netif) pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); /* per section 4.4.4, broadcast DECLINE messages */ - udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + udp_sendto_if_src(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); dhcp_delete_msg(dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); } else { @@ -895,7 +895,7 @@ dhcp_discover(struct netif *netif) pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); - udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + udp_sendto_if_src(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); dhcp_delete_msg(dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); diff --git a/src/core/ipv4/ip4.c b/src/core/ipv4/ip4.c index 48d2a391..2f1da5b8 100644 --- a/src/core/ipv4/ip4.c +++ b/src/core/ipv4/ip4.c @@ -655,6 +655,43 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, u16_t optlen) { +#endif /* IP_OPTIONS_SEND */ + ip_addr_t *src_used = src; + if (dest != IP_HDRINCL) { + if (ip_addr_isany(src)) { + src_used = &netif->ip_addr; + } + } + +#if IP_OPTIONS_SEND + return ip_output_if_opt_src(p, src_used, dest, ttl, tos, proto, netif, + ip_options, optlen); +#else /* IP_OPTIONS_SEND */ + return ip_output_if_src(p, src_used, dest, ttl, tos, proto, netif); +#endif /* IP_OPTIONS_SEND */ +} + +/** + * Same as ip_output_if() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip_output_if_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip_output_if_opt_src(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if_opt() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t ip_output_if_opt_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ #endif /* IP_OPTIONS_SEND */ struct ip_hdr *iphdr; ip_addr_t dest_addr; @@ -741,8 +778,8 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, #endif /* CHECKSUM_GEN_IP_INLINE */ ++ip_id; - if (ip_addr_isany(src)) { - ip_addr_copy(iphdr->src, netif->ip_addr); + if (src == NULL) { + ip_addr_copy(iphdr->src, ip_addr_any); } else { /* src cannot be NULL here */ ip_addr_copy(iphdr->src, *src); diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c index 5ab51848..fa786e99 100644 --- a/src/core/ipv6/ip6.c +++ b/src/core/ipv6/ip6.c @@ -744,6 +744,29 @@ err_t ip6_output_if(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, u8_t hl, u8_t tc, u8_t nexth, struct netif *netif) +{ + ip6_addr_t *src_used = src; + if (dest != IP_HDRINCL) { + if (src != NULL && ip6_addr_isany(src)) { + src = ip6_select_source_address(netif, dest); + if ((src == NULL) || ip6_addr_isany(src)) { + /* No appropriate source address was found for this packet. */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + } + return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif); +} + +/** + * Same as ip6_output_if() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip6_output_if_src(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, + u8_t hl, u8_t tc, + u8_t nexth, struct netif *netif) { struct ip6_hdr *ip6hdr; ip6_addr_t dest_addr; @@ -777,15 +800,6 @@ ip6_output_if(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, if (src == NULL) { src = IP6_ADDR_ANY; } - else if (ip6_addr_isany(src)) { - src = ip6_select_source_address(netif, dest); - if ((src == NULL) || ip6_addr_isany(src)) { - /* No appropriate source address was found for this packet. */ - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); - IP6_STATS_INC(ip6.rterr); - return ERR_RTE; - } - } /* src cannot be NULL here */ ip6_addr_copy(ip6hdr->src, *src); diff --git a/src/core/udp.c b/src/core/udp.c index 986e6992..a7b24466 100644 --- a/src/core/udp.c +++ b/src/core/udp.c @@ -626,8 +626,65 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, u16_t chksum) { #endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - struct udp_hdr *udphdr; ip_addr_t *src_ip; + + /* PCB local address is IP_ANY_ADDR? */ +#if LWIP_IPV6 + if (PCB_ISIPV6(pcb)) { + if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) { + src_ip = ip6_2_ip(ip6_select_source_address(netif, ip_2_ip6(dst_ip))); + if (src_ip == NULL) { + /* No suitable source address was found. */ + return ERR_RTE; + } + } else { + /* use UDP PCB local IPv6 address as source address, if still valid. */ + if (netif_get_ip6_addr_match(netif, ipX_2_ip6(&pcb->local_ip)) < 0) { + /* Address isn't valid anymore. */ + return ERR_RTE; + } + src_ip = ipX_2_ip(&pcb->local_ip); + } + } + else +#endif /* LWIP_IPV6 */ + if (ip_addr_isany(ipX_2_ip(&pcb->local_ip))) { + /* use outgoing network interface IP address as source address */ + src_ip = &(netif->ip_addr); + } else { + /* check if UDP PCB local IP address is correct + * this could be an old address if netif->ip_addr has changed */ + if (!ip_addr_cmp(ipX_2_ip(&(pcb->local_ip)), &(netif->ip_addr))) { + /* local_ip doesn't match, drop the packet */ + return ERR_VAL; + } + /* use UDP PCB local IP address as source address */ + src_ip = ipX_2_ip(&(pcb->local_ip)); + } +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum, src_ip); +#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + return udp_sendto_if_src(pcb, p, dst_ip, dst_port, netif, src_ip); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +} + +/** Same as udp_sendto_if(), but with source address */ +err_t +udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, ip_addr_t *src_ip) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0, src_ip); +} + +/** Same as udp_sendto_if_src(), but with checksum */ +err_t +udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum, ip_addr_t *src_ip) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + struct udp_hdr *udphdr; err_t err; struct pbuf *q; /* q will be sent down the stack */ u8_t ip_proto; @@ -704,57 +761,6 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, } #endif /* LWIP_IGMP */ - - /* PCB local address is IP_ANY_ADDR? */ -#if LWIP_IPV6 - if (PCB_ISIPV6(pcb)) { - if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) { - src_ip = ip6_2_ip(ip6_select_source_address(netif, ip_2_ip6(dst_ip))); - if (src_ip == NULL) { - /* No suitable source address was found. */ - if (q != p) { - /* free the header pbuf */ - pbuf_free(q); - /* p is still referenced by the caller, and will live on */ - } - return ERR_RTE; - } - } else { - /* use UDP PCB local IPv6 address as source address, if still valid. */ - if (netif_get_ip6_addr_match(netif, ipX_2_ip6(&pcb->local_ip)) < 0) { - /* Address isn't valid anymore. */ - if (q != p) { - /* free the header pbuf */ - pbuf_free(q); - /* p is still referenced by the caller, and will live on */ - } - return ERR_RTE; - } - src_ip = ipX_2_ip(&pcb->local_ip); - } - } - else -#endif /* LWIP_IPV6 */ - if (ip_addr_isany(ipX_2_ip(&pcb->local_ip))) { - /* use outgoing network interface IP address as source address */ - src_ip = &(netif->ip_addr); - } else { - /* check if UDP PCB local IP address is correct - * this could be an old address if netif->ip_addr has changed */ - if (!ip_addr_cmp(ipX_2_ip(&(pcb->local_ip)), &(netif->ip_addr))) { - /* local_ip doesn't match, drop the packet */ - if (q != p) { - /* free the header pbuf */ - pbuf_free(q); - q = NULL; - /* p is still referenced by the caller, and will live on */ - } - return ERR_VAL; - } - /* use UDP PCB local IP address as source address */ - src_ip = ipX_2_ip(&(pcb->local_ip)); - } - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); #if LWIP_UDPLITE @@ -840,7 +846,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto)); /* output to IP */ NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ipX_output_if(PCB_ISIPV6(pcb), q, src_ip, dst_ip, pcb->ttl, pcb->tos, ip_proto, netif); + err = ipX_output_if_src(PCB_ISIPV6(pcb), q, src_ip, dst_ip, pcb->ttl, pcb->tos, ip_proto, netif); NETIF_SET_HWADDRHINT(netif, NULL); /* TODO: must this be increased even if error occured? */ diff --git a/src/include/ipv4/lwip/ip4.h b/src/include/ipv4/lwip/ip4.h index 04b5b8a6..e1728357 100644 --- a/src/include/ipv4/lwip/ip4.h +++ b/src/include/ipv4/lwip/ip4.h @@ -117,8 +117,9 @@ err_t ip_input(struct pbuf *p, struct netif *inp); err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t ttl, u8_t tos, u8_t proto); err_t ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, - struct netif *netif); + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); +err_t ip_output_if_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); #if LWIP_NETIF_HWADDRHINT err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); @@ -127,6 +128,9 @@ err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, u16_t optlen); +err_t ip_output_if_opt_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); #endif /* IP_OPTIONS_SEND */ #define ip_netif_get_local_ipX(netif) (((netif) != NULL) ? ip_2_ipX(&((netif)->ip_addr)) : NULL) diff --git a/src/include/ipv6/lwip/ip6.h b/src/include/ipv6/lwip/ip6.h index ac32ceec..5ab61c3c 100644 --- a/src/include/ipv6/lwip/ip6.h +++ b/src/include/ipv6/lwip/ip6.h @@ -169,6 +169,8 @@ err_t ip6_output(struct pbuf *p, struct ip6_addr *src, struct ip6_addr * u8_t hl, u8_t tc, u8_t nexth); err_t ip6_output_if(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest, u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); +err_t ip6_output_if_src(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest, + u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); #if LWIP_NETIF_HWADDRHINT err_t ip6_output_hinted(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint); diff --git a/src/include/lwip/ip.h b/src/include/lwip/ip.h index a0cd1d4d..5d34e9bc 100644 --- a/src/include/lwip/ip.h +++ b/src/include/lwip/ip.h @@ -213,6 +213,10 @@ extern struct ip_globals ip_data; ((isipv6) ? \ ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ ip_output_if(p, (src), (dest), ttl, tos, proto, netif)) +#define ipX_output_if_src(isipv6, p, src, dest, ttl, tos, proto, netif) \ + ((isipv6) ? \ + ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ + ip_output_if_src(p, (src), (dest), ttl, tos, proto, netif)) #define ipX_output_hinted(isipv6, p, src, dest, ttl, tos, proto, addr_hint) \ ((isipv6) ? \ ip6_output_hinted(p, ipX_2_ip6(src), ipX_2_ip6(dest), ttl, tos, proto, addr_hint) : \ @@ -231,6 +235,8 @@ extern struct ip_globals ip_data; ip_output(p, src, dest, ttl, tos, proto) #define ipX_output_if(isipv6, p, src, dest, ttl, tos, proto, netif) \ ip_output_if(p, src, dest, ttl, tos, proto, netif) +#define ipX_output_if_src(isipv6, p, src, dest, ttl, tos, proto, netif) \ + ip_output_if_src(p, src, dest, ttl, tos, proto, netif) #define ipX_output_hinted(isipv6, p, src, dest, ttl, tos, proto, addr_hint) \ ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) #define ipX_route(isipv6, src, dest) \ diff --git a/src/include/lwip/udp.h b/src/include/lwip/udp.h index 14d5c0ae..93c72b79 100644 --- a/src/include/lwip/udp.h +++ b/src/include/lwip/udp.h @@ -156,6 +156,9 @@ void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif); +err_t udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, ip_addr_t *src_ip); err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, u16_t dst_port); err_t udp_send (struct udp_pcb *pcb, struct pbuf *p); @@ -170,6 +173,9 @@ err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, u8_t have_chksum, u16_t chksum); err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, u8_t have_chksum, u16_t chksum); +err_t udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, + u8_t have_chksum, u16_t chksum, ip_addr_t *src_ip); #endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ #define udp_flags(pcb) ((pcb)->flags) From 3f016fcc5a5d9dbce9eb62e5c7b8b2ab03453aea Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Sun, 6 Apr 2014 21:43:37 +0200 Subject: [PATCH 2/5] Multiple small/minor issues: bug #36492 Static Analysis on code 1.4.0 --- src/api/api_msg.c | 9 ++++++--- src/api/tcpip.c | 5 +++++ src/core/dhcp.c | 2 +- src/core/ipv4/ip_frag.c | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/api/api_msg.c b/src/api/api_msg.c index f39d7359..f3e4f9a3 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -1235,9 +1235,8 @@ lwip_netconn_do_writemore(struct netconn *conn) u16_t len, available; u8_t write_finished = 0; size_t diff; - u8_t dontblock = netconn_is_nonblocking(conn) || - (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK); - u8_t apiflags = conn->current_msg->msg.w.apiflags; + u8_t dontblock; + u8_t apiflags; LWIP_ASSERT("conn != NULL", conn != NULL); LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); @@ -1246,6 +1245,10 @@ lwip_netconn_do_writemore(struct netconn *conn) LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", conn->write_offset < conn->current_msg->msg.w.len); + dontblock = netconn_is_nonblocking(conn) || + (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK); + apiflags = conn->current_msg->msg.w.apiflags; + #if LWIP_SO_SNDTIMEO if ((conn->send_timeout != 0) && ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { diff --git a/src/api/tcpip.c b/src/api/tcpip.c index 31e7c924..06ff3c79 100644 --- a/src/api/tcpip.c +++ b/src/api/tcpip.c @@ -93,6 +93,11 @@ tcpip_thread(void *arg) /* wait for a message, timeouts are processed while waiting */ sys_timeouts_mbox_fetch(&mbox, (void **)&msg); LOCK_TCPIP_CORE(); + if (msg == NULL) { + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); + LWIP_ASSERT("tcpip_thread: invalid message", 0); + continue; + } switch (msg->type) { #if LWIP_NETCONN case TCPIP_MSG_API: diff --git a/src/core/dhcp.c b/src/core/dhcp.c index 32307461..28c594d9 100644 --- a/src/core/dhcp.c +++ b/src/core/dhcp.c @@ -1563,7 +1563,7 @@ dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t goto free_pbuf_and_return; } /* iterate through hardware address and match against DHCP message */ - for (i = 0; i < netif->hwaddr_len; i++) { + for (i = 0; i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN && i < DHCP_CHADDR_LEN; i++) { if (netif->hwaddr[i] != reply_msg->chaddr[i]) { LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", diff --git a/src/core/ipv4/ip_frag.c b/src/core/ipv4/ip_frag.c index 1b549834..8bf8141f 100644 --- a/src/core/ipv4/ip_frag.c +++ b/src/core/ipv4/ip_frag.c @@ -423,7 +423,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct if (valid) { /* then check if the rest of the fragments is here */ /* Check if the queue starts with the first datagram */ - if (((struct ip_reass_helper*)ipr->p->payload)->start != 0) { + if ((ipr->p == NULL) || (((struct ip_reass_helper*)ipr->p->payload)->start != 0)) { valid = 0; } else { /* and check that there are no wholes after this datagram */ From 4c3b6814dc69ff975c968d528ca8a3e5a60f9818 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Sun, 6 Apr 2014 22:33:27 +0200 Subject: [PATCH 3/5] Fixed compiling broken ip6.c after last commit --- src/core/ipv6/ip6.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c index fa786e99..cdace5c5 100644 --- a/src/core/ipv6/ip6.c +++ b/src/core/ipv6/ip6.c @@ -755,6 +755,7 @@ ip6_output_if(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, IP6_STATS_INC(ip6.rterr); return ERR_RTE; } + } } return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif); } From 035ecef8a540e0efefa0bfcd59816ab293c51242 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Sun, 6 Apr 2014 22:40:51 +0200 Subject: [PATCH 4/5] Fixed bug #36210 lwIP does not elicit an empty ACK when received unacceptable ACK --- CHANGELOG | 4 ++++ src/core/tcp_in.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index c217efb9..f3015a80 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -100,6 +100,10 @@ HISTORY ++ Bugfixes: + 2014-04-06: Simon Goldschmidt + * tcp_in.c: Fixed bug #36210 lwIP does not elicit an empty ACK when received + unacceptable ACK + 2014-04-06: Simon Goldschmidt * dhcp.c, ip4.c/.h, ip6.c/.h, udp.c/.h, ip.h: Fixed bug #41787 DHCP Discovery is invalid when an IP is set to thet netif. diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index bf921a84..d3b8a126 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -1112,8 +1112,9 @@ tcp_receive(struct tcp_pcb *pcb) } #endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ } else { - /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */ + /* Out of sequence ACK, didn't really ack anything */ pcb->acked = 0; + tcp_send_empty_ack(pcb); } /* We go through the ->unsent list to see if any of the segments From 88a57dc98d9793d74f8e1c52729b50188d5a0b4f Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Tue, 8 Apr 2014 21:26:27 +0200 Subject: [PATCH 5/5] Fixed bug #36167 tcp server crash when client closes (maximum window) --- CHANGELOG | 3 +++ src/core/tcp.c | 12 ++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f3015a80..8736ecc5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -100,6 +100,9 @@ HISTORY ++ Bugfixes: + 2014-04-08: Simon Goldschmidt + * tcp.c: Fixed bug #36167 tcp server crash when client closes (maximum window) + 2014-04-06: Simon Goldschmidt * tcp_in.c: Fixed bug #36210 lwIP does not elicit an empty ACK when received unacceptable ACK diff --git a/src/core/tcp.c b/src/core/tcp.c index 1af3d6b3..cdd08aef 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -650,12 +650,20 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len) /* pcb->state LISTEN not allowed here */ LWIP_ASSERT("don't call tcp_recved for listen-pcbs", pcb->state != LISTEN); - LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n", - len <= TCPWND_MAX - pcb->rcv_wnd); pcb->rcv_wnd += len; if (pcb->rcv_wnd > TCP_WND) { pcb->rcv_wnd = TCP_WND; + } else if(pcb->rcv_wnd == 0) { + /* rcv_wnd overflowed */ + if ((pcb->state == CLOSE_WAIT) || (pcb->state == LAST_ACK)) { + /* In passive close, we allow this, since the FIN bit is added to rcv_wnd + by the stack itself, since it is not mandatory for an application + to call tcp_recved() for the FIN bit, but e.g. the netconn API does so. */ + pcb->rcv_wnd = TCP_WND; + } else { + LWIP_ASSERT("tcp_recved: len wrapped rcv_wnd\n", 0); + } } wnd_inflation = tcp_update_rcv_ann_wnd(pcb);