From 845ed09f3edef0c836200df6afbd6bfbc7b3fef6 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 11 Feb 2010 13:15:26 +0800 Subject: [PATCH] Work on IP/TCP Stack - TCP now registered with IPv4 - Added debug code and started on TCP server support - Fixed bitfield error (removed the bitfields for portability) --- Kernel/Makefile.BuildNum | 2 +- Modules/IPStack/ipv4.c | 7 ++- Modules/IPStack/main.c | 33 +++++------ Modules/IPStack/tcp.c | 116 ++++++++++++++++++++++++++++++++++++--- Modules/IPStack/tcp.h | 60 ++++++++++++++++---- 5 files changed, 176 insertions(+), 42 deletions(-) diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index d5ebf2f6..da45617b 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 1431 +BUILD_NUM = 1438 diff --git a/Modules/IPStack/ipv4.c b/Modules/IPStack/ipv4.c index 3a1a893b..5fe99abc 100644 --- a/Modules/IPStack/ipv4.c +++ b/Modules/IPStack/ipv4.c @@ -12,7 +12,6 @@ extern tInterface *gIP_Interfaces; extern void ICMP_Initialise(); extern int ICMP_Ping(tInterface *Interface, tIPv4 Addr); -extern void UDP_Initialise(); extern tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address); // === PROTOTYPES === @@ -34,7 +33,6 @@ tIPCallback gaIPv4_Callbacks[256]; int IPv4_Initialise() { ICMP_Initialise(); - UDP_Initialise(); Link_RegisterType(IPV4_ETHERNET_ID, IPv4_int_GetPacket); return 1; } @@ -135,7 +133,10 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff data = &hdr->Options[0]; // Send it on - gaIPv4_Callbacks[hdr->Protocol] (iface, &hdr->Source, dataLength, data); + if( gaIPv4_Callbacks[hdr->Protocol] ) + gaIPv4_Callbacks[hdr->Protocol] (iface, &hdr->Source, dataLength, data); + else + Log("[IPv4 ] Unknown Protocol %i", hdr->Protocol); } /** diff --git a/Modules/IPStack/main.c b/Modules/IPStack/main.c index 60bc787d..37caba8c 100644 --- a/Modules/IPStack/main.c +++ b/Modules/IPStack/main.c @@ -17,6 +17,8 @@ // === IMPORTS === extern int ARP_Initialise(); +extern void UDP_Initialise(); +extern void TCP_Initialise(); extern int IPv4_Initialise(); extern int IPv4_Ping(tInterface *Iface, tIPv4 Addr); @@ -66,6 +68,8 @@ int IPStack_Install(char **Arguments) // Install Handlers ARP_Initialise(); IPv4_Initialise(); + TCP_Initialise(); + UDP_Initialise(); if(Arguments) { @@ -111,26 +115,24 @@ char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos) return NULL; } - name = malloc(6); - name[0] = 'i'; - name[1] = 'p'; + name = malloc(4); // Create the name Pos = iface->Node.ImplInt; if(Pos < 10) { - name[2] = '0' + Pos; - name[3] = '\0'; + name[0] = '0' + Pos; + name[1] = '\0'; } else if(Pos < 100) { - name[2] = '0' + Pos/10; - name[3] = '0' + Pos%10; - name[4] = '\0'; + name[0] = '0' + Pos/10; + name[1] = '0' + Pos%10; + name[2] = '\0'; } else { - name[2] = '0' + Pos/100; - name[3] = '0' + (Pos/10)%10; - name[4] = '0' + Pos%10; - name[5] = '\0'; + name[0] = '0' + Pos/100; + name[1] = '0' + (Pos/10)%10; + name[2] = '0' + Pos%10; + name[3] = '\0'; } LEAVE('s', name); @@ -148,12 +150,7 @@ tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, char *Name) ENTER("pNode sName", Node, Name); - if(Name[0] != 'i' || Name[1] != 'p') { - LEAVE('n'); - return NULL; - } - - i = 2; num = 0; + i = 0; num = 0; while('0' <= Name[i] && Name[i] <= '9') { num *= 10; diff --git a/Modules/IPStack/tcp.c b/Modules/IPStack/tcp.c index cfc3efc0..36b7d914 100644 --- a/Modules/IPStack/tcp.c +++ b/Modules/IPStack/tcp.c @@ -3,14 +3,17 @@ * - TCP Handling */ #include "ipstack.h" +#include "ipv4.h" #include "tcp.h" #define TCP_MIN_DYNPORT 0x1000 +#define TCP_MAX_HALFOPEN 1024 // Should be enough // === PROTOTYPES === void TCP_Initialise(); -void *TCP_Open(tInterface *Interface, Uint16 LocalPort, void *Address, Uint16 Port); +void TCP_StartConnection(tTCPConnection *Conn); void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer); +void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header); Uint16 TCP_GetUnusedPort(); int TCP_AllocatePort(Uint16 Port); int TCP_DeallocatePort(Uint16 Port); @@ -33,7 +36,9 @@ tSocketFile gTCP_ClientFile = {NULL, "tcpc", TCP_Client_Init}; // === GLOBALS === int giTCP_NumHalfopen = 0; +tSpinlock glTCP_Listeners; tTCPListener *gTCP_Listeners; +tSpinlock glTCP_OutbountCons; tTCPConnection *gTCP_OutbountCons; Uint32 gaTCP_PortBitmap[0x800]; int giTCP_NextOutPort = TCP_MIN_DYNPORT; @@ -47,10 +52,10 @@ void TCP_Initialise() { IPStack_AddFile(&gTCP_ServerFile); IPStack_AddFile(&gTCP_ClientFile); + IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket); } /** - * \fn void *TCP_Open(tInterface *Interface, Uint16 LocalPort, void *Address, Uint16 Port) * \brief Open a connection to another host using TCP */ void TCP_StartConnection(tTCPConnection *Conn) @@ -70,6 +75,26 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe tTCPListener *srv; tTCPConnection *conn; + Log("[TCP ] sizeof(tTCPHeader) = %i", sizeof(tTCPHeader)); + Log("[TCP ] DestPort = %i", ntohs(hdr->DestPort)); + Log("[TCP ] DestPort = %i", ntohs(hdr->DestPort)); + Log("[TCP ] SequenceNumber = %i", ntohl(hdr->SequenceNumber)); + Log("[TCP ] AcknowlegementNumber = %i", ntohl(hdr->AcknowlegementNumber)); + Log("[TCP ] DataOffset = %i", hdr->DataOffset >> 4); + Log("[TCP ] Flags = {"); + Log("[TCP ] CWR = %B", !!(hdr->Flags & TCP_FLAG_CWR)); + Log("[TCP ] ECE = %B", !!(hdr->Flags & TCP_FLAG_ECE)); + Log("[TCP ] URG = %B", !!(hdr->Flags & TCP_FLAG_URG)); + Log("[TCP ] ACK = %B", !!(hdr->Flags & TCP_FLAG_ACK)); + Log("[TCP ] PSH = %B", !!(hdr->Flags & TCP_FLAG_PSH)); + Log("[TCP ] RST = %B", !!(hdr->Flags & TCP_FLAG_RST)); + Log("[TCP ] SYN = %B", !!(hdr->Flags & TCP_FLAG_SYN)); + Log("[TCP ] FIN = %B", !!(hdr->Flags & TCP_FLAG_FIN)); + Log("[TCP ] }"); + Log("[TCP ] WindowSize = %i", htons(hdr->WindowSize)); + Log("[TCP ] Checksum = 0x%x", htons(hdr->Checksum)); + Log("[TCP ] UrgentPointer = 0x%x", htons(hdr->UrgentPointer)); + // Check Servers { for( srv = gTCP_Listeners; srv; srv = srv->Next ) @@ -95,7 +120,7 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe continue; // We have a response! - //TODO + TCP_INT_HandleConnectionPacket(conn, hdr) return; } @@ -112,11 +137,31 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe { for( conn = gTCP_OutbountCons; conn; conn = conn->Next ) { - // TODO + // Check that it is coming in on the same interface + if(conn->Interface != Interface) continue; + + // Check Source Port + if(conn->RemotePort != hdr->SourcePort) continue; + + // Check Source IP + if(conn->Interface->Type == 6 && !IP6_EQU(conn->RemoteIP.v6, *(tIPv6*)Address)) + continue; + if(conn->Interface->Type == 4 && !IP4_EQU(conn->RemoteIP.v4, *(tIPv4*)Address)) + continue; + + TCP_INT_HandleConnectionPacket(conn, hdr) } } } +/** + * \brief Handles a packet sent to a specific connection + */ +void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header) +{ + +} + /** * \fn Uint16 TCP_GetUnusedPort() * \brief Gets an unused port and allocates it @@ -177,7 +222,26 @@ int TCP_DeallocatePort(Uint16 Port) // --- Server tVFS_Node *TCP_Server_Init(tInterface *Interface) { - return NULL; + tTCPListener *srv = malloc( sizeof(tTCPListener) ); + + srv->Interface = Interface; + srv->Port = 0; + srv->Connections = NULL; + srv->Next = NULL; + srv->Node.ImplPtr = srv; + srv->Node.NumACLs = 1; + srv->Node.ACLs = &gVFS_ACL_EveryoneRW; + srv->Node.ReadDir = TCP_Server_ReadDir; + srv->Node.FindDir = TCP_Server_FindDir; + srv->Node.IOCtl = TCP_Server_IOCtl; + srv->Node.Close = TCP_Server_Close; + + LOCK(&glTCP_Listeners); + srv->Next = gTCP_Listeners; + gTCP_Listeners = srv; + RELEASE(&glTCP_Listeners); + + return &srv->Node; } char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos) @@ -192,9 +256,38 @@ tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, char *Name) int TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data) { + tTCPListener *srv = Node->ImplPtr; + + switch(ID) + { + case 4: // Get/Set Port + if(!Data) + return srv->Port; + + if(srv->Port) + return -1; + + if(!CheckMem(Data, sizeof(Uint16))) + return -1; + + if(Threads_GetUID() != 0 && *(Uint16*)Data < 1024) + return -1; + + srv->Port = *(Uint16*)Data; + if(srv->Port == 0) + srv->Port = TCP_GetUnusedPort(); + else + TCP_AllocatePort(srv->Port); + return srv->Port; + } return 0; } +void TCP_Server_Close(tVFS_Node *Node) +{ + free(Node->ImplPtr); +} + // --- Client tVFS_Node *TCP_Client_Init(tInterface *Interface) { @@ -214,6 +307,11 @@ tVFS_Node *TCP_Client_Init(tInterface *Interface) conn->Node.IOCtl = TCP_Client_IOCtl; conn->Node.Close = TCP_Client_Close; + LOCK(&glTCP_OutbountCons); + conn->Next = gTCP_OutbountCons; + gTCP_OutbountCons = conn; + RELEASE(&glTCP_OutbountCons); + return &conn->Node; } @@ -233,7 +331,7 @@ int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data) switch(ID) { - case 5: // Get/Set local port + case 4: // Get/Set local port if(!Data) return conn->LocalPort; if(conn->State != TCP_ST_CLOSED) @@ -247,14 +345,14 @@ int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data) conn->LocalPort = *(Uint16*)Data; return 0; - case 6: // Get/Set remote port + case 5: // Get/Set remote port if(!Data) return conn->RemotePort; if(conn->State != TCP_ST_CLOSED) return -1; if(!CheckMem(Data, sizeof(Uint16))) return -1; conn->RemotePort = *(Uint16*)Data; return 0; - case 7: // Set Remote IP + case 6: // Set Remote IP if( conn->State != TCP_ST_CLOSED ) return -1; if( conn->Interface->Type == 4 ) @@ -269,7 +367,7 @@ int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data) } return 0; - case 8: // Connect + case 7: // Connect if(conn->LocalPort == -1) conn->LocalPort = TCP_GetUnusedPort(); if(conn->RemotePort == -1) diff --git a/Modules/IPStack/tcp.h b/Modules/IPStack/tcp.h index 0b641950..cd6caf09 100644 --- a/Modules/IPStack/tcp.h +++ b/Modules/IPStack/tcp.h @@ -17,26 +17,46 @@ struct sTCPHeader Uint16 DestPort; Uint32 SequenceNumber; Uint32 AcknowlegementNumber; + #if 0 struct { - unsigned DataOffset: 4; // Size of the header in 32-bit words unsigned Reserved: 4; - }; - struct { - unsigned CWR: 1; // Congestion Window Reduced - unsigned ECE: 1; // ECN-Echo - unsigned URG: 1; // Urgent pointer is significant - unsigned ACK: 1; // Acknowlegement field is significant - unsigned PSH: 1; // Push Function - unsigned RST: 1; // Reset Connection - unsigned SYN: 1; // Synchronise Sequence Numbers + unsigned DataOffset: 4; // Size of the header in 32-bit words + } __attribute__ ((packed)); + #else + Uint8 DataOffset; + #endif + #if 0 + struct { // Lowest to Highest unsigned FIN: 1; // Last packet - } Flags; + unsigned SYN: 1; // Synchronise Sequence Numbers + unsigned RST: 1; // Reset Connection + unsigned PSH: 1; // Push Function + unsigned ACK: 1; // Acknowlegement field is significant + unsigned URG: 1; // Urgent pointer is significant + unsigned ECE: 1; // ECN-Echo + unsigned CWR: 1; // Congestion Window Reduced + } __attribute__ ((packed)) Flags; + #else + Uint8 Flags; + #endif Uint16 WindowSize; Uint16 Checksum; Uint16 UrgentPointer; Uint8 Options[]; +} __attribute__ ((packed)); + +enum eTCPFlags +{ + TCP_FLAG_FIN = 0x01, + TCP_FLAG_SYN = 0x02, + TCP_FLAG_RST = 0x04, + TCP_FLAG_PSH = 0x08, + TCP_FLAG_ACK = 0x10, + TCP_FLAG_URG = 0x20, + TCP_FLAG_ECE = 0x40, + TCP_FLAG_CWR = 0x80 }; struct sTCPListener @@ -44,6 +64,8 @@ struct sTCPListener struct sTCPListener *Next; Uint16 Port; tInterface *Interface; + tVFS_Node Node; + int NextID; tTCPConnection *Connections; }; @@ -55,6 +77,22 @@ struct sTCPConnection Uint16 RemotePort; tVFS_Node Node; + int NextSequenceSend; + int NextSequenceRcv; + + int nQueuedPackets; + struct { + int Sequence; + void *Data; + } *QueuedPackets; + + + int nFuturePackets; + struct { + int SequenceNum; + void *Data; + } **FuturePackets; + tInterface *Interface; union { tIPv4 v4; -- 2.20.1