Résumé

  • RFC 768 attribuait deux sens distincts au zéro dans le champ checksum d’UDP : un résultat calculé nul devenait 0xFFFF, tandis que 0x0000 indiquait qu’aucun checksum n’avait été calculé.
  • Les exigences hôtes de 1989 conservaient la possibilité de l’omettre, mais faisaient du calcul la valeur par défaut. IPv6 l’a ensuite rendu obligatoire avant qu’une mise à jour de 2013 n’autorise un cas de tunnel étroitement délimité.

Deux zéros dans un seul champ

En août 1980, RFC 768, rédigé par Jon Postel, définissait le User Datagram Protocol comme un moyen d’échanger des datagrammes avec un minimum de mécanismes. UDP ne garantissait ni l’ordre de livraison, ni la protection contre les doublons, ni la fiabilité. Son en-tête ne faisait que huit octets : ports source et destination, longueur et checksum, puis les données.

Le dernier champ paraît simple jusqu’à ce que l’arithmétique lui donne une singularité. UDP emploie le checksum de 16 bits en complément à un également utilisé par TCP. Le calcul couvre l’en-tête et les données UDP, ainsi qu’un pseudo-en-tête contenant les adresses IP source et destination, le numéro de protocole et la longueur UDP. Selon Postel, ce pseudo-en-tête aide à protéger contre les datagrammes mal acheminés.

En complément à un, zéro possède deux représentations binaires : tous les bits à zéro et tous les bits à un. RFC 768 attribuait à chacune une fonction différente sur le réseau. Si le calcul donnait zéro, l’émetteur devait transmettre tous les bits à un. Un champ transmis entièrement à zéro signifiait au contraire qu’aucun checksum n’avait été généré. Le format portait donc à la fois un résultat et un petit indicateur d’état, sans ajouter de bit de drapeau.

C’est le point historique précis de cet article. Un checksum UDP nul n’était pas un checksum calculé dont le résultat valait zéro. Il codait une absence. Confondre les deux états pouvait conduire une implémentation à rejeter un datagramme valide ou à traiter l’absence de détection d’erreurs comme une vérification réussie.

Une option qui n’était pas la valeur par défaut

La spécification initiale laissait la possibilité d’omettre le checksum, notamment pour le débogage ou pour des protocoles de niveau supérieur qui n’en avaient pas besoin. Neuf ans plus tard, RFC 1122, consacré aux exigences des hôtes Internet, précisait la règle opérationnelle. Un hôte devait implémenter le calcul et la validation ; une application pouvait contrôler la génération, mais celle-ci devait être activée par défaut. Les récepteurs pouvaient choisir s’ils transmettaient aux applications des datagrammes sans checksum.

RFC 1122 signalait aussi une erreur d’implémentation fréquente : un résultat calculé nul doit être transmis comme 65535, alors que le champ entièrement à zéro signifie « absent ». Le document rapportait que certaines applications destinées aux seuls réseaux locaux avaient désactivé les checksums pour gagner en efficacité, et que de nombreuses erreurs non détectées avaient été signalées. Il ne donnait ni décompte, ni incident nommé, ni dénominateur. C’est donc la trace d’une préoccupation des auteurs de normes, pas une mesure de sa fréquence.

Le checksum n’a jamais été une signature. Son pseudo-en-tête pouvait détecter certains mauvais acheminements et son calcul certaines corruptions accidentelles. Il n’authentifiait pas l’émetteur, n’empêchait pas une modification délibérée et ne prouvait pas que les données applicatives étaient cohérentes. « checksum présent » et « paquet digne de confiance » désignaient deux choses différentes.

IPv6 a resserré la règle

La spécification IPv6 de 1998, RFC 2460, rendait le checksum UDP obligatoire. Si le calcul donnait zéro, il fallait aussi l’écrire 0xFFFF ; le récepteur devait écarter un datagramme UDP IPv6 dont le champ checksum valait zéro. L’ancien marqueur d’absence facultatif devenait ainsi inacceptable pour le trafic UDP IPv6 ordinaire.

Cette règle a ensuite rencontré un cas de performance précis. En 2013, RFC 6935 et RFC 6936 ont modifié le traitement IPv6 pour certains tunnels UDP. Ces tunnels pouvaient transporter des paquets dotés de leurs propres contrôles d’intégrité, et le calcul d’un checksum externe avait un coût. L’exception dépendait de critères d’applicabilité, du comportement des deux extrémités et de la compatibilité des équipements intermédiaires ; elle ne transformait pas le checksum nul en option générale pour IPv6.

La séquence normative montre que le motif binaire est resté identique tandis que son contexte autorisé changeait. En IPv4, zéro pouvait marquer l’absence, avec un calcul activé par défaut dans les exigences hôtes. En IPv6, cette absence a d’abord été rejetée, puis réadmise sous conditions pour un rôle précis d’encapsulation externe. La valeur seule ne disait jamais au récepteur si l’omission était acceptable : la version IP et le contexte d’usage comptaient.

Sources