Skip to content

Icmpv6 checksum is calculated wrong #3

@Ozame

Description

@Ozame

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);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions