Sourcecode Fortschritt
-
Version 0.0.2.93:
- Initialisierungsreihenfolge verbessert: U.a. wird Video früher installiert (-> je eher, desto besser. Ermöglicht frühere Debugausgaben).
- printf unterstützt nun %M und %I für die Ausgabe von IP und MAC Adressen. Angewendet im Netzwerkcode
- Strg+A resultiert nicht mehr in #PF, wenn keine Netzwerkkarte vorhanden ist
- Code aufgeräumt
-
Version 0.0.2.94:
- Analyse der DHCP-Option-Bytes vereinfacht
- c/s/vs/v/printf geben nun Anzahl geschriebener Zeichen zurück
- i2Hex (und damit auch c/s/vs/v/printf) gibt kein h mehr am Ende hexadezimaler Zahlen aus
- Ausgabe der ARP-Tabelle verbessert
-
version = "0.0.2.95 - Rev: 934"
SIP ersatzlos gestrichen
Problem: Zusammenhang netzwork adapter und IP geht verloren
-
version = "0.0.2.96 - Rev: 935"
Fehler bei ACK auf DHCP_Inform korrigiert. Your IP (dhcp->yiaddr) wird nur übernommen, wenn ungleich 0.0.0.0:
static void useDHCP_IP(network_adapter_t* adapter, dhcp_t* dhcp) { if (dhcp->yiaddr[0] || dhcp->yiaddr[1] || dhcp->yiaddr[2] || dhcp->yiaddr[3]) { for(uint8_t i = 0; i < 4; i++) adapter->IP_address[i] = dhcp->yiaddr[i]; } }
-
version = "0.0.2.97 - Rev: 936"
Endlich habe ich einen Trick gefunden, wie man auch die Antworten des DHCP-Servers in wireshark von einem anderen PC im LAN beobachten kann. Man muss bei den Anfragen die Forderung stellen, dass die Antwort an alle (BROADCAST) gesendet wird.
Beweis-Foto: http://www.henkessoft.de/OS_Dev/Bilder/rev936.PNG
Nachdem dieser Ablauf nun eindeutig demonstriert werden konnte, bitte ich um Reproduktion auch an anderer Stelle.
-
Version 0.0.2.98:
- Unterstützung von Parametern beim Programmstart
- Hello-Userprogramm zeigt übergebene Parameter an
- Verbessertes makefile für other_userprogs
-
Tests von Cuervo mit der vorhergehenden Vesrion:
- DHCP_Release funktioniert. Wenn der DHCP-Server will, wird es als abgelaufen angezeigt
- Wir müssen das Angebot aus OFFER verwenden für REQUEST anstelle der konstanten RIP (das kann der Server anders sehen ^^) aus network.h
- HOST NAME angeben bei den optionsFotos (Cuervo): http://prettyos.fanofblitzbasic.de/PrettyNWPics.zip
MrX: deine Version produziert einen #PF F000EF6F eip: 115391
ckernel.c: shell auskommentiert, "executeFile("1:/ttt.ELF", 0, 0); // TEST" eingefügt, klappt bestens. Bitte in Ordnung bringen.
-
version = "0.0.2.99 - Rev: 938"
shell auskommentiert, ttt wird testweise ausgeführt.
Netzwerk: Hostname "PrettyOS" eingeführt bei DHCP, DHCP_Request übernimmt IP aus DHCP_Offer.
-
Version 0.0.2.100:
- cpu.c: Es wird überprüft, ob cpuid unterstützt wird; Funktionen zum Lesen und Schreiben des MSR implementiert
- memory.txt geupdated und erweitert
- Bugfix/Hack: Shell nimmt nun argv/argc-Parameter beim Start
- Projektmappen: Verbesserte Intellisense-Kompatibilität durch Dummy-Header VCcompatibility.h und verbesserte Includepfad-Einstellungen
-
Version 0.0.2.101:
- Neuer Bugfix-Versuch. argc/argv nun via user stack übergeben.
-
Bitte darauf achten, dass bei den cross-tools die enthaltenen binutils, darunter auch ld.exe nicht mehr zu einem lauffähigen produkt führen (#PF).
MrX wird demnächst ein neues bundle für die crosstools hochladen.
http://kloke-witten.dyndns.org/~philipp/bin.zip <--- wenn es eilt
-
Version 0.0.2.102:
- Parameterübergabe wieder über eax/ecx
- Fehlerbehandlung im Floppytreiber verbessert
- Konsolen überarbeitet (Stabilität, Code vereinfacht)
-
version = "0.0.2.103 - Rev: 942"
TCP weiter ausgebaut:
- Senden klappt
- Checksum (UDP, TCP) bewirkt #PF
- 3-way-handshake: SYN kann bereits mit SYN ACK beantwortet werden
-
version = "0.0.2.105 - Rev: 944" (beim nächsten Mal bitte stehen lassen, wurde offenbar eine übersprungen)
checksum für UDP: 0 (wegen DHCP)
checksum für TCP: aktiviert, wireshark validiert diese aber als "incorrect"Checksum: 0x7754 [incorrect, should be 0xba47 (maybe caused by "TCP checksum offload"?)]
-
version = "0.0.2.105 - Rev: 944"
Parameter "protocol" ergänzt:
uint16_t udptcpCalculateChecksum(void* p, size_t length, uint8_t sourceIp[4], uint8_t destinationIp[4], uint16_t protocol)Checksum falsch.
-
version = "0.0.2.106 - Rev: 945"
- TCP-Checksum noch nicht korrekt
- internetChecksum (Fkt. wird bereits bei ip und icmp eingesetzt) mit verwendet
-
version = "0.0.2.107 - Rev: 946"
- tcp checksum noch nicht korrekt, aber schon nahe dran ^^
-
version = "0.0.2.108 - Rev: 947"
- tcp checksum noch falsch
- pseudoheader byteweise aufgebaut für besseren Überblickuint16_t udptcpCalculateChecksum(void* p, uint16_t length, uint8_t srcIP[4], uint8_t destIP[4], uint16_t protocol) { uint32_t pseudoHeaderChecksum = 0; uint8_t header[12]; // Pseudo header uint8_t* data = header; uint8_t count = 12; // pseudo header contains 12 byte for (uint8_t i=0; i<4; i++) { header[i] = srcIP[i]; } for (uint8_t i=4; i<8; i++) { header[i] = destIP[i-4]; } header[8] = 0; header[9] = protocol; header[10] = length & 0xFF; header[11] = (length >> 8) & 0xFF; while (count > 1) { // pseudo header contains 6 WORD pseudoHeaderChecksum += (data[0] << 8) | data[1]; // Big Endian data += 2; count -= 2; } return internetChecksum(p, length, pseudoHeaderChecksum); // util.c } // compute internet checksum for "count" bytes beginning at location "addr" uint16_t internetChecksum(void* addr, size_t count, uint32_t pseudoHeaderChecksum) { uint32_t sum = pseudoHeaderChecksum; uint8_t* data = addr; while (count > 1) // inner loop { sum += (data[0] << 8) | data[1]; // Big Endian data += 2; count -= 2; } if (count > 0) // add left-over byte, if any { sum += data[0] << 8; } while (sum >> 16) // fold 32-bit sum to 16 bits { sum = (sum & 0xFFFF) + (sum >> 16); } return ~sum & 0xFFFF; } void tcpSend(network_adapter_t* adapter, void* data, uint32_t length, uint16_t srcPort, uint8_t srcIP[4], uint16_t destPort, uint8_t destIP[4], tcpFlags flags, uint32_t seqNumber, uint32_t ackNumber) { //... packet->checksum = 0; // for checksum calculation packet->checksum = htons(udptcpCalculateChecksum((void*)packet, length + sizeof(tcpPacket_t), srcIP, destIP, 6)); ipv4_send(adapter, packet, length + sizeof(tcpPacket_t), destIP, 6); //... }
Wenn man header[8] ... [11] dreht, wird die differenz kleiner.
Hier ein Hexpaket:
0013d41127a50010a70f0a0c0800450000280000400080067707c0a80161c0a8011700170607000000001cb30fc95012fffff3750000000000000000
Checksum: 0xf375 [incorrect, should be 0xf96f (maybe caused by "TCP checksum offload"?)]Hex-Code:
IP-Paket: 450000280000400080067707c0a80161c0a80117
TCP-Paket: 00170607000000001cb30fc95012fffff3750000Internet Protocol Version 4, Src: 192.168.1.97 (192.168.1.97), Dst: 192.168.1.23 (192.168.1.23)
Transmission Control Protocol, Src Port: telnet (23), Dst Port: simba-cs (1543), Seq: 0, Ack: 1, Len: 0
(Len ist hier die Datenlänge)chat: <ehenkes>TCP-Paket: 00170607000000001cb30fc95012fffff3750000 <ehenkes>Src: 192.168.1.97 (192.168.1.97), Dst: 192.168.1.23 (192.168.1.23) <ehenkes>raus kommen muss: 0xf96f <ehenkes>daten gibts keine, reiner header <ehenkes>udptcpCalculateChecksum(void* p, uint16_t length, uint8_t srcIP[4], uint8_t destIP[4], uint16_t protocol) <ehenkes>p zeigt auf den tcp-header <ehenkes>length = sizeof(tcp_header) <ehenkes>IPs sind klar <ehenkes>MrX: gut so? <MrX>ja <ehenkes>Header length: 20 bytes <ehenkes>des TCP headers
Weitere Pakete: (IPs gleich)
<ehenkes>0017062800000000c56a32495012ffff007827a5 Checksum: 0x0078 [incorrect, should be 0x0672 (maybe caused by "TCP checksum offload"?)] <ehenkes>0017062900000000591dc44a5012fffffc630604 Checksum: 0xfc63 [incorrect, should be 0x025e (maybe caused by "TCP checksum offload"?)]
erzeugt mit:
header[11] = 0; header[10] = protocol; header[9] = length & 0xFF; header[8] = (length >> 8) & 0xFF;
Nach Simulation:
<MrX>Übrigens weiß ich, wie Du deine Variante lauffähig kriegst.header[8] = 0; header[9] = protocol; header[11] = length & 0xFF; header[10] = (length >> 8) & 0xFF;
-
version = "0.0.2.109 - Rev: 948"
MEILENSTEIN: http://www.c-plusplus.net/forum/p2078201#2078201
Erfolg! (thx to Mrx for simulating TCP checksum)tcp.h:
typedef struct { uint8_t src[4]; uint8_t dest[4]; uint8_t res; uint8_t prot; uint16_t length; } __attribute__((packed)) tcpPseudoHeader_t;
network.c:
uint16_t udptcpCalculateChecksum(void* p, uint16_t length, uint8_t srcIP[4], uint8_t destIP[4], uint16_t protocol) { tcpPseudoHeader_t pseudo; for (uint8_t i=0; i<4; i++) { pseudo.src[i] = srcIP[i]; pseudo.dest[i] = destIP[i]; } pseudo.length = htons(length); pseudo.prot = protocol; pseudo.res = 0; uint32_t pseudoHeaderChecksum = 0; uint8_t count = 12; // pseudo header contains 12 byte uint8_t* data = (uint8_t*)&pseudo; while (count > 1) { // pseudo header contains 6 WORD pseudoHeaderChecksum += (data[0] << 8) | data[1]; // Big Endian data += 2; count -= 2; } return internetChecksum(p, length, pseudoHeaderChecksum); // util.c }
... und schon geht der Weg zum ESTABLISHED:
12 14.042894 192.168.1.23 192.168.1.97 TCP 62 shockwave > telnet [SYN] Seq=0 Win=65535 Len=0 MSS=1460 SACK_PERM=1
13 14.052667 192.168.1.97 192.168.1.23 TCP 60 telnet > shockwave [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0
14 14.052691 192.168.1.23 192.168.1.97 TCP 54 shockwave > telnet [ACK] Seq=1 Ack=1 Win=65535 Len=0syn - syn ack - ack (TCP 3-way-handshake)
Mit dieser Version kann man erste versuche bei TCP/IP unternehmen, z.B. TELNET nutzen: http://www.henkessoft.de/OS_Dev/Bilder/rev.948_TCP_TELNET.PNG
http://www.manpagez.com/man/1/telnet/ <--- Kommandos
-
rev. 949:
TCP weiter ausgebaut, vor allem werden nun die Transition States angezeigt:
(CLOSED -->) LISTEN --> SYN_RECEIVED --> ESTABLISHEDLength: 66 Rcv: 00-10-A7-0F-0A-0C Transm.: 00-13-D4-11-27-A5 Ethernet 2. Prot. type: IP. IP version: 4, IP Header Length: 20 byte TCP: src port: 1232 dest port: 23 URG: 0 ACK: 0 PSH: 0 RST: 0 SYN: 1 FIN: 0 TCP prev. state: CLOSED TCP set from CLOSED to LISTEN. TCP curr. state: LISTEN Length: 66 Rcv: 00-10-A7-0F-0A-0C Transm.: 00-13-D4-11-27-A5 Ethernet 2. Prot. type: IP. IP version: 4, IP Header Length: 20 byte TCP: src port: 1232 dest port: 23 URG: 0 ACK: 0 PSH: 0 RST: 0 SYN: 1 FIN: 0 TCP prev. state: LISTEN EthernetSend: length: 54. >>> Transmission starts <<< Physical Address of Tx Buffer = 014051D8h packet sent. TCP curr. state: SYN_RECEIVED Length: 64 Rcv: 00-10-A7-0F-0A-0C Transm.: 00-13-D4-11-27-A5 Ethernet 2. Prot. type: IP. IP version: 4, IP Header Length: 20 byte TCP: src port: 1232 dest port: 23 URG: 0 ACK: 1 PSH: 0 RST: 0 SYN: 0 FIN: 0 TCP prev. state: SYN_RECEIVED TCP curr. state: ESTABLISHED
Da wir mit CLOSED starten und noch keine sockets bauen, müssen wir den Übergang zu LISTEN noch etwas künstlich durchführen:
void tcpListen(network_adapter_t* adapter) { adapter->TCP_PrevState = adapter->TCP_CurrState; adapter->TCP_CurrState = LISTEN; // TODO: more action needed? } Erst ab dort geht es geregelt weiter: [cpp]if (tcp->SYN && !tcp->ACK) // SYN { adapter->TCP_PrevState = adapter->TCP_CurrState; if (adapter->TCP_CurrState == CLOSED) { printf("TCP set from CLOSED to LISTEN.\n"); tcpListen(adapter); } else if (adapter->TCP_CurrState == LISTEN) { tcpSend(adapter, 0, 0, htons(tcp->destPort), adapter->IP_address, htons(tcp->sourcePort), transmittingIP, SYN_ACK_FLAG, 0 /*seqNumber*/ , tcp->sequenceNumber+htonl(1) /*ackNumber*/); adapter->TCP_CurrState = SYN_RECEIVED; } //...
telnet baut zumindest einen "Kontakt" zu uns auf, erwartet aber wohl mehr von seinem "Server" als nur einen 3-way-handshake:
Microsoft Telnet> open 192.168.1.97 Verbindungsaufbau zu 192.168.1.97...