Programmation.c : Probleme de calcul du Checksum TCP
Posté par Julien Vehent (Jabber id, page perso, ) le 24 juillet 2007
Bonjour a tous,
je fabrique mes propres paquets TCP et j'ai du mal a calculer le checksum
je cree le pseudo header comme ca :
ma fonction checksum est la suivante
et le tout est appele de la facon suivante
PAYLOAD_SIZE a la bonne valeur (je bosse sur des caracteres ascii pour le moment)
replay_tcp est bien parse, je le vois dans ethereal
Par contre ethereal me dit toujours que mes checksums sont faux, et effectivement la machine de destination n'accepte pas la connection lorsquelle recoit un SYN
J'ai relu plusieurs fois la RFC et le pseudo header correspond a ce qui est requis. Du coup, je pense que j'ai un probleme avec ma fonction checksum mais comme elle ne viens pas de moi et que je suis pas super a l'aise avec les complements a 1, j'y ai pas retouche......
si quelqu'un a une idee.... :)
je fabrique mes propres paquets TCP et j'ai du mal a calculer le checksum
je cree le pseudo header comme ca :
struct pseudo_header
{
unsigned long saddr, daddr; /*! src/dst IP addresses */
char mbz;
unsigned char ptcl; /*! protocol (tcp = 6, udp = 17) */
unsigned short tcpl; /*! length (tcp header + payload)*/
};
ma fonction checksum est la suivante
int checksum (unsigned short *buf, int nwords)
{
unsigned long sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
et le tout est appele de la facon suivante
/*! *******************
* compute TCP checksum
* ********************
*/
int PSEUDO_SIZE = /*! 12 = size of the pseudoheader */
PAYLOAD_SIZE + (replay_tcp->doff*4) + 12;
char pseudo_tcp[ PSEUDO_SIZE ];
/*! fill up the pseudo header
*/
struct pseudo_header *ph;
ph->saddr = iph->saddr;
ph->daddr = iph->daddr;
ph->mbz = 0;
ph->ptcl = 6;
ph->tcpl = htons(PSEUDO_SIZE - 12);
replay_tcp->check = 0;
memcpy(pseudo_tcp, (char *) ph, 12);
memcpy(pseudo_tcp + 12, (char *) replay_tcp, PSEUDO_SIZE - 12);
/*! compute the checksum and store it in the TCP structure
*/
replay_tcp->check = checksum((unsigned short*) pseudo_tcp, PSEUDO_SIZE );
replay_tcp->check = checksum((unsigned short*) pseudo_tcp, PSEUDO_SIZE );
g_print("%x\n", ntohs(checksum((unsigned short*) pseudo_tcp, PSEUDO_SIZE )));
PAYLOAD_SIZE a la bonne valeur (je bosse sur des caracteres ascii pour le moment)
replay_tcp est bien parse, je le vois dans ethereal
Par contre ethereal me dit toujours que mes checksums sont faux, et effectivement la machine de destination n'accepte pas la connection lorsquelle recoit un SYN
J'ai relu plusieurs fois la RFC et le pseudo header correspond a ce qui est requis. Du coup, je pense que j'ai un probleme avec ma fonction checksum mais comme elle ne viens pas de moi et que je suis pas super a l'aise avec les complements a 1, j'y ai pas retouche......
si quelqu'un a une idee.... :)
> Lire le message (3 commentaires, moyenne: 1).
Vous avez demandé le commentaire #853719.



2 idées et 1 remarque
1 - La RFC 793 dit
. Cependant tu calcules la somme des mots de 16 bits sans prendre le complément à 1.2 - Tu risques des problèmes d'endianness en castant ta struct en unsigned short (surtout si tu es sur une little endian comme les x86) : problème des retenues dans la somme.
Remarque : Le unsigned short ne fait pas forcément 16 bits. Mieux vaut utiliser les types définis dans inttypes.h (Single Unix) intXX_t et uintXX_t.
Hurd will be out in a year (or two, or next month, who knows)
-- Linus Benedict Torvalds, 1991
[^]Re: 2 idées et 1 remarque
J'utilise une autre fonction de calcul de checksum qui vient d'un article de phrack maintenant
de fait, le code de creation devient
mais ca marche toujours pas :'(
www.linuxwall.info