2016-05-20 3 views
3

versucht, diesen Code für eine Weile ohne Glück zu beheben, versuchte, verschiedene Implementierungen, die die IPv4-Header-Prüfsumme berechnen, aber ihre Leistung ist ganz anders als meine Programme Ausgabe:IPv4-Header-Prüfsumme Berechnung, was bin ich fehle

Funktion stahl ich aus dem linux-kernel dies zu tun:

static inline uint16_t ip_fast_csum(const void *iph, unsigned int ihl){ 

    unsigned int sum; 

    asm(" movl (%1), %0\n" 
     " subl $4, %2\n" 
     " jbe 2f\n" 
     " addl 4(%1), %0\n" 
     " adcl 8(%1), %0\n" 
     " adcl 12(%1), %0\n" 
     "1: adcl 16(%1), %0\n" 
     " lea 4(%1), %1\n" 
     " decl %2\n" 
     " jne  1b\n" 
     " adcl $0, %0\n" 
     " movl %0, %2\n" 
     " shrl $16, %0\n" 
     " addw %w2, %w0\n" 
     " adcl $0, %0\n" 
     " notl %0\n" 
     "2:" 
    /* Since the input registers which are loaded with iph and ihl 
     are modified, we must also specify them as outputs, or gcc 
     will assume they contain their original values. */ 
     : "=r" (sum), "=r" (iph), "=r" (ihl) 
     : "1" (iph), "2" (ihl) 
     : "memory"); 
    return (uint16_t)sum; } 

Beispiel Header (Byte): 45009d4326400406af6cd052ed12ac10a51

Abschnitt meines Programms, das die oben ruft Funktion ordnet die Prüfsumme an den Header und druckt den Header sowie die Prüfsumme:

newpacket.ipheader->check = ip_fast_csum ((unsigned short *) newpacket.ipheader, IP4_HDRLEN); 
    debug(5,"newpacket checksum set to %0x\r\n",newpacket.ipheader->check); 
    uint8_t *ipbuf=(uint8_t *)newpacket.ipheader; 
    for(i=0;i<IP4_HDRLEN;i++){ 
    debug(5,"%0x",ipbuf[i]); 
    }debug(5,"\n"); 

debug() ist nur eine printf() Wrapper, folgende Beispielausgabe:

newpacket checksum set to 6caf 
45009d4326400406af6cd052ed12ac10a51 

Screencap von dem, was wireshark ist mir zu sagen:

wiresharkcap

können Sie mir helfen und mir sagen, was ich falsch mache?

Dies ist die Funktion, die ich normalerweise verwenden:

inline unsigned short csum (unsigned short *buf, int nwords) { 
    unsigned long sum; 

    for (sum = 0; nwords > 0; nwords--) 
      sum += *buf++; 
    sum = (sum >> 16) + (sum & 0xffff); 
    sum += (sum >> 16); 
    return (unsigned short) (~sum); 
} 

Vielen Dank im Voraus.

+1

[RFC 1071] (https://tools.ietf.org/html/rfc1071), [RFC 1141] (https://tools.ietf.org/html/rfc1141) und [RFC 1624] (https : //tools.ietf.org/html/rfc1624) sind die Quellen, die Ihnen den Algorithmus zur Berechnung der IPv4 Header Checksum geben. –

+2

Sieht so aus, als würden Sie die IP-Header-Prüfsumme berechnen. Wireshark scheint die TCP-Header-Prüfsumme anzuzeigen. – SergeyA

+0

Nur um @SergeyA zu erweitern, scheint es, dass Sie die IP-Schicht-Prüfsumme in der TCP-Schicht platziert haben. Oder in "offiziellen" Bedingungen. https://en.wikipedia.org/wiki/OSI_model Sie vermischen Schicht 3 und 4. – arduic

Antwort

0

Nur um ein bisschen mehr @SergeyA aus den Kommentaren und mir ein bisschen mehr zu erweitern. Wenn Sie sich die Datei suchen Sie above Bezug genommen wird, werden Sie in der Kommentar bemerken für diese Funktion

ip_fast_csum - Berechnen Sie die Header-Prüfsumme IPv4 effizient.

Sie möchten die IPv4-Header-Prüfsumme nicht berechnen, die TCP-Prüfsumme gewünscht wird. Dies sind separate Schichten im OSI-Modell here. Um die TCP-Prüfsumme zu berechnen, müssen Sie als these feine Leute beschreiben.

Mit nur dem Kernel-Code, wie Sie früher machen wollten, gibt es hier eine Funktion, die die TCP-Prüfsumme berechnen sollte. Unten werde ich die Beschreibung und den Header kopieren.

static inline __sum16 tcp_v4_check(int len, __be32 saddr, 
            __be32 daddr, __wsum base) 
  • berechnen (/ Check) TCP-Prüfsumme

Wenn aber Sie möchten es auf die harte Art und Weise zu tun. Wenn Sie in derselben Datei suchen, auf die Sie verwiesen haben, können Sie den Pseudo-Header für TCP-Pakete mithilfe der Funktion berechnen.

csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, 
       __u8 proto, __wsum sum) 

Gibt die Pseudo-Header-Prüfsumme der Eingangsdaten. Ergebnis ist 32bit entfaltet.

Dies ist nur der psuedo Header von dort allerdings müssen Sie die gesamte Prüfsumme berechnen, die ich (nicht 100% sicher) glauben, dass Sie nur die Funktion, die Sie früher gezeigt verwenden können, um zu berechnen, wenn Sie die Pseudo-Header beschrieben Pad früher darauf.

Auf einer Seite habe ich diesen Code nicht überprüft, aber es scheint auf den ersten Blick ziemlich genau, so here ist ein C/Assembly Weg, um die TCP-Prüfsumme zu berechnen.

+0

Hallo, TCP-Prüfsumme ist in Ordnung, ich habe eine separate Funktion, die es berechnet.wireshark zeigt eine gute TCP-Prüfsumme, so dass ich mir keine Sorgen machen, TCP-Prüfsumme benötigt die tcp Heder + Daten + IP-Pseudo-Header. Dies ist für die ipv4-Header-Prüfsumme, die separat ist und ausschließlich für den ipv4-Header ist. https://en.wikipedia.org/wiki/IPv4_header_checksum – misterdobalina

+0

Ah ok mein Fehler von dem Bild, das Sie zur Verfügung gestellt und der Text, den ich dachte, Sie hatten die IP-Prüfsumme in das TCP-Feld. Das tut mir leid. – arduic

0

wollte nur dies zu posten und diese Frage zu lösen, ich habe dieses Problem nach dem Versuch viele Implementierungen gelöst, die einzige, die funktioniert ist Suricata IDPS-Code.

static inline uint16_t IPV4CalculateChecksum(uint16_t *pkt, uint16_t hlen) 
{ 
    uint32_t csum = pkt[0]; 

    csum += pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[6] + pkt[7] + pkt[8] + 
     pkt[9]; 

    hlen -= 20; 
    pkt += 10; 

    if (hlen == 0) { 
     ; 
    } else if (hlen == 4) { 
     csum += pkt[0] + pkt[1]; 
    } else if (hlen == 8) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3]; 
    } else if (hlen == 12) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5]; 
    } else if (hlen == 16) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7]; 
    } else if (hlen == 20) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9]; 
    } else if (hlen == 24) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11]; 
    } else if (hlen == 28) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13]; 
    } else if (hlen == 32) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] + 
      pkt[14] + pkt[15]; 
    } else if (hlen == 36) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] + 
      pkt[14] + pkt[15] + pkt[16] + pkt[17]; 
    } else if (hlen == 40) { 
     csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + 
      pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] + 
      pkt[14] + pkt[15] + pkt[16] + pkt[17] + pkt[18] + pkt[19]; 
    } 

    csum = (csum >> 16) + (csum & 0x0000FFFF); 
    csum += (csum >> 16); 

    return (uint16_t) ~csum; 
} 

https://github.com/inliniac/suricata/blob/master/src/decode-ipv4.h

Ich hoffe, dass dies auch anderen hilft, Suricata hervorragende Code-Basis hat, geschrieben gut Code zu arbeiten.

Prost und danke für jeden, der versucht hat zu helfen.