diff --git a/llarp/net/ip.cpp b/llarp/net/ip.cpp index 33c4b022d..38123fc29 100644 --- a/llarp/net/ip.cpp +++ b/llarp/net/ip.cpp @@ -196,11 +196,11 @@ namespace llarp #undef SUB32CS static void - deltaChecksumIPv4TCP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz, - size_t fragoff, size_t chksumoff, nuint32_t oSrcIP, - nuint32_t oDstIP, nuint32_t nSrcIP, nuint32_t nDstIP) + deltaChecksumIPv4TCP(byte_t *pld, size_t psz, size_t fragoff, + size_t chksumoff, nuint32_t oSrcIP, nuint32_t oDstIP, + nuint32_t nSrcIP, nuint32_t nDstIP) { - if(fragoff > chksumoff) + if(fragoff > chksumoff || psz < chksumoff - fragoff + 2) return; auto check = (nuint16_t *)(pld + chksumoff - fragoff); @@ -215,12 +215,12 @@ namespace llarp } static void - deltaChecksumIPv6TCP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz, - size_t fragoff, size_t chksumoff, - const uint32_t oSrcIP[4], const uint32_t oDstIP[4], - const uint32_t nSrcIP[4], const uint32_t nDstIP[4]) + deltaChecksumIPv6TCP(byte_t *pld, size_t psz, size_t fragoff, + size_t chksumoff, const uint32_t oSrcIP[4], + const uint32_t oDstIP[4], const uint32_t nSrcIP[4], + const uint32_t nDstIP[4]) { - if(fragoff > chksumoff) + if(fragoff > chksumoff || psz < chksumoff - fragoff + 2) return; auto check = (nuint16_t *)(pld + chksumoff - fragoff); @@ -235,11 +235,11 @@ namespace llarp } static void - deltaChecksumIPv4UDP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz, - size_t fragoff, nuint32_t oSrcIP, nuint32_t oDstIP, - nuint32_t nSrcIP, nuint32_t nDstIP) + deltaChecksumIPv4UDP(byte_t *pld, size_t psz, size_t fragoff, + nuint32_t oSrcIP, nuint32_t oDstIP, nuint32_t nSrcIP, + nuint32_t nDstIP) { - if(fragoff > 6) + if(fragoff > 6 || psz < 6 + 2) return; auto check = (nuint16_t *)(pld + 6); @@ -258,12 +258,11 @@ namespace llarp } static void - deltaChecksumIPv6UDP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz, - size_t fragoff, const uint32_t oSrcIP[4], - const uint32_t oDstIP[4], const uint32_t nSrcIP[4], - const uint32_t nDstIP[4]) + deltaChecksumIPv6UDP(byte_t *pld, size_t psz, size_t fragoff, + const uint32_t oSrcIP[4], const uint32_t oDstIP[4], + const uint32_t nSrcIP[4], const uint32_t nDstIP[4]) { - if(fragoff > 6) + if(fragoff > 6 || psz < 6 + 2) return; auto check = (nuint16_t *)(pld + 6); @@ -337,7 +336,7 @@ namespace llarp void IPPacket::UpdateIPv6Address(huint128_t src, huint128_t dst) { - const size_t ihs = 40; + const size_t ihs = 4 + 4 + 16 + 16; // XXX should've been checked at upper level? if(sz <= ihs) @@ -357,11 +356,55 @@ namespace llarp const uint32_t *nDstIP = hdr->dstaddr.s6_addr32; // TODO IPv6 header options - auto pld = buf + ihs; - auto psz = sz - ihs; - const size_t fragoff = 0; + auto pld = buf + ihs; + auto psz = sz - ihs; - switch(hdr->proto) + size_t fragoff = 0; + auto nextproto = hdr->proto; + for(;;) + { + switch(nextproto) + { + case 0: // Hop-by-Hop Options + case 43: // Routing Header + case 60: // Destination Options + { + nextproto = pld[0]; + auto addlen = (size_t(pld[1]) + 1) * 8; + if(psz < addlen) + return; + pld += addlen; + psz -= addlen; + break; + } + + case 44: // Fragment Header + /* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Reserved | Fragment Offset |Res|M| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identification | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + nextproto = pld[0]; + fragoff = (uint16_t(pld[2]) << 8) | (uint16_t(pld[3]) & 0xFC); + if(psz < 8) + return; + pld += 8; + psz -= 8; + + // jump straight to payload processing + if(fragoff != 0) + goto endprotohdrs; + break; + + default: + goto endprotohdrs; + } + } + endprotohdrs: + + switch(nextproto) { case 6: // TCP deltaChecksumIPv6TCP(pld, psz, fragoff, 16, oSrcIP, oDstIP, nSrcIP,