2009-09-26 14 views
18

Le struct d'en-tête UDP défini à /usr/include/netinet/udp.h est la suivantecalcul de la somme de contrôle UDP

struct udphdr 
{ 
    u_int16_t source; 
    u_int16_t dest; 
    u_int16_t len; 
    u_int16_t check; 
}; 

Quelle est la valeur stockée dans le champ de contrôle de l'en-tête? Comment vérifier si la somme de contrôle est correcte? Je voulais dire sur quelles données est la somme de contrôle calculée? (Est-ce seulement l'en-tête d'udp ou l'en-tête d'udp plus la charge utile qui le suit?)

Merci.

Répondre

27

La somme de contrôle UDP est effectué sur la totalité de la charge utile, et les autres champs de l'en-tête, et certains champs de l'en-tête IP. Un pseudo-en-tête est construit à partir de l'en-tête IP afin d'effectuer le calcul (qui est effectué sur ce pseudo-en-tête, l'en-tête UDP et la charge utile). La raison pour laquelle le pseudo-en-tête est inclus est d'intercepter les paquets qui ont été routés vers la mauvaise adresse IP. Fondamentalement, à la réception, tous les mots de 16 bits des en-têtes plus la zone de données sont additionnés (emballage à 16 bits) et le résultat est vérifié par rapport 0xffff. Du côté de l'envoi, c'est un peu plus complexe. La somme de complément à un est effectuée sur toutes les valeurs de 16 bits, puis le complément à un (c'est-à-dire, inverser tous les bits) est utilisé pour remplir le champ de somme de contrôle (avec la condition supplémentaire qu'une somme de un bits). La somme du complément à un est et non juste la somme de toutes les valeurs du complément. C'est un peu plus complexe. Fondamentalement, vous avez un accumulateur de 16 bits en cours commençant à zéro et vous ajoutez toutes les valeurs de 16 bits à cela. Chaque fois que l'un de ces ajouts entraîne un report, la valeur est enroulée et vous en ajoutez une à la valeur. Cela prend effectivement le bit de report de l'addition de 16 bits et l'ajoute à la valeur.


En aparté, ce qui est pure conjecture de ma part, mais cela pourrait probablement être efficacement fait par l'utilisation du ADC (ajouter avec report) instruction plutôt que ADD (, ajouter assez étonnamment), ou quelles instructions équivalentes étaient disponibles sur votre CPU à ce moment-là. S'il n'y avait pas de report, ADC ajouterait simplement le bit zéro du report. À l'époque où ce genre de choses était fait (et malheureusement, je l'ai déjà), la mémoire était beaucoup plus contraignante que la vitesse, ce qui n'est pas le cas de nos jours, donc sauver quelques octets dans votre code pourrait bien élever vous au niveau de demi-dieu-empereur-de-la-univers :-)


Notez que vous jamais eu à se soucier porter de la deuxième fois (ou un report de deux avec la prochaine ADC si vous utilisez cette méthode mentionnée dans le paragraphe précédent) puisque les deux plus grandes valeurs de 16 bits, quand additionnées, produisent (tronquées de 0x1fffe) 0xfffe - en ajoutant une à celle qui ne causera jamais un autre report.Une fois la somme du complément calculée calculée, ses bits sont inversés et insérés dans le paquet, ce qui entraîne le calcul à la fin de la réception pour produire 0xffff, en supposant qu'il n'y a pas d'erreurs dans la transmission bien sûr.

Il est à noter que la charge utile est toujours complétée pour s'assurer qu'il y a un nombre entier de mots de 16 bits. Si était rembourré, le champ de longueur vous indique la longueur réelle.

RFC768 est la spécification qui détaille ceci.

+0

Merci pour cela. J'étais un peu confus au sujet de la partie Pseudo-Header ... mais alors le RFC a dégagé l'air. – Deepak

+1

"Tous les mots de 16 bits des en-têtes (où la somme de contrôle UDP est zéro) sont ajoutés et le complément à un (c'est-à-dire, inverser tous les bits) est ce qui est placé dans le champ de somme de contrôle." Non, ce que dit le RFC conduirait à "tous les compléments (c'est-à-dire, inverser tous les bits) des mots de 16 bits des en-têtes (où la somme de contrôle UDP est nulle) et le complément de celui-ci est ce qui est mis dans le champ de somme de contrôle. " Sinon réponse parfaite +1. – Joren

+1

Ce n'est pas correct. "La somme du complément" ne signifie pas prendre le complément de chaque mot et les additionner. Cela signifie que vous ajoutez les mots ensemble, et quand un carry est produit, vous ajoutez 1 à la somme courante. Voir http://mathforum.org/library/drmath/view/54379.html. –

1

Un agréable et facile à comprendre par exemple de calcul de la somme de contrôle UDP est effectuée par Gerd Hoffmann .

Vous pouvez google pour "net-checksum.c Gerd Hoffmann" ou regarder le fichier ici:

https://gist.github.com/fxlv/81209bbd150abfeaceb1f85ff076c9f3

Vous pouvez utiliser la fonction net_checksum_tcpudp, nourrir la longueur de la charge utile UDP, proto, src et dst IPs puis la charge utile UDP elle-même et il fera la bonne chose. À la fin, vous devez appeler htons() sur la somme de contrôle et vous êtes bon.