calcular ip checksum y paso de u_long a u_char falla

Iniciado por Kaxperday, 20 Julio 2015, 14:21 PM

0 Miembros y 1 Visitante están viendo este tema.

Kaxperday

Código (cpp) [Seleccionar]
u_char* checksum_ip(u_char* datos, int tamaño)
{
u_char *checksum = new u_char[2]();
u_long suma = 0;
for (int i = 0; i < 24; i++)
{
suma += datos[i];
if (suma & 0xFFFF0000)
{
suma &= 0xFFFF;
suma++;
}
}
checksum = (u_char*)&suma;
cout << checksum << endl;
for (int i = 0; i < sizeof(checksum); i++)
printf("%x", checksum[i]);
system("pause");
return checksum;
}


La salida no concuerda con el checksum original del paquete, algo está fallando, quiero pensar que el paso de u_long a u_char* es correcto, iré dando más detalles.

Saludos.

Edito: http://www.arcesio.net/checksum/checksuminternet.html, aqui explica bien como funciona lo del checksum, y el de ip. Según he entendido debo de sumar, de 16 bits en 16 bits todos los campos del header hasta llegar a el del checksum, que ocupartian los bytes 24 y 25 de la cabecera, así pues hice esto, pero no me funciono, no tengo ni idea de trabajar con bits ni entiendo como lo hacen  >:( >:(

Código (cpp) [Seleccionar]
u_char* checksum_ip(u_char* datos, int tamaño)
{//24 y 25 son checksum hasta el 23 sumamos

u_char *checksum = new u_char[2]();
for (int i = 0; i < 24; i++)
checksum += datos[i];
//sumo los campos byte a byte o ¿como sino?
for (int i = 0; i < 24; i++)
{
if (checksum[i] == 1)//ya se que esta mal, pero aqui sería poner 0 en los 1 y 1 en los 0, trbajando con bits ¿como accedo a ellos? ni idea
checksum[i] = 0;
else
checksum[i] = 1;
}


Segun pone aqui: http://www.arcesio.net/checksum/checksumIP.html

Debería coger los bytes de 2 en 2, y formar con el par una ristra de bits con 16 en total. Esa ristra la sumo.

Vale vale, tenia una cosa mal, ahora comento.

Código (cpp) [Seleccionar]
//un sumando del 13 al 23 incluyendo ambos.
//otro dumando 16 bits de ceros, y 2 ristras de 16 bits con las ips
//se suman se cambian 0s por 1s y 1s por 0s, separamos la ristra de 6 en 2 bytes
//formamos un u_char[2] y ya tenemos el checksum ip


La cosa ahora es como puedo sumarlos de 16 en 16?, podría sumar byte a byte, de 8 en 8, con u_char + .., pero de 16 en 16?.

Os dejo el code:

Código (cpp) [Seleccionar]
u_char* checksum_ip(u_char* datos, int tamaño)
{//24 y 25 son checksum hasta el 23 sumamos
//un sumando del 13 al 23 incluyendo ambos.
//otro dumando 16 bits de ceros, y 2 ristras de 16 bits con las ips
//se suman se cambian 0s por 1s y 1s por 0s, separamos la ristra de 6 en 2 bytes
//formamos un u_char[2] y ya tenemos el checksum ip
/*
u_char *checksum = new u_char[2]();
for (int i = 0; i < 24; i++)
checksum += datos[i];
for (int i = 0; i < 24; i++)
{
if (checksum[i] == 1)
checksum[i] = 0;
else
checksum[i] = 1;
}*/
u_char *checksum = new u_char[2]();
u_long suma = 0;
for (int i = 13; i < 24; i++)
{
suma += datos[i];
if (suma & 0xFFFF0000)
{
suma &= 0xFFFF;
suma++;
}
}
for (int i = 26; i < 33; i++)
{
suma += datos[i];
if (suma & 0xFFFF0000)
{
suma &= 0xFFFF;
suma++;
}
}
u_short a = ~(suma & 0xFFFF);
checksum = (u_char*)&a;
cout << checksum << endl;
for (int i = 0; i < sizeof(checksum); i++)
printf("%x", checksum[i]);
system("pause");
return checksum;
}


Seguiré investigando.

Horrible, http://www.dreamincode.net/forums/topic/158278-help-with-c-ip-header-checksum/

Saludos.

Ya lo tengo orgasm http://www.badprog.com/c-type-converting-two-uint8-t-words-into-one-of-uint16-t-and-one-of-uint16-t-into-two-of-uint8-t
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

Kaxperday

#1
meto ping al tema, volvemos a vernos las caras, necesito calcular el ip checksum y no hay manera, por más códigos que veo ninguno coincide con el checksum del paquete, he probado muchos, pero el que más se ha aproximado fue el que traté de implementar hace tiempo, cuando creé este hilo:

Código (cpp) [Seleccionar]
//http://realtimecollisiondetection.net/blog/?p=78
u_char* checksum_ip(u_char* datos, int tamaño)
{
u_char *checksum = new u_char[2]();
uint16_t sumando = 0, sumanda = 0;
bitset<16> salida;
for (int i = 14; i < 34; i++)
{
if (i != 24 && i != 25)
{
printf("i = %d, i + 1 = %d -> ", i, i + 1);
sumanda = (uint16_t)((datos[i] << 8) + datos[i + 1]);//no puede haber acarreo de bit ??
salida = sumanda;
cout << salida << endl;
sumando += sumanda;
if (sumando & 0xFFFF0000)
{
sumando &= 0xFFFF;
sumando++;
}
i++;
}
}
sumando = sumando +2;
sumando = sumando & 0xFFFF;
sumando = ~sumando;
salida = sumanda;
cout << salida << endl;
checksum[0] = (sumando >> 8) & 0x00FF;
checksum[1] = sumando & 0x00FF;
printf("\n%x%x", checksum[0], checksum[1]);
system("pause");
return checksum;
}


Salidas original/calculado:

Citar869a/869d
869a/8699
7c6f/7fb4
8699/8698
74b/740

Evidentemente está mal, ¿que puede fallar? me iré pasando a ver si puedo solucionarlo.

¿Alguien me puede decir porque este código no funciona? , debería de hacerlo he probado con todo.

Saludos, toda ayuda es bienvenida.

Edito: Si sumo 2 obtengo lo mismo que en el ejemplo de aqui:

http://www.arcesio.net/checksum/checksumIP.html

El mismo resultado final, sin embargo no funciona con los paquetes, pero si sumo 3 el 70% de los checksum de los paquetes coinciden, ¿que puede faltar?

Resuelto, conseguí detectar si había acarreo de byte y lo calcule satisfactoriamente.

Saludos.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.