TCPIP-Stack Programmierung

Post Reply
Message
Author
daa531
Posts: 6
Joined: 05. Feb 2006 18:48

TCPIP-Stack Programmierung

#1 Post by daa531 »

Hallo Leute,

ích Programmiere an einen Projekt mit und möchte den TCPIP-Stack erweitern.
Das man z.B. mit einen Telnet-Client auf den Server zureifen kann. Warum eigener
TCPIP-StacK? Das Projekt wird auf unterschiedlichen Plattformen genutzt
(DOS, EPROMS, WIN32, LINUX. Was schon funktioniert ist das beantworten
von PING-Anfragen. Nun möchte ich das TCP-Protokoll implementieren und bin auf
folgendes Problem gestossen. Der Telnet-Client sendet eine SYN Anfrage zum Server:

Code: Select all

CLIENT 1.Frame: 
IP : len 48 10.10.190.5->10.10.40.1 ihl 20 ttl 128 prot TCP 
TCP: 3237->23 Seq x546EC8EE Ack x00000000 SYN Wnd 16384 MSS 1460 
Und nun das Problem, hier die Ausgabe vom Server:

Code: Select all

SERVER 1.Frame: 
IP : len 40 10.10.40.1->10.10.190.5 ihl 20 ttl 31 prot TCP 
TCP: 23->3237 Seq x85BE2E1E Ack x546EC8EF ACK SYN Wnd 16384 Data 20 
@WLÑà¥.^Tn+´@R@@þ¢@@ 
Beim zusammen stellen des IP-Header oder TCP-Header muss ein Fehler enthalten sein,
weis aber nicht wo was sein koennte. Vielleicht sieht einer gleich woran es liegt.
Ansonsten muss ich paar Codeschnippsel Posten.

Gruss Olli.

klopskuchen
prolinux-forum-admin
Posts: 1444
Joined: 26. Jun 2004 21:18
Contact:

#2 Post by klopskuchen »

> Data 20 @WLÑà¥.^Tn+´@R@@þ¢@@
Vermutung: Du sitzt an einer x86-Maschine, hast die Nutzdaten im little-endian-Format abgeschickt, der telnet-client hält sich an den Vorschlag auch Nutzlast im big-endian (network-byte-order) zu behandeln, wandelt das little-endian nochmal um und liefert Müll.

?, Klopskuchen
When all else fails, read the instructions .

daa531
Posts: 6
Joined: 05. Feb 2006 18:48

#3 Post by daa531 »

Vermutung: Du sitzt an einer x86-Maschine, hast die Nutzdaten im little-endian-Format abgeschickt, der telnet-client hält sich an den Vorschlag auch Nutzlast im big-endian (network-byte-order) zu behandeln, wandelt das little-endian nochmal um und liefert Müll.
Versteh ich nicht? Es gibt doch nur 2 Frame im Posting, 1.Frame Telnet Client und das
2.Frame ist vom Server der muell produziert. Naja habe mir erstmal Lektuere bestellt.
Alles findet man nicht im Internet (Google usw.)

Gruss Olli.

klopskuchen
prolinux-forum-admin
Posts: 1444
Joined: 26. Jun 2004 21:18
Contact:

#4 Post by klopskuchen »

Es gibt doch nur 2 Frame im Posting, 1.Frame Telnet Client und das
2.Frame ist vom Server der muell produziert.
Es war nicht genau ersichtlich, was dein "Frame" definiert und durch welche Applikation die Daten zuletzt gingen.
Versteh ich nicht?
Programmierst du auf einer x86? Die Protokollinformationen liegen im NetworkByteOrder vor. Du hast sie von maschineninterner Byteanordnung little-endian (niederwertigstes Byte an niedrigster Adresse) in big-endian (höchstwertiges Byte an niedrigster Adresse), sog. network-byte-order konvertiert. Hast du das mit den Nutzdaten nicht getan, gibt eine Diskrepanz in der Interpretation der Daten zwischen Server und Client, da der Client Ein- und Ausgang konvertiert, der Server jedoch nicht.
Das erscheint mir jedenfalls naheliegend, auf Grund der korrekt ausgegebenen Protokollinformationen (sonst hätte es erst gar keine Verbindung gegeben), und der nach "klassischem Schrott" aussehenden letzten Zeile auf die ich mich bezog, die wohl Nutzdaten darstellen soll.
Naja habe mir erstmal Lektuere bestellt.
Papier ist wesentlich angenehmer als die olle Glotze. ;)


MfG, Klopskuchen
When all else fails, read the instructions .

daa531
Posts: 6
Joined: 05. Feb 2006 18:48

#5 Post by daa531 »

sonst hätte es erst gar keine Verbindung gegeben
Es gibt ja NOCH keine Verbindung ! Der Telnet-Client sendet das 1.Frame mit SYN und
der Server soll das mit SYN + ACK bestaetigen.

Ich habe mir mal das Netzwerk-Tool etherreal besorgt um den Header zu Analysieren.
Und siehe da, da ist was faul, aber erstmal buch welsen......

Gruss Olli.
PS:
Es fehlt am Header auch die MSS
TCP: 23->2389 Seq x29221B7C Ack xA3583F1D ACK SYN Wnd 16384 Data 20
Wo Data 20 steht muss MSS hin.

klopskuchen
prolinux-forum-admin
Posts: 1444
Joined: 26. Jun 2004 21:18
Contact:

#6 Post by klopskuchen »

> Es fehlt am Header auch die MSS
Aha. Zum Thema Codebastelei mit MTU und MSS halt ich aber lieber die Klappe. Vielleicht hilft dir ja für den Anfang das hier: http://www.nabooisland.com/publications/pmtud/ . In den rfc's buddeln könnte auch nicht schaden.

Viel Spaß, Klopskuchen
When all else fails, read the instructions .

Marco Gerber

#7 Post by Marco Gerber »

tach

Das data 20 kommt so wie das logfile aussieht vom tcp header.
Beim 3-way Handshake ist es sinnlos, "Daten anzufuegen".
Diese Daten werden dann einfach vom Client interpretiert, sind aber in wirklichkeit nur fiktiv (weil es keine "leeren" Daten gibt, dies aber nur als Anmerkung).

Also musst du zuerst das Problem mit dem data offset Eintrag im TCP Header beheben. Wenn du keine Optionen gesetzt hast (und davon ist auszugehen), dann sollte dort 5 drin stehen beim SYN/ACK Paket (Werte in 32bit -> 5*4byte = 20byte und das ist dann auch die Laenge des TCP Headers ohne Optionen (max uebrigens 15)).

greetz by
Marco

daa531
Posts: 6
Joined: 05. Feb 2006 18:48

#8 Post by daa531 »

Also musst du zuerst das Problem mit dem data offset Eintrag im TCP Header beheben
Ok das habe ich gemacht:

CLIENT (1.Frame):
IP : len 48 10.10.190.5->10.10.190.1 ihl 20 ttl 128 prot TCP
TCP: 1540->23 Seq x4C5DDBDD Ack x00000000 SYN Wnd 16384 MSS 1460

SERVER (1.Frame):
IP : len 48 10.10.190.1->10.10.190.5 ihl 20 ttl 31 prot TCP
TCP: 23->1540 Seq x3B083665 Ack x4C5DDBDE ACK SYN Wnd 16384 MSS 1460

also vom ersten blick sieht das schon gut aus, aber irgendwie komme ich mit der
checksum nicht klar, da stimmt was nicht, jedenfalls zeigt mit etheral incorrect checksum.

hier ist die funktion:

Code: Select all

unsigned short cksum(
/* Absender. */
unsigned long src,
/* Empfaenger. */
unsigned long dest, 
/* Protokoll. */
unsigned short  protokoll, 
/* TCP-Header + Daten. */
unsigned short len)
{
  unsigned long sum = 0;

  sum += (src & 0xffffUL);
  sum += ((src >> 16) & 0xffffUL);
  sum += (dest & 0xffffUL);
  sum += ((dest >> 16) & 0xffffUL);
  sum += protokoll;
  sum += len;

  while (sum  >> 16) {
    sum = (sum & 0xffffUL) + (sum >> 16);
  }

  return (unsigned short)~(sum & 0xffffUL);
}

das muesste doch so OK sein ?

Gruss Olli.


Marco Gerber

#9 Post by Marco Gerber »

tach

Schwer zu sagen. Ich schlage dir vor, die Checksummenberechnung so durchzufuehren, wie sie im Linux Kernel berechnet wird. Dabei musst du darauf achten, dass die Checksummenfelder des jeweiligen Protokolles auf 0 gesetzt ist, um sie korrekt berechnen zu koennen.

In meinem Beispiel wird ein Pseudo Header mit allen notwendigen Daten erstellt:

Code: Select all

struct pseudo_header
{
        unsigned int source_address;
        unsigned int dest_address;
        unsigned char placeholder;
        unsigned char protocol;
        unsigned short tcp_length;
        struct tcphdr tcp;
        char buf[65535];
} pseudo_header;

/*Berechnung im Code*/
                pkt_stct->tcp->check = 0;
                //set tcp pseudo header fields
                pseudo_header.source_address = ip->saddr;
                pseudo_header.dest_address = ip->daddr;
                pseudo_header.placeholder = 0;
                pseudo_header.protocol = IPPROTO_TCP;
                memset (pseudo_header.buf, 0, ETH_FRAME_LEN);
                pseudo_header.tcp_length = htons (ntohs (ip->tot_len) - (ip->ihl * (32 / 8)));
                bcopy ((char *)tcp, (char *) &pseudo_header.tcp, ntohs (ip->tot_len) - (ip->ihl * (32 / 8)));
                //checksum
                ip->check = in_cksum ((unsigned short *) ip, ip->ihl * (32 / 8));
                tcp->check = in_cksum ((unsigned short *) &pseudo_header,ntohs (ip->tot_len) - (ip->ihl * (32 / 8)) + 12);



  //Berechnet das Einerkomplement der Summe aller 32bit Register des Pseudoheaders *addr
unsigned short
in_cksum (unsigned short *addr, int count)
{
        register long sum = 0;
        register unsigned short checksum;

        while (count > 1)
        {
                sum += *addr++;
                count -= 2;
        }
        if (count > 0)
        {
                sum += *(unsigned char *) addr;
        }
        while (sum >> 16)
        {
                sum = (sum & 0xffff) + (sum >> 16);
        }

        checksum = ~sum;

 return checksum;
}
Der Code ist aus TStorm [1], und kann hier frei verwendet werden.

[1] http://squeez.gurit.net/

greetz by
Marco

daa531
Posts: 6
Joined: 05. Feb 2006 18:48

#10 Post by daa531 »

AH jetzt funktioniert der Dreiwege Handshake.

Ich habe gelesen ein Socket (funktion socket) wird aus der IP-Adresse und Portnummer gebildet. Aber nirgends steht wie ?! Welches Buch kann man empfehlen?

Im TCP/IP Volume 3 von Stevens steht da nicht viel drine.
Gruss Olli.

User avatar
Lateralus
prolinux-forum-admin
Posts: 1238
Joined: 05. May 2004 7:35

#11 Post by Lateralus »


daa531
Posts: 6
Joined: 05. Feb 2006 18:48

#12 Post by daa531 »

Im TCP-Header koennen auch OPTIONEN sein,
wie z.B. die MSS Maximum Segment Size.

Ich braeuchte eine genauere Beschreibung von allen 4 16Bit eintraegen:
1.Option ??? (bekomme vom Nachbarn ein wert von 516)
2.Option 1460 das ist die Maximum Segment Size
2.Option ??? (bekomme vom Nachbarn ein wert von 257)
3.Option ??? (bekomme vom Nachbarn ein wert von 1026)

Was bedeuten die 516, 257 und 1026?

Danke im vorraus, gruss Olli.

klopskuchen
prolinux-forum-admin
Posts: 1444
Joined: 26. Jun 2004 21:18
Contact:

#13 Post by klopskuchen »

rfc791, rfc793 und 'man getsockopt'


MfG, Klopskuchen
When all else fails, read the instructions .

Post Reply