Código
UCHAR* GetTCPChecksum(const UCHAR* content, UINT length) { UCHAR checksum[2]; USHORT added = 0, add = 0; std::bitset<17> bs; if (length < 54) return NULL; for (UCHAR i = 26; i < 33; i++) { add = (USHORT)((content[i] << 8) + content[i + 1]); bs = added + add; added += add; if (bs[16] == 1) added++; i++; } add = (USHORT)0x06; bs = added + add; added += add; if (bs[16] == 1) added++; add = (USHORT)((content[16] << 8) + content[17]) - (USHORT)((content[46] & 0xF0) >> 4) * 4; bs = added + add; added += add; if (bs[16] == 1) added++; for (UINT i = 34; i < length - 1; i++) { if (i != 50) { add = (USHORT)((content[i] << 8) + content[i + 1]); bs = added + add; added += add; if (bs[16] == 1) added++; } i++; } if (length % 2) { add = (USHORT)(content[length - 1] << 8) + 0; bs = added + add; added += add; if (bs[16] == 1) added++; } added = added & 0xFFFF; added = ~added; checksum[0] = (added >> 8) & 0x00FF; checksum[1] = added & 0x00FF; return checksum; }
Hay que sumar en de 16 bits en 16 bits (en USHORT): el IP origen + IP destino + numero de protocolo <<8 + longitud del segmento TCP (la linea en cuestión) + payload TCP y si es impar se suma el ultimo pasandole a la izquierda del USHORT (<<8).
Eso es todo pero la práctica.. dejo un link que sigo para hacerlo:
http://www.arcesio.net/checksum/checksumTCP.html
Probad vosotros mismos con el wireshark, pasandole el paquete completo y el header-> caplen a la función, los paquetes que llevan el campo options suelen fallar.