2009-09-26 5 views
18

Der UDP-Header-Struktur bei /usr/include/netinet/udp.h definiert ist alsUDP-Prüfsumme Berechnung

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

folgt, welcher Wert in das Prüffeld des Header gespeichert wird? Wie kann überprüft werden, ob die Prüfsumme korrekt ist? Ich meinte, auf welchen Daten wird die Prüfsumme berechnet? (Ist es nur die UDP-Header oder UDP-Header und die Nutzlast, die ihm folgt?)

Vielen Dank.

Antwort

27

Die UDP-Prüfsumme über die gesamte Nutzlast durchgeführt, und die anderen Felder in der Kopfzeile, und einige Felder aus den IP-Header. Ein Pseudo-Header wird aus dem IP-Header konstruiert, um die Berechnung durchzuführen (was über diesen Pseudo-Header, den UDP-Header und die Nutzdaten erfolgt). Der Grund für das Einschließen des Pseudo-Headers besteht darin, Pakete abzufangen, die an die falsche IP-Adresse weitergeleitet wurden.

Grundsätzlich werden am empfangenden Ende alle 16-Bit-Wörter der Header plus Datenbereich zusammenaddiert (Wrapping bei 16 Bit) und das Ergebnis wird gegen 0xffff geprüft.

Auf der sendenden Seite ist es ein wenig komplexer. Eine Eins-Komplement-Summe wird an allen 16-Bit-Werten durchgeführt, dann wird das Einerkomplement (dh 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) Ein-Bits).

Die Summe der Einser-Komplement ist nicht nur die Summe aller Einerkomplementwerte. Es ist ein bisschen komplexer.

Grundsätzlich haben Sie einen laufenden 16-Bit-Akkumulator, der bei Null beginnt, und Sie fügen jeden 16-Bit-Wert hinzu. Immer wenn eine dieser Ergänzungen zu einem Übertrag führt, wird der Wert umbrochen und Sie fügen dem Wert erneut eins hinzu. Dies nimmt effektiv das Übertragsbit der 16-Bit-Addition und addiert es zu dem Wert.


Als beiseite, und das ist reine Vermutung meinerseits aber wahrscheinlich effizient durch die Verwendung der ADC (add mit Carry) Befehl getan werden könnte, anstatt ADD (überraschenderweise, hinzufügen), oder was auch immer entsprechende Anweisungen auf Ihrer CPU zu der Zeit zur Verfügung standen.

Wenn es keinen Übertrag geben würde, würde nur das Null-Bit aus dem Übertrag hinzufügen. In den Tagen, als dieses Zeug fertig war (und ja, ich leider so alt bin), Speicher war weit mehr eine Einschränkung als Geschwindigkeit, nicht so sehr der Fall heutzutage, so ein paar Bytes in Ihrem Code speichern konnte gut erhöhen Sie auf die Ebene des Halbgott-Kaiser-of-the-Universum :-)


Beachten Sie, dass Sie nie um das zweite Mal trägt Sorge mußten über (oder einen Übertrag von zwei mit dem nächsten ADC Wenn Sie diese Methode verwenden, die im vorherigen Absatz erwähnt wurde), da die zwei größten 16-Bit-Werte, wenn summiert, produzieren (abgeschnitten von 0x1fffe) 0xfffe - Hinzufügen von einem, das nie einen anderen Übertrag verursachen wird.

Sobald die berechnete Einerkomplement-Summe berechnet ist, ihre Bits invertiert sind und in das Paket eingefügt werden, führt dies dazu, dass die Berechnung am empfangenden Ende 0xffff ergibt, wobei natürlich keine Fehler bei der Übertragung angenommen werden.

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 gepolstert wurde, sagt das Längenfeld Ihnen die tatsächliche Länge.

RFC768 ist die Spezifikation, die dies detailliert.

+0

Danke dafür. Ich war ein bisschen verwirrt über den Pseudo-Header-Teil ... aber dann reinigte der RFC die Luft. – Deepak

+1

Alle 16-Bit-Wörter der Header (wobei die UDP-Prüfsumme Null ist) werden addiert und das Einerkomplement (d. H. Alle Bits invertieren) wird in das Prüfsummenfeld eingegeben. Nein, was der RFC sagt würde zu "All die Ergänzungen (dh invertieren alle Bits) der 16-Bit-Wörter der Header (wo die UDP-Prüfsumme ist Null) hinzugefügt werden und das Einser-Kompliment von dem ist, was gesetzt wird in das Prüfsummenfeld. " Ansonsten perfekte Antwort +1. – Joren

+1

Das ist nicht richtig. "Eins-Komplement-Summe" bedeutet nicht, dass man die Ergänzung jedes Wortes nimmt und sie addiert. Es bedeutet, dass Sie die Wörter zusammenfügen, und wenn ein Übertragsbit erzeugt wird, fügen Sie der laufenden Summe 1 hinzu. Siehe http://mathforum.org/library/drmath/view/54379.html. –

1

Eine schöne und leicht aus Beispiel UDP-Prüfsumme Berechnung zu verstehen, wird von Gerd Hoffmann getan .

Sie für "net-checksum.c Gerd Hoffmann" google kann oder hier in der Datei aussehen:

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

Sie net_checksum_tcpudp Funktion nutzen zu können, ist es die Nutzlast Länge UDP füttern, Proto, src und dst IPs und dann die UDP-Payload selbst und es wird das Richtige tun.

Am Ende müssen Sie htons() auf der Prüfsumme anrufen und du bist gut.