C Programmation TCP Checksum

J’ai eu du mal à faire la sum de contrôle pour TCP depuis plusieurs jours maintenant. J’ai consulté de nombreuses sources sur Internet, mais aucun des exemples que j’ai vus ne montre comment utiliser la sum de contrôle TCP. J’ai également consulté le document RFC et j’ai toujours des problèmes:

Voici le code que j’utilise pour générer la sum de contrôle:

unsigned short checksum(unsigned short * buffer, int bytes) { unsigned long sum = 0; unsigned short answer = 0; int i = bytes; while(i>0) { sum+=*buffer; buffer+=1; i-=2; } sum = (sum >> 16) + (sum & htonl(0x0000ffff)); sum += (sum >> 16); return ~sum; } 

Cette fonction fonctionne pour la sum de contrôle IP.

Voici la structure que j’ai créée pour mon en-tête TCP:

 struct tcp_header { unsigned short tcp_sprt; unsigned short tcp_dprt; unsigned int tcp_seq; unsigned int tcp_ack; unsigned char tcp_res:4; unsigned char tcp_off:4; unsigned char tcp_flags; unsigned short tcp_win; unsigned short tcp_csum; unsigned short tcp_urp; }; 

J’utilise Wireshark pour tester ces paquets et la seule chose qui ne va pas, c’est la sum de contrôle.

Enfin, voici la structure du pseudo en-tête que je charge avec l’en-tête TCP et les informations de l’en-tête IP:

 struct pseudoTcpHeader { unsigned int ip_src; unsigned int ip_dst; unsigned char zero;//always zero unsigned char protocol;// = 6;//for tcp unsigned short tcp_len; struct tcp_header tcph; }; 

Une fois que je charge cette structure avec les informations correctes, j’utilise ensuite la fonction de sum de contrôle sur la structure entière du pseudo en-tête et assigne la sum de contrôle TCP à cette valeur. Voyez-vous quelque chose de mal avec ce que j’ai fourni? Si le problème n’est pas là, il s’agit peut-être d’une erreur imprudente que je ne peux pas voir.

J’ai trouvé un assez bon exemple sur la liste de diffusion winpcap-users qui devrait répondre au commentaire de Greg sur les données de longueurs irrégulières et vous permettre de comparer votre code.

 USHORT CheckSum(USHORT *buffer, int size) { unsigned long cksum=0; while(size >1) { cksum+=*buffer++; size -=sizeof(USHORT); } if(size) cksum += *(UCHAR*)buffer; cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); } 

Je vois deux choses:

  • Vous ne comptez pas pour des données de longueur impaire par un remplissage avec zéro.
  • Vous devrez tenir compte de l’ordre des octets du réseau lors de la lecture de chaque mot du paquet.
  • Votre utilisation de htonl(0x0000ffff) semble suspecte. Pourquoi convertissez-vous une constante en ordre d’octet réseau pour la combiner avec des données dans l’ordre des octets hôte ?

La RFC 793 dit: “Si un segment contient un nombre impair d’octets d’en-tête et de texte à contrôler, le dernier octet est complété à droite par des zéros pour former un mot de 16 bits à des fins de total de contrôle.” Votre code ci-dessus ne gère pas ce cas. Je pense que la boucle conditionnelle devrait être i> 1, puis vérifier si i == 1 en dehors de la boucle et effectuer le traitement spécial pour le dernier octet.

Moi aussi, j’ai eu du mal à trouver le code c ++ / c qui le calcule, jusqu’à ce que je sache comment calculer la sum de contrôle IP / TCP / UDP – Mise en œuvre de la partie 2 – roman10 , et cela a fonctionné! Testé avec la validation de Wireshark.