-
Notifications
You must be signed in to change notification settings - Fork 1
Description
I noticed that the IpUtils#calculateInternetChecksum calculates the checksum wrong. The last carry bit fold should be done until there are no more carries left.
Example:
ICMPv6 ping:
6003e8e800403a40fd2001ba301818000000002700000000fda4098011112222000000001ad276d98000fffb00121aa64ceb746800000000ce8c030000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
Same at online packet checked
The checksum data of same packet:
fd2001ba301818000000002700000000fda4098011112222000000001ad276d9000000400000003a8000000000121aa64ceb746800000000ce8c030000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
The method returns -4 (0xFFFC), while the packet has the correct checksum -5 (0xFFFB).
I'm not sure where all this affects, but it at least breaks the IpPayload#fromBytes decoding.
The correct implementation would do the fold multiple times, something like this:
public static short calculateInternetChecksum(byte[] data) {
ByteBuffer buf = ByteBuffer.wrap(data);
long sum = 0;
while(buf.hasRemaining()) {
if(buf.remaining() > 1) {
sum += buf.getShort() & 0xFFFF;
} else {
sum += (buf.get() & 0xFF) << 8;
}
}
// Multiple folding - keep folding until no more carries
while ((sum >> 16) != 0) {
sum = (sum & 0xFFFF) + (sum >> 16);
}
return (short) (~sum & 0xFFFF);
}