Я снова здесь, чтобы вычислить контрольную сумму TCP.
Мне нужно добавить псевдоголовок tcp + tcp header + tcp payload.
Все должно быть добавлено в 16 бит, как вы должны знать.
В моем коде первое, что я делаю, это добавляется к «sumando» (переменная, которая загружает контрольную сумму) псевдозаголовку.
После этого я добавляю заголовок tcp из unsigned short в unsigned short.
После этого я добавляю tcp полезной нагрузки из unsigned short в unsigned short.
Наконец, я делаю дополнение моей контрольной суммы tcp и преобразую ее в 2 байта. И это должно быть работой, но это не работает.
Я использую winpcap, чтобы перехватить пакеты с моего компьютера и пересчитать контрольную сумму tcp. Откройте Wireshark, вы можете увидеть, в каком байте начинается поля.
//http://www.arcesio.net/checksum/checksumTCP.html
u_char* tcp_checksum(const u_char* _datos, int _tamaño)
{
u_char *checksum = new u_char[2];
u_short sumando = 0, sumanda = 0;
bitset<17> controlador;
if (_tamaño < 54)
return nullptr;
//sumo ip origen e ip destino
for (int i = 26; i < 33; i++){
sumanda = (u_short)((_datos[i] << 8) + _datos[i + 1]);
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
i++;
}
//sumo el byte de ceros y el numero de protocolo TCP
sumanda = (u_short)0x06;
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
//sumamos el tcp segment len
sumanda = (u_short)((_datos[16] << 8) + _datos[17]) - ((u_short)((_datos[46] & 0xF0) >> 4) +
(u_short)(_datos[14] & 0x0F)) * 4;
//cout << "tcpseglen: " << sumanda;
cout << " tamaño: " << _tamaño << " ";
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
//YA TENEMOS SUMADO EL PSEUDO HEADER BIEEEEEN
//sumo todo el campo de cabecera con el checksum a cero
for (int i = 34; i < 53; i++){
if (i != 50){
sumanda = (u_short)((_datos[i] << 8) + _datos[i + 1]);
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
}
i++;
}
//suponiendo un tamaño de 20 bytes de cabecera siempre..
//sumo todo el payload tcp
for (int i = 54; i < _tamaño; i++){
if (i + 1 == _tamaño && _tamaño % 2 == 0){//se desborda entonces copiamos solo el ultimo, pero estará ya copiado??
sumanda = (u_short)_datos[_tamaño - 1];
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
break;
}
sumanda = (u_short)((_datos[i] << 8) + _datos[i + 1]);
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
i++;
}
u_short original;
original = (_datos[50] << 8) + _datos[51];
sumando += 20;
sumando = sumando & 0xFFFF;
sumando = ~sumando;
//cout << "checksum original: " << original << endl;
//cout << "checksum calculado: " << sumando << endl;
checksum[0] = (sumando >> 8) & 0x00FF;
checksum[1] = sumando & 0x00FF;
return checksum;
}
Я передаю пакет tcp этой функции (пакет, перехваченный с помощью winpcap).
Я сравниваю свою контрольную сумму tcp с реальной контрольной суммой tcp пакета, и это и пример вывода, исходной контрольной суммы tcp и моей контрольной суммы tcp соответственно:
6e9==6e9
75a==75a
fe1e==fe1e
8c3e==8c3e
73ed==73ed
8a52==8a52
844d==841d
dad2==dac4
5cde==5cde
e2d1==e2d1
Когда пакет не является нечетным, мне просто нужно добавить 20 к моей контрольной сумме, чтобы получить оригинал, я не знаю почему, но он работает .. но я не хочу делать это очевидно, если пакет нечетный, разница между контрольными суммами не является постоянной ,
Что не так с моим кодом? Пожалуйста помоги.
Regardes Kaxper!
Задача ещё не решена.
Других решений пока нет …