UDP checksum calcul

la structure d'en-tête UDP définie à /usr/include/netinet/udp.h est comme suit

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

quelle valeur est 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 la somme de contrôle est-elle calculée? (Est-ce seulement l'en-tête udp ou l'en-tête udp plus la charge utile qui le suit?)

Merci.

19
demandé sur Deepak 2009-09-26 10:29:51

3 réponses

la somme de contrôle UDP est effectuée sur toute la charge utile,et les autres champs de l'en-tête et quelques 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 fait 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 de saisir les paquets qui ont été routés à la mauvaise adresse IP.

en gros, à la réception, Tous les Les mots de 16 bits de la zone de données headers plus sont additionnés ensemble (enrubannage à 16 bits) et le résultat est vérifié par 0xffff.

Sur le côté émetteur, c'est un peu plus complexe. La somme du complément d'une personne est effectuée sur toutes les valeurs de 16 bits, puis le complément d'une personne (c.-à-d., inverser tous les bits) est pris de cette valeur pour remplir le champ de somme de contrôle (avec la condition supplémentaire qu'une somme de contrôle calculée de zéro sera changée dans tous les bits).

Le complément somme juste la somme de toutes les valeurs du complément. C'est un peu plus complexe.

en gros, vous avez un accumulateur 16 bits qui démarre à zéro et vous ajoutez chaque valeur 16 bits à cela. Chaque fois que l'un de ces ajouts résulte en un carry, la valeur est enroulée autour et vous ajoutez une à la valeur à nouveau. Cela prend effectivement le bit de portage de l'addition de 16 bits et l'ajoute à la valeur.


comme une mise de côté, et c'est une pure conjecture de ma part, mais cela pourrait probablement être fait efficacement en utilisant le ADC (ajouter avec carry) instruction au lieu de ADD (étonnamment, add), ou n'importe quelles instructions équivalentes étaient disponibles sur votre CPU à l'époque.

Si il n'y avait pas de report, ADC ajouterait juste le zéro bit du carry. Dans les jours où cette chose a été fait (et oui, malheureusement, je suis ce vieux), la mémoire était beaucoup plus une contrainte que la vitesse, pas tellement le cas aujourd'hui, afin de gagner quelques octets dans votre code pourrait bien vous élever le niveau de demi-dieu-empereur de l'univers :-)


Notez que vous n'avez jamais eu à vous soucier de transporter 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, une fois additionnées, produisent (tronquées de 0x1fffe) 0xfffe - l'ajout d'un à cela ne causera jamais un autre report.

une fois que la somme du complément calculé est calculée, que ses bits sont inversés et insérés dans le paquet, le calcul à la réception produira 0xffff, en présumant qu'il n'y a pas d'erreurs dans la transmission, bien sûr.

il est intéressant de noter que la charge utile est toujours rembourrée pour s'assurer qu'il y a un nombre intégral de mots de 16 bits. Si c' padded, le champ de longueur vous indique le réel longueur.

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

30
répondu paxdiablo 2017-09-19 12:09:39

je cherchais sur le net un code qui calculerait l'en-tête udp (avec le pseudo-en-tête ip comme mentionné ci-dessus).

finalement j'ai trouvé le paquet dhclient open-bsd.c:

https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sbin/dhclient/packet.c

découvrez la fonction assemble_udp_ip_header()

1
répondu Guy L 2014-08-13 15:54:28

un exemple agréable et facile à comprendre de calcul de somme de contrôle UDP est fait par Gerd Hoffmann.

vous pouvez googler pour " NET-checksum.c Gerd Hoffmann" ou de regarder le fichier ici:

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

Vous pouvez utiliser net_checksum_tcpudp fonction, l'alimenter la longueur de la charge utile UDP, proto, src et dst IPs et puis la charge utile UDP elle-même et il fera la bonne chose.

À la fin vous avez pour appeler htons() sur la somme de contrôle et vous êtes bon.

1
répondu fxlv 2016-06-01 06:24:42