diff --git a/src/core/ipv6/ip6_frag.c b/src/core/ipv6/ip6_frag.c index e97e9524..3deedddf 100644 --- a/src/core/ipv6/ip6_frag.c +++ b/src/core/ipv6/ip6_frag.c @@ -181,7 +181,7 @@ ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) } clen = pbuf_clen(p); LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; + pbufs_freed = (u16_t)(pbufs_freed + clen); pbuf_free(p); } #endif /* LWIP_ICMP6 */ @@ -197,7 +197,7 @@ ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) p = iprh->next_pbuf; clen = pbuf_clen(pcur); LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; + pbufs_freed = (u16_t)(pbufs_freed + clen); pbuf_free(pcur); } @@ -220,7 +220,7 @@ ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) /* Finally, update number of pbufs in reassembly queue */ LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed); - ip6_reass_pbufcount -= pbufs_freed; + ip6_reass_pbufcount = (u16_t)(ip6_reass_pbufcount - pbufs_freed); } #if IP_REASS_FREE_OLDEST @@ -275,6 +275,7 @@ ip6_reass(struct pbuf *p) struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; struct ip6_frag_hdr *frag_hdr; u16_t offset, len, start, end; + ptrdiff_t hdrdiff; u16_t clen; u8_t valid = 1; struct pbuf *q, *next_pbuf; @@ -295,8 +296,24 @@ ip6_reass(struct pbuf *p) * Adjust for headers before Fragment Header. * And finally adjust by Fragment Header length. */ len = lwip_ntohs(ip6_current_header()->_plen); - len -= (u16_t)(((u8_t*)p->payload - (const u8_t*)ip6_current_header()) - IP6_HLEN); - len -= IP6_FRAG_HLEN; + hdrdiff = (u8_t*)p->payload - (const u8_t*)ip6_current_header(); + LWIP_ASSERT("not a valid pbuf (ip6_input check missing?)", hdrdiff <= 0xFFFF); + LWIP_ASSERT("not a valid pbuf (ip6_input check missing?)", hdrdiff >= IP6_HLEN); + hdrdiff -= IP6_HLEN; + hdrdiff += IP6_FRAG_HLEN; + if (hdrdiff > len) { + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + len = (u16_t)(len - hdrdiff); + start = (offset & IP6_FRAG_OFFSET_MASK); + if (start > (0xFFFF - len)) { + /* u16_t overflow, cannot handle this */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } /* Look for the datagram the fragment belongs to in the current datagram queue, * remembering the previous in the queue for later dequeueing. */ @@ -412,8 +429,7 @@ ip6_reass(struct pbuf *p) * sure that we are going to add this packet to the list. */ iprh = (struct ip6_reass_helper *)p->payload; next_pbuf = NULL; - start = (offset & IP6_FRAG_OFFSET_MASK); - end = (offset & IP6_FRAG_OFFSET_MASK) + len; + end = (u16_t)(start + len); /* find the right place to insert this pbuf */ /* Iterate through until we either get to the end of the list (append), @@ -496,7 +512,7 @@ ip6_reass(struct pbuf *p) /* Track the current number of pbufs current 'in-flight', in order to limit the number of fragments that may be enqueued at any one time */ - ip6_reass_pbufcount += clen; + ip6_reass_pbufcount = (u16_t)(ip6_reass_pbufcount + clen); /* Remember IPv6 header if this is the first fragment. */ if (start == 0) { @@ -599,14 +615,14 @@ ip6_reass(struct pbuf *p) * of the chain, and because the caller adjusts all its pointers on * successful reassembly. */ MEMMOVE((u8_t*)ipr->iphdr + sizeof(struct ip6_frag_hdr), ipr->iphdr, - (u8_t*)p->payload - (u8_t*)ipr->iphdr); + (size_t)((u8_t*)p->payload - (u8_t*)ipr->iphdr)); /* This is where the IPv6 header is now. */ iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->iphdr + sizeof(struct ip6_frag_hdr)); /* Adjust datagram length by adding header lengths. */ - ipr->datagram_len += (u16_t)(((u8_t*)p->payload - (u8_t*)iphdr_ptr) + ipr->datagram_len = (u16_t)(ipr->datagram_len + ((u8_t*)p->payload - (u8_t*)iphdr_ptr) - IP6_HLEN); /* Set payload length in ip header. */ @@ -638,7 +654,9 @@ ip6_reass(struct pbuf *p) memp_free(MEMP_IP6_REASSDATA, ipr); /* adjust the number of pbufs currently queued for reassembly. */ - ip6_reass_pbufcount -= pbuf_clen(p); + clen = pbuf_clen(p); + LWIP_ASSERT("ip6_reass_pbufcount >= clen", ip6_reass_pbufcount >= clen); + ip6_reass_pbufcount = (u16_t)(ip6_reass_pbufcount - clen); /* Move pbuf back to IPv6 header. This should never fail. */ if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)iphdr_ptr))) { @@ -718,9 +736,9 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) u16_t left_to_copy; #endif static u32_t identification; - u16_t nfb; u16_t left, cop; - u16_t mtu; + const u16_t mtu = nd6_get_destination_mtu(dest, netif); + const u16_t nfb = (u16_t)((mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK); u16_t fragment_offset = 0; u16_t last; u16_t poff = IP6_HLEN; @@ -729,12 +747,9 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) original_ip6hdr = (struct ip6_hdr *)p->payload; - mtu = nd6_get_destination_mtu(dest, netif); - /* @todo we assume there are no options in the unfragmentable part (IPv6 header). */ - left = p->tot_len - IP6_HLEN; - - nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK; + LWIP_ASSERT("p->tot_len >= IP6_HLEN", p->tot_len >= IP6_HLEN); + left = (u16_t)(p->tot_len - IP6_HLEN); while (left) { last = (left <= nfb); @@ -780,8 +795,8 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) /* Can just adjust p directly for needed offset. */ p->payload = (u8_t *)p->payload + poff; - p->len -= poff; - p->tot_len -= poff; + p->len = (u16_t)(p->len - poff); + p->tot_len = (u16_t)(p->tot_len - poff); left_to_copy = cop; while (left_to_copy) { @@ -814,7 +829,7 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) * so that it is removed when pbuf_dechain is later called on rambuf. */ pbuf_cat(rambuf, newpbuf); - left_to_copy -= newpbuflen; + left_to_copy = (u16_t)(left_to_copy - newpbuflen); if (left_to_copy) { p = p->next; } @@ -825,11 +840,11 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) /* Set headers */ frag_hdr->_nexth = original_ip6hdr->_nexth; frag_hdr->reserved = 0; - frag_hdr->_fragment_offset = lwip_htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); + frag_hdr->_fragment_offset = lwip_htons((u16_t)((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG))); frag_hdr->_identification = lwip_htonl(identification); IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT); - IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN); + IP6H_PLEN_SET(ip6hdr, (u16_t)(cop + IP6_FRAG_HLEN)); /* No need for separate header pbuf - we allowed room for it in rambuf * when allocated. @@ -845,8 +860,8 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) */ pbuf_free(rambuf); - left -= cop; - fragment_offset += cop; + left = (u16_t)(left - cop); + fragment_offset = (u16_t)(fragment_offset + cop); } return ERR_OK; } diff --git a/src/core/ipv6/mld6.c b/src/core/ipv6/mld6.c index 7400a2af..69aa7a8b 100644 --- a/src/core/ipv6/mld6.c +++ b/src/core/ipv6/mld6.c @@ -509,20 +509,20 @@ mld6_tmr(void) * * @param group the mld_group for which "delaying" membership report * should be sent - * @param maxresp the max resp delay provided in the query + * @param maxresp_in the max resp delay provided in the query */ static void -mld6_delayed_report(struct mld_group *group, u16_t maxresp) +mld6_delayed_report(struct mld_group *group, u16_t maxresp_in) { /* Convert maxresp from milliseconds to tmr ticks */ - maxresp = maxresp / MLD6_TMR_INTERVAL; + u16_t maxresp = maxresp_in / MLD6_TMR_INTERVAL; if (maxresp == 0) { maxresp = 1; } #ifdef LWIP_RAND /* Randomize maxresp. (if LWIP_RAND is supported) */ - maxresp = LWIP_RAND() % maxresp; + maxresp = (u16_t)(LWIP_RAND() % maxresp); if (maxresp == 0) { maxresp = 1; }