Question

I am writing a simple program to send and recieve icmp messages. I have written the following to calculate the checksum for the icmp message:

char sbuf[] = "        This is a test message..";
sbuf[0] = 0x10;
sbuf[1] = 0x00;
sbuf[2] = 0x00;
sbuf[3] = 0x00;
sbuf[4] = 0x00;
sbuf[5] = 0x00;
sbuf[6] = 0x00;
sbuf[7] = 0x00;
for (int i = 0; i < sizeof(sbuf); i += 2)
    checksum += (sbuf[i] << 8) + sbuf[i + 1];

if (sizeof(sbuf) % 2)
    checksum += sbuf[sizeof(sbuf) - 1] << 8;
checksum = (checksum >> 16) + (checksum & 0xffff);
checksum = ~(checksum + (checksum >> 16));
sbuf[2] = checksum >> 8;
sbuf[3] = checksum & 0x00ff;

The problem is, the calculated checksum is not correct when the messege length is an odd number. There is something wrong with the checksum += sbuf[sizeof(sbuf) - 1] << 8; part but i can't figure out what

How do i fix this?

Thanks

Was it helpful?

Solution

So i think i have found the soloution.

for (int i = 0; i < sizeof(sbuf) - 1; i += 2)
    checksum += (sbuf[i] << 8) + sbuf[i + 1];

if (sizeof(sbuf) % 2)
    checksum += sbuf[sizeof(sbuf) - 1];

Now this does calculate the correct checksum for any lenght of messege. But i can't confirm if it is a real solution or it just works because the last byte of my message is always zero.

OTHER TIPS

You may like my version

uint16_t Checksum(const void* data, size_t len) {
    auto p = reinterpret_cast<const uint16_t*>(data);
    uint32_t sum = 0;
    if (len & 1) {
        // len is odd
        sum = reinterpret_cast<const uint8_t*>(p)[len - 1];
    }
    len /= 2;
    while (len--) {
        sum += *p++;
        if (sum & 0xffff0000) {
            sum = (sum >> 16) + (sum & 0xffff);
        }
    }
    return static_cast<uint16_t>(~sum);
}

std::cout << "0x" << std::hex << std::setw(4)
          << Checksum(sbuf, sizeof(sbuf))
          << std::endl;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top