6 #include <tpl_drv_common.h>
9 #define UDP_ALLOC_BASE 0xC000
12 void UDP_Initialise();
13 void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
14 // --- Listening Server
15 tVFS_Node *UDP_Server_Init(tInterface *Interface);
16 char *UDP_Server_ReadDir(tVFS_Node *Node, int ID);
17 tVFS_Node UDP_Server_FindDir(tVFS_Node *Node, char *Name);
18 int UDP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data);
19 void UDP_Server_Close(tVFS_Node *Node);
20 // --- Client Channels
21 tVFS_Node *UDP_Channel_Init(tInterface *Interface);
22 Uint64 UDP_Channel_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
23 Uint64 UDP_Channel_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
24 int UDP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data);
25 void UDP_Channel_Close(tVFS_Node *Node);
27 Uint16 UDP_int_AllocatePort();
28 int UDP_int_MarkPortAsUsed(Uint16 Port);
29 void UDP_int_FreePort(Uint16 Port);
32 tSpinlock glUDP_Channels;
33 tUDPChannel *gpUDP_Channels;
34 tSpinlock glUDP_Ports;
35 Uint32 gUDP_Ports[0x10000/32];
36 //tSocketFile gUDP_ServerFile = {NULL, "udps", UDP_Server_Init};
37 tSocketFile gUDP_ClientFile = {NULL, "udpc", UDP_Channel_Init};
41 * \fn void TCP_Initialise()
42 * \brief Initialise the TCP Layer
46 IPStack_AddFile(&gUDP_ClientFile);
47 IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket);
51 * \fn void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
52 * \brief Handles a packet from the IP Layer
54 void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
56 tUDPHeader *hdr = Buffer;
61 Log("[UDP ] hdr->SourcePort = %i", ntohs(hdr->SourcePort));
62 Log("[UDP ] hdr->DestPort = %i", ntohs(hdr->DestPort));
63 Log("[UDP ] hdr->Length = %i", ntohs(hdr->Length));
64 Log("[UDP ] hdr->Checksum = 0x%x", ntohs(hdr->Checksum));
66 // Check registered connections
67 LOCK(&glUDP_Channels);
68 for(chan = gpUDP_Channels;
72 if(chan->Interface != Interface) continue;
73 if(chan->LocalPort != ntohs(hdr->DestPort)) continue;
74 if(chan->RemotePort != ntohs(hdr->SourcePort)) continue;
76 if(Interface->Type == 4) {
77 if(IP4_EQU(chan->RemoteAddr.v4, *(tIPv4*)Address)) continue;
79 else if(Interface->Type == 6) {
80 if(IP6_EQU(chan->RemoteAddr.v6, *(tIPv6*)Address)) continue;
83 Warning("[UDP ] Address type %i unknown", Interface->Type);
84 RELEASE(&glUDP_Channels);
88 // Create the cached packet
89 len = ntohs(hdr->Length);
90 pack = malloc(sizeof(tUDPPacket) + len);
93 memcpy(pack->Data, hdr->Data, len);
95 // Add the packet to the channel's queue
98 chan->QueueEnd->Next = pack;
100 chan->QueueEnd = chan->Queue = pack;
101 RELEASE(&chan->lQueue);
102 RELEASE(&glUDP_Channels);
106 // TODO: Server/Listener
108 RELEASE(&glUDP_Channels);
112 * \brief Send a packet
113 * \param Channel Channel to send the packet from
114 * \param Data Packet data
115 * \param Length Length in bytes of packet data
117 void UDP_SendPacket(tUDPChannel *Channel, void *Data, size_t Length)
121 switch(Channel->Interface->Type)
125 hdr = malloc(sizeof(tUDPHeader)+Length);
126 hdr->SourcePort = htons( Channel->LocalPort );
127 hdr->DestPort = htons( Channel->RemotePort );
128 hdr->Length = htons( sizeof(tUDPHeader) + Length );
129 hdr->Checksum = 0; // Checksum can be zero on IPv4
130 memcpy(hdr->Data, Data, Length);
131 // Pass on the the IPv4 Layer
132 IPv4_SendPacket(Channel->Interface, Channel->RemoteAddr.v4, IP4PROT_UDP, 0, sizeof(tUDPHeader)+Length, hdr);
133 // Free allocated packet
139 // --- Client Channels
140 tVFS_Node *UDP_Channel_Init(tInterface *Interface)
143 new = calloc( sizeof(tUDPChannel), 1 );
144 new->Interface = Interface;
145 new->Node.ImplPtr = new;
146 new->Node.NumACLs = 1;
147 new->Node.ACLs = &gVFS_ACL_EveryoneRW;
148 new->Node.Read = UDP_Channel_Read;
149 new->Node.Write = UDP_Channel_Write;
150 new->Node.IOCtl = UDP_Channel_IOCtl;
151 new->Node.Close = UDP_Channel_Close;
153 LOCK(&glUDP_Channels);
154 new->Next = gpUDP_Channels;
155 gpUDP_Channels = new;
156 RELEASE(&glUDP_Channels);
162 * \brief Read from the channel file (wait for a packet)
164 Uint64 UDP_Channel_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
166 tUDPChannel *chan = Node->ImplPtr;
169 if(chan->LocalPort == 0) return 0;
170 if(chan->RemotePort == 0) return 0;
172 while(chan->Queue == NULL) Threads_Yield();
177 if(chan->Queue == NULL) {
178 RELEASE(&chan->lQueue);
182 chan->Queue = pack->Next;
183 if(!chan->Queue) chan->QueueEnd = NULL;
184 RELEASE(&chan->lQueue);
188 // Clip length to packet length
189 if(Length > pack->Length) Length = pack->Length;
190 // Copy packet data from cache
191 memcpy(Buffer, pack->Data, Length);
192 // Free cached packet
199 * \brief Write to the channel file (send a packet)
201 Uint64 UDP_Channel_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
203 tUDPChannel *chan = Node->ImplPtr;
204 if(chan->RemotePort == 0) return 0;
206 UDP_SendPacket(chan, Buffer, (size_t)Length);
212 * \brief Names for channel IOCtl Calls
214 static const char *casIOCtls_Channel[] = {
222 * \brief Channel IOCtls
224 int UDP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data)
226 tUDPChannel *chan = Node->ImplPtr;
227 ENTER("pNode iID pData", Node, ID, Data);
230 BASE_IOCTLS(DRV_TYPE_MISC, "UDP Channel", 0x100, casIOCtls_Channel);
232 case 4: // getset_localport (returns bool success)
233 if(!Data) LEAVE_RET('i', chan->LocalPort);
234 if(!CheckMem( Data, sizeof(Uint16) ) ) {
235 LOG("Invalid pointer %p", Data);
239 chan->LocalPort = *(Uint16*)Data;
240 // Permissions check (Ports lower than 1024 are root-only)
241 if(chan->LocalPort != 0 && chan->LocalPort < 1024) {
242 if( Threads_GetUID() != 0 ) {
243 LOG("Attempt by non-superuser to listen on port %i", chan->LocalPort);
248 // Allocate a random port if requested
249 if( chan->LocalPort == 0 )
250 chan->LocalPort = UDP_int_AllocatePort();
253 // Else, mark the requested port as used
254 if( UDP_int_MarkPortAsUsed(chan->LocalPort) == 0 ) {
255 LOG("Port %i us currently in use", chan->LocalPort);
263 case 5: // getset_remoteport (returns bool success)
264 if(!Data) LEAVE_RET('i', chan->RemotePort);
265 if(!CheckMem( Data, sizeof(Uint16) ) ) {
266 LOG("Invalid pointer %p", Data);
269 chan->RemotePort = *(Uint16*)Data;
272 case 6: // set_remoteaddr (returns bool success)
273 switch(chan->Interface->Type)
276 if(!CheckMem(Data, sizeof(tIPv4))) {
277 LOG("Invalid pointer %p", Data);
280 chan->RemoteAddr.v4 = *(tIPv4*)Data;
289 * \brief Close and destroy an open channel
291 void UDP_Channel_Close(tVFS_Node *Node)
293 tUDPChannel *chan = Node->ImplPtr;
296 // Remove from the main list first
297 LOCK(&glUDP_Channels);
298 if(gpUDP_Channels == chan)
299 gpUDP_Channels = gpUDP_Channels->Next;
302 for(prev = gpUDP_Channels;
303 prev->Next && prev->Next != chan;
306 Warning("[UDP ] Bookeeping Fail, channel %p is not in main list", chan);
308 prev->Next = prev->Next->Next;
310 RELEASE(&glUDP_Channels);
318 chan->Queue = tmp->Next;
321 RELEASE(&chan->lQueue);
323 // Free channel structure
328 * \return Port Number on success, or zero on failure
330 Uint16 UDP_int_AllocatePort()
335 for( i = UDP_ALLOC_BASE; i < 0x10000; i += 32 )
336 if( gUDP_Ports[i/32] != 0xFFFFFFFF )
338 if(i == 0x10000) return 0;
341 if( !(gUDP_Ports[i/32] & (1 << (i%32))) )
344 RELEASE(&glUDP_Ports);
348 * \brief Allocate a specific port
349 * \return Boolean Success
351 int UDP_int_MarkPortAsUsed(Uint16 Port)
354 if( gUDP_Ports[Port/32] & (1 << (Port%32)) ) {
356 RELEASE(&glUDP_Ports);
358 gUDP_Ports[Port/32] |= 1 << (Port%32);
359 RELEASE(&glUDP_Ports);
364 * \brief Free an allocated port
366 void UDP_int_FreePort(Uint16 Port)
369 gUDP_Ports[Port/32] &= ~(1 << (Port%32));
370 RELEASE(&glUDP_Ports);