Berechnung der UDP-Prüfsumme

Lesezeit: 5 Minuten

Benutzer-Avatar
Deepak

Die unter /usr/include/netinet/udp.h definierte UDP-Header-Struktur lautet wie folgt

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

Welcher Wert wird im Prüffeld des Headers gespeichert? Wie überprüfe ich, ob die Prüfsumme korrekt ist? Ich meinte, auf welchen Daten wird die Prüfsumme berechnet? (Ist es nur der udp-Header oder der udp-Header plus die darauf folgende Nutzlast?)

Vielen Dank.

Benutzer-Avatar
paxdiablo

Die UDP-Prüfsumme wird über die gesamte Nutzlast durchgeführt, und die anderen Felder in der Kopfzeile, und einige Felder aus dem IP-Header. Aus dem IP-Header wird ein Pseudo-Header konstruiert, um die Berechnung durchzuführen (die über diesen Pseudo-Header, den UDP-Header und die Payload erfolgt). Der Pseudo-Header wird eingefügt, um Pakete abzufangen, die an die falsche IP-Adresse weitergeleitet wurden.

Grundsätzlich werden auf der Empfangsseite alle 16-Bit-Wörter der Header plus Datenbereich zusammenaddiert (Wrapping bei 16 Bit) und das Ergebnis gegengeprüft 0xffff.

Auf der Senderseite ist es etwas komplexer. Eine Einerkomplementsumme wird für alle 16-Bit-Werte durchgeführt, dann wird das Einerkomplement (d. h. alle Bits invertieren) von diesem Wert genommen, um das Prüfsummenfeld zu füllen (mit der zusätzlichen Bedingung, dass eine berechnete Prüfsumme von Null in alle geändert wird Eins-Bits).

Die Einerkomplementsumme ist nicht nur die Summe aller Einerkomplementwerte. Es ist etwas komplexer.

Grundsätzlich haben Sie einen laufenden 16-Bit-Akkumulator, der bei Null beginnt, und Sie addieren jeden 16-Bit-Wert dazu. Immer wenn eine dieser Additionen zu einem Übertrag führt, wird der Wert umgebrochen und Sie addieren erneut eins zum Wert. Dies nimmt effektiv das Übertragsbit der 16-Bit-Addition und addiert es zum Wert.


Nebenbei bemerkt, und dies ist eine reine Vermutung meinerseits, aber dies könnte wahrscheinlich durch die Verwendung von effizient durchgeführt werden ADC (add with carry) Anweisung statt ADD (überraschenderweise, fügen Sie hinzu) oder welche gleichwertigen Anweisungen zu diesem Zeitpunkt auf Ihrer CPU verfügbar waren.

Wenn es keinen Carry gäbe, ADC würde nur das Nullbit aus dem Übertrag hinzufügen. In den Tagen, als diese Sachen gemacht wurden (und ja, leider, ich bin so alt), war der Arbeitsspeicher weit mehr eine Einschränkung als die Geschwindigkeit, was heutzutage nicht mehr so ​​​​sehr der Fall ist, so dass das Speichern von ein paar Bytes in Ihrem Code Sie durchaus auf die Ebene des Halbgott-Imperators des Universums heben könnte :- )


Beachten Sie, dass Sie sich beim zweiten Mal keine Gedanken über das Tragen machen mussten (oder ein Tragen von zwei beim nächsten Mal). ADC wenn Sie die im vorherigen Absatz erwähnte Methode verwenden), da die beiden größten 16-Bit-Werte, wenn sie summiert werden, (abgeschnitten von 0x1fffe) 0xfffe – Das Hinzufügen von einem wird niemals einen weiteren Übertrag verursachen.

Sobald die berechnete Einerkomplementsumme berechnet ist, ihre Bits invertiert und in das Paket eingefügt werden, bewirkt dies, dass die Berechnung am empfangenden Ende produziert wird 0xffffvorausgesetzt natürlich, dass keine Übertragungsfehler auftreten.

Es ist erwähnenswert, dass die Nutzlast immer aufgefüllt wird, um sicherzustellen, dass es eine ganzzahlige Anzahl von 16-Bit-Wörtern gibt. Wenn es war aufgefüllt, das Längenfeld gibt Ihnen die tatsächliche Länge an.

RFC768 ist die Spezifikation, die dies detailliert.

  • Dank dafür. Ich war etwas verwirrt über den Pseudo-Header-Teil … aber dann hat der RFC die Luft geräumt.

    – Deepak

    26. September 2009 um 7:03 Uhr

  • “Alle 16-Bit-Wörter der Header (wobei die UDP-Prüfsumme Null ist) werden addiert und das Einerkomplement (dh alle Bits invertieren) wird in das Prüfsummenfeld eingefügt.” Nein, was der RFC sagt, würde dazu führen, dass “alle Einerkomplemente (dh alle Bits invertieren) der 16-Bit-Wörter der Header (wobei die UDP-Prüfsumme Null ist) hinzugefügt werden und das Einerkomplement davon wird gesetzt in das Prüfsummenfeld ein.” Ansonsten perfekte Antwort +1.

    – Joren

    26. September 2009 um 7:17 Uhr

  • Das ist nicht richtig. „Einerkomplementsumme“ bedeutet nicht, dass man von jedem Wort das Einerkomplement nimmt und sie zusammenzählt. Das bedeutet, dass Sie die Wörter addieren, und wenn ein Übertragsbit erzeugt wird, addieren Sie 1 zur laufenden Summe. Sehen mathforum.org/library/drmath/view/54379.html .

    – Jim Hunziker

    22. April 2010 um 15:51 Uhr

  • Danke, @Jim, ein bisschen mehr Recherche zeigt, dass Sie absolut richtig liegen. Ich wollte sagen, dass ich mich total geirrt habe, aber mein Ego hat sich in letzter Minute eingemischt und es nicht zugelassen :-). Wenn Sie der Meinung sind, dass die aktualisierte Antwort immer noch falsch ist, lassen Sie es mich bitte wissen. Prost.

    – paxdiablo

    23. April 2010 um 2:45 Uhr

  • Eine interessante Anmerkung zur Einerkomplement-Prüfsumme, die möglicherweise viel damit zu tun hat, warum sie gewählt wurde, ist, dass das Vertauschen der Byte-Reihenfolge der zu summierenden Wörter die Byte-Reihenfolge der Summe vertauscht.

    – Superkatze

    8. Februar 2012 um 17:12 Uhr

Ein schönes und leicht verständliches Beispiel für die UDP-Prüfsummenberechnung stammt von Gerd Hoffmann.

Sie können nach “net-checksum.c Gerd Hoffmann” googeln oder sich die Datei hier ansehen:

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

Sie können verwenden net_checksum_tcpudp Funktion, geben Sie ihr die UDP-Nutzdatenlänge, proto, src und dst IPs und dann die UDP-Nutzdaten selbst und es wird das Richtige tun.

Am Ende muss man anrufen htons() auf die Prüfsumme und gut ist.

Benutzer-Avatar
Kerl L

Ich habe im Netz nach Code gesucht, der den UDP-Header berechnet (mit dem Pseudo-IP-Header, wie oben erwähnt).

Endlich habe ich das open-bsd dhclient packet.c gefunden:

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

schau dir mal die funktion an assemble_udp_ip_header()

1368130cookie-checkBerechnung der UDP-Prüfsumme

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy