9 #define TCP_MIN_DYNPORT 0x1000
10 #define TCP_MAX_HALFOPEN 1024 // Should be enough
13 void TCP_Initialise();
14 void TCP_StartConnection(tTCPConnection *Conn);
15 void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
16 void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header);
17 Uint16 TCP_GetUnusedPort();
18 int TCP_AllocatePort(Uint16 Port);
19 int TCP_DeallocatePort(Uint16 Port);
21 tVFS_Node *TCP_Server_Init(tInterface *Interface);
22 char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos);
23 tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, char *Name);
24 int TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data);
25 void TCP_Server_Close(tVFS_Node *Node);
27 tVFS_Node *TCP_Client_Init(tInterface *Interface);
28 Uint64 TCP_Client_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
29 Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
30 int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data);
31 void TCP_Client_Close(tVFS_Node *Node);
34 tSocketFile gTCP_ServerFile = {NULL, "tcps", TCP_Server_Init};
35 tSocketFile gTCP_ClientFile = {NULL, "tcpc", TCP_Client_Init};
38 int giTCP_NumHalfopen = 0;
39 tSpinlock glTCP_Listeners;
40 tTCPListener *gTCP_Listeners;
41 tSpinlock glTCP_OutbountCons;
42 tTCPConnection *gTCP_OutbountCons;
43 Uint32 gaTCP_PortBitmap[0x800];
44 int giTCP_NextOutPort = TCP_MIN_DYNPORT;
48 * \fn void TCP_Initialise()
49 * \brief Initialise the TCP Layer
53 IPStack_AddFile(&gTCP_ServerFile);
54 IPStack_AddFile(&gTCP_ClientFile);
55 IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket);
59 * \brief Open a connection to another host using TCP
61 void TCP_StartConnection(tTCPConnection *Conn)
65 hdr->SourcePort = Conn->LocalPort;
66 hdr->DestPort = Conn->RemotePort;
67 hdr->SequenceNumber = rand();
68 hdr->DataOffset = (sizeof(tTCPHeader)+3)/4;
69 hdr->Flags = TCP_FLAG_SYN;
71 // Send a TCP SYN to the target to open the connection
76 * \fn void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
77 * \brief Handles a packet from the IP Layer
79 void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
81 tTCPHeader *hdr = Buffer;
85 Log("[TCP ] sizeof(tTCPHeader) = %i", sizeof(tTCPHeader));
86 Log("[TCP ] DestPort = %i", ntohs(hdr->DestPort));
87 Log("[TCP ] DestPort = %i", ntohs(hdr->DestPort));
88 Log("[TCP ] SequenceNumber = %i", ntohl(hdr->SequenceNumber));
89 Log("[TCP ] AcknowlegementNumber = %i", ntohl(hdr->AcknowlegementNumber));
90 Log("[TCP ] DataOffset = %i", hdr->DataOffset >> 4);
91 Log("[TCP ] Flags = {");
92 Log("[TCP ] CWR = %B", !!(hdr->Flags & TCP_FLAG_CWR));
93 Log("[TCP ] ECE = %B", !!(hdr->Flags & TCP_FLAG_ECE));
94 Log("[TCP ] URG = %B", !!(hdr->Flags & TCP_FLAG_URG));
95 Log("[TCP ] ACK = %B", !!(hdr->Flags & TCP_FLAG_ACK));
96 Log("[TCP ] PSH = %B", !!(hdr->Flags & TCP_FLAG_PSH));
97 Log("[TCP ] RST = %B", !!(hdr->Flags & TCP_FLAG_RST));
98 Log("[TCP ] SYN = %B", !!(hdr->Flags & TCP_FLAG_SYN));
99 Log("[TCP ] FIN = %B", !!(hdr->Flags & TCP_FLAG_FIN));
101 Log("[TCP ] WindowSize = %i", htons(hdr->WindowSize));
102 Log("[TCP ] Checksum = 0x%x", htons(hdr->Checksum));
103 Log("[TCP ] UrgentPointer = 0x%x", htons(hdr->UrgentPointer));
107 for( srv = gTCP_Listeners; srv; srv = srv->Next )
109 // Check if the server is active
110 if(srv->Port == 0) continue;
111 // Check the interface
112 if(srv->Interface && srv->Interface != Interface) continue;
113 // Check the destination port
114 if(srv->Port != hdr->DestPort) continue;
116 // Is this in an established connection?
117 for( conn = srv->Connections; conn; conn = conn->Next )
119 // Check that it is coming in on the same interface
120 if(conn->Interface != Interface) continue;
123 if(conn->RemotePort != hdr->SourcePort) continue;
126 if(conn->Interface->Type == 6 && !IP6_EQU(conn->RemoteIP.v6, *(tIPv6*)Address))
128 if(conn->Interface->Type == 4 && !IP4_EQU(conn->RemoteIP.v4, *(tIPv4*)Address))
131 // We have a response!
132 TCP_INT_HandleConnectionPacket(conn, hdr)
137 // Open a new connection (well, check that it's a SYN)
145 // Check Open Connections
147 for( conn = gTCP_OutbountCons; conn; conn = conn->Next )
149 // Check that it is coming in on the same interface
150 if(conn->Interface != Interface) continue;
153 if(conn->RemotePort != hdr->SourcePort) continue;
156 if(conn->Interface->Type == 6 && !IP6_EQU(conn->RemoteIP.v6, *(tIPv6*)Address))
158 if(conn->Interface->Type == 4 && !IP4_EQU(conn->RemoteIP.v4, *(tIPv4*)Address))
161 TCP_INT_HandleConnectionPacket(conn, hdr)
167 * \brief Handles a packet sent to a specific connection
169 void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header)
175 * \fn Uint16 TCP_GetUnusedPort()
176 * \brief Gets an unused port and allocates it
178 Uint16 TCP_GetUnusedPort()
182 // Get Next outbound port
183 ret = giTCP_NextOutPort++;
184 while( gaTCP_PortBitmap[ret/32] & (1 << (ret%32)) )
188 if(giTCP_NextOutPort == 0x10000) {
189 ret = giTCP_NextOutPort = TCP_MIN_DYNPORT;
193 // Mark the new port as used
194 gaTCP_PortBitmap[ret/32] |= 1 << (ret%32);
200 * \fn int TCP_AllocatePort(Uint16 Port)
201 * \brief Marks a port as used
203 int TCP_AllocatePort(Uint16 Port)
205 // Check if the port has already been allocated
206 if( gaTCP_PortBitmap[Port/32] & (1 << (Port%32)) )
210 gaTCP_PortBitmap[Port/32] |= 1 << (Port%32);
216 * \fn int TCP_DeallocatePort(Uint16 Port)
217 * \brief Marks a port as unused
219 int TCP_DeallocatePort(Uint16 Port)
221 // Check if the port has already been allocated
222 if( !(gaTCP_PortBitmap[Port/32] & (1 << (Port%32))) )
226 gaTCP_PortBitmap[Port/32] &= ~(1 << (Port%32));
232 tVFS_Node *TCP_Server_Init(tInterface *Interface)
234 tTCPListener *srv = malloc( sizeof(tTCPListener) );
236 srv->Interface = Interface;
239 srv->Connections = NULL;
241 srv->Node.ImplPtr = srv;
242 srv->Node.NumACLs = 1;
243 srv->Node.ACLs = &gVFS_ACL_EveryoneRW;
244 srv->Node.ReadDir = TCP_Server_ReadDir;
245 srv->Node.FindDir = TCP_Server_FindDir;
246 srv->Node.IOCtl = TCP_Server_IOCtl;
247 srv->Node.Close = TCP_Server_Close;
249 LOCK(&glTCP_Listeners);
250 srv->Next = gTCP_Listeners;
251 gTCP_Listeners = srv;
252 RELEASE(&glTCP_Listeners);
258 * \brief Wait for a new connection and return the connection ID
259 * \note Blocks until a new connection is made
260 * \param Node Server node
261 * \param Pos Position (ignored)
263 char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos)
265 tTCPListener *srv = Node->ImplPtr;
266 tTCPConnection *conn;
269 while( srv->NewConnections == NULL ) Threads_Yield();
271 conn = srv->NewConnections;
272 srv->NewConnections = conn->Next;
275 itoa(ret, conn->ImplInt, 16, '0', 8);
280 * \brief Gets a client connection node
281 * \param Node Server node
282 * \param Name Hexadecimal ID of the node
284 tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, char *Name)
289 int TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data)
291 tTCPListener *srv = Node->ImplPtr;
295 case 4: // Get/Set Port
296 if(!Data) // Get Port
299 if(srv->Port) // Wait, you can't CHANGE the port
302 if(!CheckMem(Data, sizeof(Uint16))) // Sanity check
306 if(Threads_GetUID() != 0
307 && *(Uint16*)Data != 0
308 && *(Uint16*)Data < 1024)
311 // TODO: Check if a port is in use
314 srv->Port = *(Uint16*)Data;
315 if(srv->Port == 0) // Allocate a random port
316 srv->Port = TCP_GetUnusedPort();
317 else // Else, mark this as used
318 TCP_AllocatePort(srv->Port);
324 void TCP_Server_Close(tVFS_Node *Node)
330 tVFS_Node *TCP_Client_Init(tInterface *Interface)
332 tTCPConnection *conn = malloc( sizeof(tTCPConnection) );
334 conn->State = TCP_ST_CLOSED;
335 conn->Interface = Interface;
337 conn->RemotePort = 0;
338 memset( &conn->RemoteIP, 0, sizeof(conn->RemoteIP) );
340 conn->Node.ImplPtr = conn;
341 conn->Node.NumACLs = 1;
342 conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
343 conn->Node.Read = TCP_Client_Read;
344 conn->Node.Write = TCP_Client_Write;
345 conn->Node.IOCtl = TCP_Client_IOCtl;
346 conn->Node.Close = TCP_Client_Close;
348 LOCK(&glTCP_OutbountCons);
349 conn->Next = gTCP_OutbountCons;
350 gTCP_OutbountCons = conn;
351 RELEASE(&glTCP_OutbountCons);
356 Uint64 TCP_Client_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
361 Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
366 int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data)
368 tTCPConnection *conn = Node->ImplPtr;
372 case 4: // Get/Set local port
374 return conn->LocalPort;
375 if(conn->State != TCP_ST_CLOSED)
377 if(!CheckMem(Data, sizeof(Uint16)))
380 if(Threads_GetUID() != 0 && *(Uint16*)Data < 1024)
383 conn->LocalPort = *(Uint16*)Data;
386 case 5: // Get/Set remote port
387 if(!Data) return conn->RemotePort;
388 if(conn->State != TCP_ST_CLOSED) return -1;
389 if(!CheckMem(Data, sizeof(Uint16))) return -1;
390 conn->RemotePort = *(Uint16*)Data;
393 case 6: // Set Remote IP
394 if( conn->State != TCP_ST_CLOSED )
396 if( conn->Interface->Type == 4 )
398 if(!CheckMem(Data, sizeof(tIPv4))) return -1;
399 conn->RemoteIP.v4 = *(tIPv4*)Data;
401 else if( conn->Interface->Type == 6 )
403 if(!CheckMem(Data, sizeof(tIPv6))) return -1;
404 conn->RemoteIP.v6 = *(tIPv6*)Data;
409 if(conn->LocalPort == -1)
410 conn->LocalPort = TCP_GetUnusedPort();
411 if(conn->RemotePort == -1)
414 TCP_StartConnection(conn);
421 void TCP_Client_Close(tVFS_Node *Node)