cfc3efc08c715c95011e673dfdc239f22565174a
[tpg/acess2.git] / Modules / IPStack / tcp.c
1 /*
2  * Acess2 IP Stack
3  * - TCP Handling
4  */
5 #include "ipstack.h"
6 #include "tcp.h"
7
8 #define TCP_MIN_DYNPORT 0x1000
9
10 // === PROTOTYPES ===
11 void    TCP_Initialise();
12 void    *TCP_Open(tInterface *Interface, Uint16 LocalPort, void *Address, Uint16 Port);
13 void    TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
14 Uint16  TCP_GetUnusedPort();
15  int    TCP_AllocatePort(Uint16 Port);
16  int    TCP_DeallocatePort(Uint16 Port);
17 // --- Server
18 tVFS_Node       *TCP_Server_Init(tInterface *Interface);
19 char    *TCP_Server_ReadDir(tVFS_Node *Node, int Pos);
20 tVFS_Node       *TCP_Server_FindDir(tVFS_Node *Node, char *Name);
21  int    TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data);
22 void    TCP_Server_Close(tVFS_Node *Node);
23 // --- Client
24 tVFS_Node       *TCP_Client_Init(tInterface *Interface);
25 Uint64  TCP_Client_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
26 Uint64  TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
27  int    TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data);
28 void    TCP_Client_Close(tVFS_Node *Node);
29
30 // === TEMPLATES ===
31 tSocketFile     gTCP_ServerFile = {NULL, "tcps", TCP_Server_Init};
32 tSocketFile     gTCP_ClientFile = {NULL, "tcpc", TCP_Client_Init};
33
34 // === GLOBALS ===
35  int    giTCP_NumHalfopen = 0;
36 tTCPListener    *gTCP_Listeners;
37 tTCPConnection  *gTCP_OutbountCons;
38 Uint32  gaTCP_PortBitmap[0x800];
39  int    giTCP_NextOutPort = TCP_MIN_DYNPORT;
40
41 // === CODE ===
42 /**
43  * \fn void TCP_Initialise()
44  * \brief Initialise the TCP Layer
45  */
46 void TCP_Initialise()
47 {
48         IPStack_AddFile(&gTCP_ServerFile);
49         IPStack_AddFile(&gTCP_ClientFile);
50 }
51
52 /**
53  * \fn void *TCP_Open(tInterface *Interface, Uint16 LocalPort, void *Address, Uint16 Port)
54  * \brief Open a connection to another host using TCP
55  */
56 void TCP_StartConnection(tTCPConnection *Conn)
57 {       
58         // SEND PACKET
59         // Send a TCP SYN to the target to open the connection
60         return ;
61 }
62
63 /**
64  * \fn void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
65  * \brief Handles a packet from the IP Layer
66  */
67 void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
68 {
69         tTCPHeader      *hdr = Buffer;
70         tTCPListener    *srv;
71         tTCPConnection  *conn;
72         
73         // Check Servers
74         {
75                 for( srv = gTCP_Listeners; srv; srv = srv->Next )
76                 {
77                         // Check the interface
78                         if(srv->Interface && srv->Interface != Interface)       continue;
79                         // Check the destination port
80                         if(srv->Port != hdr->DestPort)  continue;
81                         
82                         // Is this in an established connection?
83                         for( conn = srv->Connections; conn; conn = conn->Next )
84                         {
85                                 // Check that it is coming in on the same interface
86                                 if(conn->Interface != Interface)        continue;
87                                 
88                                 // Check Source Port
89                                 if(conn->RemotePort != hdr->SourcePort) continue;
90                                 
91                                 // Check Source IP
92                                 if(conn->Interface->Type == 6 && !IP6_EQU(conn->RemoteIP.v6, *(tIPv6*)Address))
93                                         continue;
94                                 if(conn->Interface->Type == 4 && !IP4_EQU(conn->RemoteIP.v4, *(tIPv4*)Address))
95                                         continue;
96                                 
97                                 // We have a response!
98                                 //TODO
99                                 
100                                 return;
101                         }
102                         
103                         // Open a new connection (well, check that it's a SYN)
104                         //TODO
105                         
106                         break;
107                 }
108         }
109         
110         
111         // Check Open Connections
112         {
113                 for( conn = gTCP_OutbountCons; conn; conn = conn->Next )
114                 {
115                         // TODO
116                 }
117         }
118 }
119
120 /**
121  * \fn Uint16 TCP_GetUnusedPort()
122  * \brief Gets an unused port and allocates it
123  */
124 Uint16 TCP_GetUnusedPort()
125 {
126         Uint16  ret;
127         
128         // Get Next outbound port
129         ret = giTCP_NextOutPort++;
130         while( gaTCP_PortBitmap[ret/32] & (1 << (ret%32)) )
131         {
132                 ret ++;
133                 giTCP_NextOutPort++;
134                 if(giTCP_NextOutPort == 0x10000) {
135                         ret = giTCP_NextOutPort = TCP_MIN_DYNPORT;
136                 }
137         }
138         
139         // Mark the new port as used
140         gaTCP_PortBitmap[ret/32] |= 1 << (ret%32);
141         
142         return ret;
143 }
144
145 /**
146  * \fn int TCP_AllocatePort(Uint16 Port)
147  * \brief Marks a port as used
148  */
149 int TCP_AllocatePort(Uint16 Port)
150 {
151         // Check if the port has already been allocated
152         if( gaTCP_PortBitmap[Port/32] & (1 << (Port%32)) )
153                 return 0;
154         
155         // Allocate
156         gaTCP_PortBitmap[Port/32] |= 1 << (Port%32);
157         
158         return 1;
159 }
160
161 /**
162  * \fn int TCP_DeallocatePort(Uint16 Port)
163  * \brief Marks a port as unused
164  */
165 int TCP_DeallocatePort(Uint16 Port)
166 {
167         // Check if the port has already been allocated
168         if( !(gaTCP_PortBitmap[Port/32] & (1 << (Port%32))) )
169                 return 0;
170         
171         // Allocate
172         gaTCP_PortBitmap[Port/32] &= ~(1 << (Port%32));
173         
174         return 1;
175 }
176
177 // --- Server
178 tVFS_Node *TCP_Server_Init(tInterface *Interface)
179 {
180         return NULL;
181 }
182
183 char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos)
184 {
185         return NULL;
186 }
187
188 tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, char *Name)
189 {
190         return NULL;
191 }
192
193 int TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data)
194 {
195         return 0;
196 }
197
198 // --- Client
199 tVFS_Node *TCP_Client_Init(tInterface *Interface)
200 {
201         tTCPConnection  *conn = malloc( sizeof(tTCPConnection) );
202         
203         conn->State = TCP_ST_CLOSED;
204         conn->Interface = Interface;
205         conn->LocalPort = 0;
206         conn->RemotePort = 0;
207         memset( &conn->RemoteIP, 0, sizeof(conn->RemoteIP) );
208         
209         conn->Node.ImplPtr = conn;
210         conn->Node.NumACLs = 1;
211         conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
212         conn->Node.Read = TCP_Client_Read;
213         conn->Node.Write = TCP_Client_Write;
214         conn->Node.IOCtl = TCP_Client_IOCtl;
215         conn->Node.Close = TCP_Client_Close;
216         
217         return &conn->Node;
218 }
219
220 Uint64 TCP_Client_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
221 {
222         return 0;
223 }
224
225 Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
226 {
227         return 0;
228 }
229
230 int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data)
231 {
232         tTCPConnection  *conn = Node->ImplPtr;
233         
234         switch(ID)
235         {
236         case 5: // Get/Set local port
237                 if(!Data)
238                         return conn->LocalPort;
239                 if(conn->State != TCP_ST_CLOSED)
240                         return -1;
241                 if(!CheckMem(Data, sizeof(Uint16)))
242                         return -1;
243                 
244                 if(Threads_GetUID() != 0 && *(Uint16*)Data < 1024)
245                         return -1;
246                 
247                 conn->LocalPort = *(Uint16*)Data;
248                 return 0;
249         
250         case 6: // Get/Set remote port
251                 if(!Data)       return conn->RemotePort;
252                 if(conn->State != TCP_ST_CLOSED)        return -1;
253                 if(!CheckMem(Data, sizeof(Uint16)))     return -1;
254                 conn->RemotePort = *(Uint16*)Data;
255                 return 0;
256         
257         case 7: // Set Remote IP
258                 if( conn->State != TCP_ST_CLOSED )
259                         return -1;
260                 if( conn->Interface->Type == 4 )
261                 {
262                         if(!CheckMem(Data, sizeof(tIPv4)))      return -1;
263                         conn->RemoteIP.v4 = *(tIPv4*)Data;
264                 }
265                 else if( conn->Interface->Type == 6 )
266                 {
267                         if(!CheckMem(Data, sizeof(tIPv6)))      return -1;
268                         conn->RemoteIP.v6 = *(tIPv6*)Data;
269                 }
270                 return 0;
271         
272         case 8: // Connect
273                 if(conn->LocalPort == -1)
274                         conn->LocalPort = TCP_GetUnusedPort();
275                 if(conn->RemotePort == -1)
276                         return 0;
277                 
278                 TCP_StartConnection(conn);
279                 return 1;
280         }
281         
282         return 0;
283 }
284
285 void TCP_Client_Close(tVFS_Node *Node)
286 {
287         free(Node->ImplPtr);
288 }

UCC git Repository :: git.ucc.asn.au