3 * - SCTP (Stream Control Transmission Protocol) Handling
6 #include <api_drv_common.h>
9 #define SCTP_ALLOC_BASE 0xC000
12 void SCTP_Initialise();
13 void SCTP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
14 void SCTP_Unreachable(tInterface *Interface, int Code, void *Address, int Length, void *Buffer);
15 void SCTP_SendPacket(tSCTPChannel *Channel, void *Data, size_t Length);
16 // --- Listening Server
17 tVFS_Node *SCTP_Server_Init(tInterface *Interface);
18 char *SCTP_Server_ReadDir(tVFS_Node *Node, int ID);
19 tVFS_Node *SCTP_Server_FindDir(tVFS_Node *Node, const char *Name);
20 int SCTP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data);
21 void SCTP_Server_Close(tVFS_Node *Node);
22 // --- Client Channels
23 tVFS_Node *SCTP_Channel_Init(tInterface *Interface);
24 Uint64 SCTP_Channel_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
25 Uint64 SCTP_Channel_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
26 int SCTP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data);
27 void SCTP_Channel_Close(tVFS_Node *Node);
29 Uint16 SCTP_int_AllocatePort();
30 int SCTP_int_MarkPortAsUsed(Uint16 Port);
31 void SCTP_int_FreePort(Uint16 Port);
34 tMutex glSCTP_Servers;
35 tSCTPServer *gpSCTP_Servers;
37 tMutex glSCTP_Channels;
38 tSCTPChannel *gpSCTP_Channels;
41 Uint32 gSCTP_Ports[0x10000/32];
43 tSocketFile gSCTP_ServerFile = {NULL, "sctps", SCTP_Server_Init};
44 tSocketFile gSCTP_ClientFile = {NULL, "sctpc", SCTP_Channel_Init};
48 * \fn void TCP_Initialise()
49 * \brief Initialise the TCP Layer
51 void SCTP_Initialise()
53 IPStack_AddFile(&gSCTP_ServerFile);
54 IPStack_AddFile(&gSCTP_ClientFile);
55 //IPv4_RegisterCallback(IP4PROT_SCTP, SCTP_GetPacket, SCTP_Unreachable);
56 IPv4_RegisterCallback(IP4PROT_SCTP, SCTP_GetPacket);
60 * \brief Scan a list of tSCTPChannels and find process the first match
61 * \return 0 if no match was found, -1 on error and 1 if a match was found
63 int SCTP_int_ScanList(tSCTPChannel *List, tInterface *Interface, void *Address, int Length, void *Buffer)
65 tSCTPHeader *hdr = Buffer;
74 if(chan->Interface != Interface) continue;
75 if(chan->LocalPort != ntohs(hdr->DestPort)) continue;
76 if(chan->RemotePort != ntohs(hdr->SourcePort)) continue;
78 if(Interface->Type == 4) {
79 if(!IP4_EQU(chan->RemoteAddr.v4, *(tIPv4*)Address)) continue;
81 else if(Interface->Type == 6) {
82 if(!IP6_EQU(chan->RemoteAddr.v6, *(tIPv6*)Address)) continue;
85 Log_Warning("SCTP", "Address type %i unknown", Interface->Type);
86 Mutex_Release(&glSCTP_Channels);
90 Log_Log("SCTP", "Recieved packet for %p", chan);
91 // Create the cached packet
92 len = ntohs(hdr->Length);
93 pack = malloc(sizeof(tSCTPPacket) + len);
96 memcpy(pack->Data, hdr->Data, len);
98 // Add the packet to the channel's queue
99 SHORTLOCK(&chan->lQueue);
101 chan->QueueEnd->Next = pack;
103 chan->QueueEnd = chan->Queue = pack;
104 SHORTREL(&chan->lQueue);
105 Mutex_Release(&glSCTP_Channels);
112 * \fn void SCTP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
113 * \brief Handles a packet from the IP Layer
115 void SCTP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
117 tSCTPHeader *hdr = Buffer;
121 Log_Log("SCTP", "hdr->SourcePort = %i", ntohs(hdr->SourcePort));
122 Log_Log("SCTP", "hdr->DestPort = %i", ntohs(hdr->DestPort));
123 Log_Log("SCTP", "hdr->VerifcationTag = %i", ntohs(hdr->VerifcationTag));
124 Log_Log("SCTP", "hdr->Checksum = 0x%x", ntohs(hdr->Checksum));
126 // Check registered connections
127 Mutex_Acquire(&glSCTP_Channels);
128 ret = SCTP_int_ScanList(gpSCTP_Channels, Interface, Address, Length, Buffer);
129 Mutex_Release(&glSCTP_Channels);
130 if(ret != 0) return ;
133 // TODO: Server/Listener
134 Mutex_Acquire(&glSCTP_Servers);
135 for(srv = gpSCTP_Servers;
139 if(srv->Interface != Interface) continue;
140 if(srv->ListenPort != ntohs(hdr->DestPort)) continue;
141 ret = SCTP_int_ScanList(srv->Channels, Interface, Address, Length, Buffer);
145 Log_Warning("SCTP", "TODO - Add channel on connection");
148 Mutex_Release(&glSCTP_Servers);
153 * \brief Handle an ICMP Unrechable Error
155 void SCTP_Unreachable(tInterface *Interface, int Code, void *Address, int Length, void *Buffer)
161 * \brief Send a packet
162 * \param Channel Channel to send the packet from
163 * \param Data Packet data
164 * \param Length Length in bytes of packet data
166 void SCTP_SendPacket(tSCTPChannel *Channel, void *Data, size_t Length)
170 switch(Channel->Interface->Type)
174 hdr = malloc(sizeof(tSCTPHeader)+Length);
175 hdr->SourcePort = htons( Channel->LocalPort );
176 hdr->DestPort = htons( Channel->RemotePort );
177 hdr->Length = htons( sizeof(tSCTPHeader) + Length );
178 hdr->Checksum = 0; // Checksum can be zero on IPv4
179 memcpy(hdr->Data, Data, Length);
180 // Pass on the the IPv4 Layer
181 IPv4_SendPacket(Channel->Interface, Channel->RemoteAddr.v4, IP4PROT_SCTP, 0, sizeof(tSCTPHeader)+Length, hdr);
182 // Free allocated packet
188 // --- Listening Server
189 tVFS_Node *SCTP_Server_Init(tInterface *Interface)
192 new = calloc( sizeof(tSCTPServer), 1 );
193 if(!new) return NULL;
195 new->Node.ImplPtr = new;
196 new->Node.Flags = VFS_FFLAG_DIRECTORY;
197 new->Node.NumACLs = 1;
198 new->Node.ACLs = &gVFS_ACL_EveryoneRX;
199 new->Node.ReadDir = SCTP_Server_ReadDir;
200 new->Node.FindDir = SCTP_Server_FindDir;
201 new->Node.IOCtl = SCTP_Server_IOCtl;
202 new->Node.Close = SCTP_Server_Close;
204 Mutex_Acquire(&glSCTP_Servers);
205 new->Next = gpSCTP_Servers;
206 gpSCTP_Servers = new;
207 Mutex_Release(&glSCTP_Servers);
213 * \brief Wait for a connection and return its ID in a string
215 char *SCTP_Server_ReadDir(tVFS_Node *Node, int ID)
217 tSCTPServer *srv = Node->ImplPtr;
221 if( srv->ListenPort == 0 ) return NULL;
223 // Lock (so another thread can't collide with us here) and wait for a connection
224 Mutex_Acquire( &srv->Lock );
225 while( srv->NewChannels == NULL ) Threads_Yield();
226 // Pop the connection off the new list
227 chan = srv->NewChannels;
228 srv->NewChannels = chan->Next;
230 Mutex_Release( &srv->Lock );
232 // Create the ID string and return it
234 sprintf(ret, "%i", chan->Node.ImplInt);
240 * \brief Take a string and find the channel
242 tVFS_Node *SCTP_Server_FindDir(tVFS_Node *Node, const char *Name)
244 tSCTPServer *srv = Node->ImplPtr;
248 for(chan = srv->Channels;
252 if( chan->Node.ImplInt < id ) continue;
253 if( chan->Node.ImplInt > id ) break; // Go sorted lists!
262 * \brief Names for server IOCtl Calls
264 static const char *casIOCtls_Server[] = {
270 * \brief Channel IOCtls
272 int SCTP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data)
274 tSCTPServer *srv = Node->ImplPtr;
276 ENTER("pNode iID pData", Node, ID, Data);
279 BASE_IOCTLS(DRV_TYPE_MISC, "SCTP Server", 0x100, casIOCtls_Server);
281 case 4: // getset_localport (returns bool success)
282 if(!Data) LEAVE_RET('i', srv->ListenPort);
283 if(!CheckMem( Data, sizeof(Uint16) ) ) {
284 LOG("Invalid pointer %p", Data);
288 srv->ListenPort = *(Uint16*)Data;
289 // Permissions check (Ports lower than 1024 are root-only)
290 if(srv->ListenPort != 0 && srv->ListenPort < 1024) {
291 if( Threads_GetUID() != 0 ) {
292 LOG("Attempt by non-superuser to listen on port %i", srv->ListenPort);
297 // Allocate a random port if requested
298 if( srv->ListenPort == 0 )
299 srv->ListenPort = SCTP_int_AllocatePort();
302 // Else, mark the requested port as used
303 if( SCTP_int_MarkPortAsUsed(srv->ListenPort) == 0 ) {
304 LOG("Port %i us currently in use", srv->ListenPort);
318 void SCTP_Server_Close(tVFS_Node *Node)
320 tSCTPServer *srv = Node->ImplPtr;
326 // Remove from the main list first
327 Mutex_Acquire(&glSCTP_Servers);
328 if(gpSCTP_Servers == srv)
329 gpSCTP_Servers = gpSCTP_Servers->Next;
332 for(prev = gpSCTP_Servers;
333 prev->Next && prev->Next != srv;
336 Log_Warning("SCTP", "Bookeeping Fail, server %p is not in main list", srv);
338 prev->Next = prev->Next->Next;
340 Mutex_Release(&glSCTP_Servers);
343 Mutex_Acquire(&srv->Lock);
344 for(chan = srv->Channels;
349 SHORTLOCK(&chan->lQueue);
353 chan->Queue = tmp->Next;
356 SHORTREL(&chan->lQueue);
358 // Free channel structure
361 Mutex_Release(&srv->Lock);
366 // --- Client Channels
367 tVFS_Node *SCTP_Channel_Init(tInterface *Interface)
370 new = calloc( sizeof(tSCTPChannel), 1 );
371 new->Interface = Interface;
372 new->Node.ImplPtr = new;
373 new->Node.NumACLs = 1;
374 new->Node.ACLs = &gVFS_ACL_EveryoneRW;
375 new->Node.Read = SCTP_Channel_Read;
376 new->Node.Write = SCTP_Channel_Write;
377 new->Node.IOCtl = SCTP_Channel_IOCtl;
378 new->Node.Close = SCTP_Channel_Close;
380 Mutex_Acquire(&glSCTP_Channels);
381 new->Next = gpSCTP_Channels;
382 gpSCTP_Channels = new;
383 Mutex_Release(&glSCTP_Channels);
389 * \brief Read from the channel file (wait for a packet)
391 Uint64 SCTP_Channel_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
393 tSCTPChannel *chan = Node->ImplPtr;
396 if(chan->LocalPort == 0) return 0;
397 if(chan->RemotePort == 0) return 0;
399 while(chan->Queue == NULL) Threads_Yield();
403 SHORTLOCK(&chan->lQueue);
404 if(chan->Queue == NULL) {
405 SHORTREL(&chan->lQueue);
409 chan->Queue = pack->Next;
410 if(!chan->Queue) chan->QueueEnd = NULL;
411 SHORTREL(&chan->lQueue);
415 // Clip length to packet length
416 if(Length > pack->Length) Length = pack->Length;
417 // Copy packet data from cache
418 memcpy(Buffer, pack->Data, Length);
419 // Free cached packet
426 * \brief Write to the channel file (send a packet)
428 Uint64 SCTP_Channel_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
430 tSCTPChannel *chan = Node->ImplPtr;
431 if(chan->RemotePort == 0) return 0;
433 SCTP_SendPacket(chan, Buffer, (size_t)Length);
439 * \brief Names for channel IOCtl Calls
441 static const char *casIOCtls_Channel[] = {
449 * \brief Channel IOCtls
451 int SCTP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data)
453 tSCTPChannel *chan = Node->ImplPtr;
454 ENTER("pNode iID pData", Node, ID, Data);
457 BASE_IOCTLS(DRV_TYPE_MISC, "SCTP Channel", 0x100, casIOCtls_Channel);
459 case 4: // getset_localport (returns bool success)
460 if(!Data) LEAVE_RET('i', chan->LocalPort);
461 if(!CheckMem( Data, sizeof(Uint16) ) ) {
462 LOG("Invalid pointer %p", Data);
466 chan->LocalPort = *(Uint16*)Data;
467 // Permissions check (Ports lower than 1024 are root-only)
468 if(chan->LocalPort != 0 && chan->LocalPort < 1024) {
469 if( Threads_GetUID() != 0 ) {
470 LOG("Attempt by non-superuser to listen on port %i", chan->LocalPort);
475 // Allocate a random port if requested
476 if( chan->LocalPort == 0 )
477 chan->LocalPort = SCTP_int_AllocatePort();
480 // Else, mark the requested port as used
481 if( SCTP_int_MarkPortAsUsed(chan->LocalPort) == 0 ) {
482 LOG("Port %i us currently in use", chan->LocalPort);
490 case 5: // getset_remoteport (returns bool success)
491 if(!Data) LEAVE_RET('i', chan->RemotePort);
492 if(!CheckMem( Data, sizeof(Uint16) ) ) {
493 LOG("Invalid pointer %p", Data);
496 chan->RemotePort = *(Uint16*)Data;
499 case 6: // set_remoteaddr (returns bool success)
500 switch(chan->Interface->Type)
503 if(!CheckMem(Data, sizeof(tIPv4))) {
504 LOG("Invalid pointer %p", Data);
507 chan->RemoteAddr.v4 = *(tIPv4*)Data;
516 * \brief Close and destroy an open channel
518 void SCTP_Channel_Close(tVFS_Node *Node)
520 tSCTPChannel *chan = Node->ImplPtr;
523 // Remove from the main list first
524 Mutex_Acquire(&glSCTP_Channels);
525 if(gpSCTP_Channels == chan)
526 gpSCTP_Channels = gpSCTP_Channels->Next;
529 for(prev = gpSCTP_Channels;
530 prev->Next && prev->Next != chan;
533 Log_Warning("SCTP", "Bookeeping Fail, channel %p is not in main list", chan);
535 prev->Next = prev->Next->Next;
537 Mutex_Release(&glSCTP_Channels);
540 SHORTLOCK(&chan->lQueue);
545 chan->Queue = tmp->Next;
548 SHORTREL(&chan->lQueue);
550 // Free channel structure
555 * \return Port Number on success, or zero on failure
557 Uint16 SCTP_int_AllocatePort()
560 Mutex_Acquire(&glSCTP_Ports);
562 for( i = SCTP_ALLOC_BASE; i < 0x10000; i += 32 )
563 if( gSCTP_Ports[i/32] != 0xFFFFFFFF )
565 if(i == 0x10000) return 0;
568 if( !(gSCTP_Ports[i/32] & (1 << (i%32))) )
571 Mutex_Release(&glSCTP_Ports);
575 * \brief Allocate a specific port
576 * \return Boolean Success
578 int SCTP_int_MarkPortAsUsed(Uint16 Port)
580 Mutex_Acquire(&glSCTP_Ports);
581 if( gSCTP_Ports[Port/32] & (1 << (Port%32)) ) {
583 Mutex_Release(&glSCTP_Ports);
585 gSCTP_Ports[Port/32] |= 1 << (Port%32);
586 Mutex_Release(&glSCTP_Ports);
591 * \brief Free an allocated port
593 void SCTP_int_FreePort(Uint16 Port)
595 Mutex_Acquire(&glSCTP_Ports);
596 gSCTP_Ports[Port/32] &= ~(1 << (Port%32));
597 Mutex_Release(&glSCTP_Ports);