Sourcecode Fortschritt
-
version = "0.0.2.117 - Rev: 956"
nun auch mit networktypes.h
Wichtige Links z.Z.:
http://www.tcpipguide.com/free/t_TCPConnectionPreparationTransmissionControlBlocksT-2.htm
http://www.cs.northwestern.edu/~agupta/cs340/project2/TCPIP_State_Transition_Diagram.pdf
-
Version 0.0.2.118:
- Ausgabe verbessert
- Mutexes verbessert
- PCI nutzt nun eine Liste statt eines statischen Arrays
- Aufgeräumt
-
Version 0.0.2.119:
- TCP überarbeitet. (BUG: Datentransfer funktioniert nicht.)
-
version = "0.0.2.120 - Rev: 959"
Aktives öffnen und TCP ("SYN") senden (mit strg+w) klappt.
Problem: Internet Checksum ist falsch! (Ursache bisher unklar, da das Senden von SYN ACK oder FIN ACK als server bisher klappt)Ablauf:
- PrettyOS bootet, holt sich per DHCP seine IP
- Man pingt PrettyOS von 192.168.1.23 an, damit der rechner in die ARP-Tabelle eingetragen wird (diese IP steht konkret in strg+w in keyboard.c drinnen, also ändern auf eigenen rechner)
- Man gibt strg+w ein bei PrettyOS um aktiv ein SYN zu senden
Fazit: SYN senden klappt, aber checksum falsch
TCP-Paket: 0402001700000000000000005002ffff88b00000 Checksum: 0x88b0 [incorrect, should be 0x2801 ...]Test mit dem Simulationsprogramm ergibt die korrekte Checksum, also stimmen die Eingangsdaten in die Berechnung für diese nicht.
PS: der datentransfer in rev. 958 klappt (war offenbar ein TCP-Netzproblem)
-
version = "0.0.2.121 - Rev: 960"
Nun erfolgt die korrekte Berechnung der internet checksum. Fehler war im Pseudoheader. Dort fehlte noch die source IP.
Erstes erfolgreiches "active open" mit Senden von SYN, das zum State SYN_SENT führt (wireshark):
8 22.328396 192.168.1.97 192.168.1.23 TCP 60 blackjack > telnet [SYN] Seq=0 Win=65535 Len=0blackjack steht für den gewählten Port mit der Nr. 1025.
static uint16_t getFreeSocket() { static uint16_t srcPort = 1025; return srcPort++; }Um den kompletten Handshake zu sehen, gibt es einen einfachen Weg:
- telnet dienst (server) in Windows starten
- firewall tcp port 23 öffnen
- strg+w (active open mit SYN)
Resultat:
http://www.henkessoft.de/OS_Dev/Bilder/rev.960_TCP_TELNET_ACTIVE_OPEN.PNGSYN - SYN ACK - ACK

MrX hat auf die Schnelle einen kleinen TCP-Server geschrieben:
#include <SFML/Network.hpp> #include <iostream> #include <string> #include <cstdint> sf::TcpSocket Socket; void Func() { while(true) { char buffer[512]; size_t size; if(Socket.Receive(buffer, 512, size) == sf::Socket::Disconnected) return; buffer[size] = 0; std::cout << buffer; } } sf::Thread Thr(&Func); int main() { sf::TcpListener Listener; Listener.SetBlocking(true); uint16_t port; std::cout << "Bitte Port eingeben: "; std::cin >> port; Listener.Listen(port); std::cout << "Server lauscht... "; Listener.Accept(Socket); std::cout << "Verbunden." << std::endl; Thr.Launch(); std::string str; std::cin >> str; while(str != "exit") { Socket.Send(str.c_str(), str.length()); std::cin >> str; } return(0); }Download der exe-Datei zusammen mit dem Sourcecode: http://www.henkessoft.de/OS_Dev/Downloads/TCPServer.zip (EXE etwas weiter entwickelt bezüglich Ausgaben)
-
version = "0.0.2.122 - Rev: 960"
- Beseitigung eines Fehlers, der nur ab und zu aufgetreten ist: versehentlich wurde mit bigEndian-Zahlen gerechnet, dabei verschiebt sich der Überlauf - falls vorhanden - nach rechts, da wir immer mit littleEndian-Zahlen "rechnen". Daher immer erst nach littleEndian umwandeln, dann rechnen, anschließend zurück nach bigEndian umwandeln:
htonl(htonl(tcp->sequenceNumber)+1)<--- EDIT: das zweite htonl müsste ein ntohl sein, wurde inzwischen behoben.
- internetChecksumTest.cpp (von MrX, für code::blocks umgeschrieben) in /tools
-
version = "0.0.2.123 - Rev: 961"
ntohs/ntohl und htons/htonl im Code aus Gründen der Dokumentation geordnet.
vgl. http://beej.us/guide/bgnet/output/html/multipage/htonsman.html
Die Inhalte der Macros sind für IA32 bei x86 zufällig gleich, aber es geht um den Weg (Netz <---> Host), der verschieden ist.
// htonl = Host To Network Long // htons = Host To Network Short #define htons(v) ((((v) >> 8) & 0xFF) | (((v) & 0xFF) << 8)) #define htonl(v) ((((v) >> 24) & 0xFF) | (((v) >> 8) & 0xFF00) | (((v) & 0xFF00) << 8) | (((v) & 0xFF) << 24)) // ntohl = Network To Host Long // ntohs = Network To Host Short #define ntohs(v) htons(v) #define ntohl(v) htonl(v)Diese Macros machen den Code mehr portabel, denn wenn z.B. die CPU gemäß Big Endian arbeitet dann ist die Umsetzung eben einfach ein "no operation".
Beispiel aus tpc.c:
tcp_send(connection, 0, 0, ACK_FLAG, tcp->acknowledgmentNumber /*seqNumber*/, htonl(ntohl(tcp->sequenceNumber)+tcpDataLength) /*ackNumber*/);
-
version = "0.0.2.124 - Rev: 962"
Ausgaben bei networking etwas vereinfacht.
-
version = "0.0.2.125 - Rev: 963"
Kleine Veränderungen in networking Ausgabe
-
Version 0.0.2.126:
- netutils.c/h gebildet. Enthält ntohl (u.ä.) sowie checksum-Funktionen
- Syscall-Aufruf verwendet festgelegte Register (vermeidet Fehler mit -fomit-frame-pointer)
- Code wird nun mit -fomit-frame-pointer gebaut
- Kleinigkeiten
-
Version 0.0.2.127:
- IPs und MACs jetzt mit memcmp verglichen
- IP_address und MAC_address in IP und MAC umbenannt
-
version = "0.0.2.128 - Rev: 966" (versehentlich zu hoch gedreht in ckernel.c)
PrettyOS goes to INTERNET via routing (FIRST TEST)
if(retchar == 'w') // Create & Bind connection { connection = tcp_createConnection(); // 94.142.241.111 auf Port 23 uint8_t destIP[4] ={94,142,241,111}; memcpy(connection->remoteSocket.IP, destIP, 4); connection->remoteSocket.port = 23; uint8_t sourceIP[4] ={IP_1,IP_2,IP_3,IP_4}; //HACK memcpy(connection->localSocket.IP, sourceIP, 4); network_adapter_t* adapter = network_getAdapter(sourceIP); printf("network adapter: %Xh\n", adapter); // check connection->adapter = adapter; if(adapter) { tcp_connect(connection); } return 0; }Da wird die Starwars Story erzählt von einem sehr geschwätzigen telnet server (IP: 94.142.241.111). Vielen Dank an Cuervo für diesen Bomben-Tipp!
Foto: http://www.henkessoft.de/OS_Dev/Bilder/rev.966_INTERNET.PNG
Wer dies nachstellen möchte, benötigt eine rtl8139 Netzwerkkarte, und bitte die router-mac (erhält man oft mit arp -a aus dem arp-cache) und die IP/RIP (gleich), die man von DHCP erhält, in network.h eintragen. Das muss alles noch automatisiert werden.
Start ist z.Z. mit strg+w
HTTP geht noch nicht (fehlt noch die ACH-Number aus dem SYN-ACK des handshake), kommt demnächst wenn der TCB in connection gefüttert wird.

-
-
version = "0.0.2.129 - Rev: 967"
- Zuerst Senden (also erstes ACK nach handshake) auf www.henkessoft.de port 80 (HTTP)
- bei TIME_WAIT wird connection zerstört, damit man diese mit strg+w neu aufbauen kann.Anwendung:
strg+w (verb. aufbauen),
strg+x (Daten werden geschickt: "GET / HTTP/1.0\r\nHost: www.henkessoft.de\r\n\r\n")(Die Homepage rast durch)
Foto: http://www.henkessoft.de/OS_Dev/Bilder/rev.967_INTERNET_HTTP.PNG

-
version = "0.0.2.130 - Rev: 968"
- srand, rand eingebaut für Erzeugung von ISS in tcp.c
- Extra eine eigene Übungsseite gebaut: http://www.henkessoft.de/OS_Dev/PrettyOS.htmif(retchar == 'w') // Create & Bind connection { connection = tcp_createConnection(); // uint8_t destIP[4] ={94,142,241,111}; // 94.142.241.111 at Port 23, starwars story uint8_t destIP[4] = {82,100,220,68}; // www.henkessoft.de Port 80 memcpy(connection->remoteSocket.IP, destIP, 4); connection->remoteSocket.port = 80; uint8_t sourceIP[4] ={IP_1,IP_2,IP_3,IP_4}; //HACK memcpy(connection->localSocket.IP, sourceIP, 4); network_adapter_t* adapter = network_getAdapter(sourceIP); printf("network adapter: %Xh\n", adapter); // check connection->adapter = adapter; if(adapter) { tcp_connect(connection); } return 0; } if(retchar == 'x') // send data to the connection { tcp_send(connection, "GET /OS_Dev/PrettyOS.htm HTTP/1.1\r\nHost: www.henkessoft.de\r\nConnection: close\r\n\r\n", strlen("GET /OS_Dev/PrettyOS.htm HTTP/1.1\r\nHost: www.henkessoft.de\r\nConnection: close\r\n\r\n"), ACK_FLAG, connection->tcb.SND_NXT, connection->tcb.SND_UNA); return 0; }Klappt gut!
HTTP hat natürlich im eigentlichen Kernel nichts verloren. Dies hier in keyboard ist sozusagen ein "Steckbrett".
-
version = "0.0.2.131 - Rev: 969"
- Gateway IP aus DHCP ACK gezogen und bei adpater->... eingehängt.
-
version = "0.0.2.132 - Rev: 970"
- Subnet Mask aus DHCP ACK gezogen und bei adpater->... eingehängt.
-
version = "0.0.2.132 - Rev: 970" <--- Simulation mit qemu:
qemu gestartet mit TAP1/TAP2 unter Windows XP.Foto: http://www.henkessoft.de/OS_Dev/Bilder/rev.970_INTERNET_HTTP.PNG
strg+w baut die connection via router zum Internet auf Port 80 (HTTP) auf, strg+x fordert Daten mittels GET ... an.
DHCP läuft hierbei nicht sauber zum Ende durch (bleibt bei OFFER hängen, wobwi REQUEST gesendet wird, man muss mit TAP1 Aktivierung/Deaktivierung toggeln). Daher sind die HACKs wichtig.
So wie es aussieht, kann man TCP/IP damit trotz des DHCP-Problems testen.
qemu batch datei:
qemu.exe -fda FloppyImage.img -soundhw pcspk -net nic,model=rtl8139,addr=1A,macaddr=00:12:12:12:12:12 -net tap,ifname=TAP2 -net user -localtimeDie Emulation mit qemu funktioniert auch mit dem pcnet-Treiber.

pcnet anstelle rtl8139Noch besser: Da qemu und der HOST zusammen NAT spielen, werden die PrettyOS-Pakete unter der IP des HOST verschickt, sodass man in wireshark jedes Paket sieht: http://www.henkessoft.de/OS_Dev/Bilder/rev.970_INTERNET_HTTP_WIRESHARK.PNG
PrOS = PrettyOS, web = Website
Send Recv flags seq# ack# nextseq# window --------------------------------------------------------------------------- PrOS web SYN 0 - 65535 web PrOS SYN ACK 0 1 65535 PrOS web ACK 1 1 65535 PrOS web PSH ACK 1 1 82 65535 GET /OS_Dev/... web PrOS ACK 1 82 248 65535 1. Teil Header web PrOS ACK 248 82 755 65535 OK 2. Teil <!DOCTYPE ... PrOS web ACK 82 755 64781 web PrOS FIN ACK 755 82 65535 PrOS web ACK 82 756 64781Anmerkung: beim ersten Datenpaket vom Webserver steht: TCP segment of a reassembled PDU
HTTP Protokollschicht:
GET /OS_Dev/PrettyOS.htm HTTP/1.1 Host: www.henkessoft.de Connection: close HTTP/1.1 200 OK Date: Mon, 20 Jun 2011 19:45:22 GMT Server: Apache/2.2.17 Last-Modified: Sun, 19 Jun 2011 16:32:48 GMT ETag: "1e07e25-1fb-4a6132b4e8c00" Accept-Ranges: bytes Content-Length: 507 Connection: close Content-Type: text/html <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta content="text/html;charset=ISO-8859-15" http-equiv="Content-Type"> <title>PrettyOS</title> </head> <body> <h1>Hallo, hier spricht PrettyOS. </h1> <h1>Ich wurde in C und Assembler erstellt. </h1> <h1>Es gibt eine Community, die mich hingebungsvoll pflegt und weiter entwickelt.<br> </h1> <h1><a href="http://www.c-plusplus.net/forum/f62">http://www.c-plusplus.net/forumf62</a></h1> <br> </body> </html>
-
version = "0.0.2.133 - Rev: 971"
- tcp etwas überarbeitet: mehr Ausgaben über connection (addr) und port
- bei strg+b und strg+w (gemischt) geht noch einiges durcheinander!
-
version = "0.0.2.134 - Rev: 972"
- strg+c: listet alle connections auf
- tcp kleine änderungen