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 void UDP_Unreachable(tInterface *Interface, int Code, void *Address, int Length, void *Buffer);
15 void UDP_SendPacketTo(tUDPChannel *Channel, int AddrType, void *Address, Uint16 Port, void *Data, size_t Length);
16 // --- Client Channels
17 tVFS_Node *UDP_Channel_Init(tInterface *Interface);
18 Uint64 UDP_Channel_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
19 Uint64 UDP_Channel_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
20 int UDP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data);
21 void UDP_Channel_Close(tVFS_Node *Node);
23 Uint16 UDP_int_AllocatePort();
24 int UDP_int_MarkPortAsUsed(Uint16 Port);
25 void UDP_int_FreePort(Uint16 Port);
28 tMutex glUDP_Channels;
29 tUDPChannel *gpUDP_Channels;
32 Uint32 gUDP_Ports[0x10000/32];
34 tSocketFile gUDP_SocketFile = {NULL, "udp", UDP_Channel_Init};
38 * \fn void TCP_Initialise()
39 * \brief Initialise the TCP Layer
43 IPStack_AddFile(&gUDP_SocketFile);
44 //IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket, UDP_Unreachable);
45 IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket);
49 * \brief Scan a list of tUDPChannels and find process the first match
50 * \return 0 if no match was found, -1 on error and 1 if a match was found
52 int UDP_int_ScanList(tUDPChannel *List, tInterface *Interface, void *Address, int Length, void *Buffer)
54 tUDPHeader *hdr = Buffer;
63 // Match local endpoint
64 if(chan->Interface && chan->Interface != Interface) continue;
65 if(chan->LocalPort != ntohs(hdr->DestPort)) continue;
67 // Check for remote port restriction
68 if(chan->Remote.Port && chan->Remote.Port != ntohs(hdr->SourcePort))
70 // Check for remote address restriction
73 if(chan->Remote.AddrType != Interface->Type) continue;
74 if(!IPStack_CompareAddress(Interface->Type, Address,
75 &chan->Remote.Addr, chan->RemoteMask)
80 Log_Log("UDP", "Recieved packet for %p", chan);
81 // Create the cached packet
82 len = ntohs(hdr->Length);
83 pack = malloc(sizeof(tUDPPacket) + len);
85 memcpy(&pack->Remote.Addr, Address, IPStack_GetAddressSize(Interface->Type));
86 pack->Remote.Port = ntohs(hdr->SourcePort);
88 memcpy(pack->Data, hdr->Data, len);
90 // Add the packet to the channel's queue
91 SHORTLOCK(&chan->lQueue);
93 chan->QueueEnd->Next = pack;
95 chan->QueueEnd = chan->Queue = pack;
96 SHORTREL(&chan->lQueue);
97 Mutex_Release(&glUDP_Channels);
104 * \fn void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
105 * \brief Handles a packet from the IP Layer
107 void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
109 tUDPHeader *hdr = Buffer;
111 Log_Debug("UDP", "hdr->SourcePort = %i", ntohs(hdr->SourcePort));
112 Log_Debug("UDP", "hdr->DestPort = %i", ntohs(hdr->DestPort));
113 Log_Debug("UDP", "hdr->Length = %i", ntohs(hdr->Length));
114 Log_Debug("UDP", "hdr->Checksum = 0x%x", ntohs(hdr->Checksum));
116 // Check registered connections
117 Mutex_Acquire(&glUDP_Channels);
118 UDP_int_ScanList(gpUDP_Channels, Interface, Address, Length, Buffer);
119 Mutex_Release(&glUDP_Channels);
123 * \brief Handle an ICMP Unrechable Error
125 void UDP_Unreachable(tInterface *Interface, int Code, void *Address, int Length, void *Buffer)
131 * \brief Send a packet
132 * \param Channel Channel to send the packet from
133 * \param Data Packet data
134 * \param Length Length in bytes of packet data
136 void UDP_SendPacketTo(tUDPChannel *Channel, int AddrType, void *Address, Uint16 Port, void *Data, size_t Length)
140 if(Channel->Interface && Channel->Interface->Type != AddrType) return ;
146 hdr = malloc(sizeof(tUDPHeader)+Length);
147 hdr->SourcePort = htons( Channel->LocalPort );
148 hdr->DestPort = htons( Port );
149 hdr->Length = htons( sizeof(tUDPHeader) + Length );
150 hdr->Checksum = 0; // Checksum can be zero on IPv4
151 memcpy(hdr->Data, Data, Length);
152 // Pass on the the IPv4 Layer
153 // TODO: What if Channel->Interface is NULL here?
154 IPv4_SendPacket(Channel->Interface, *(tIPv4*)Address, IP4PROT_UDP, 0, sizeof(tUDPHeader)+Length, hdr);
155 // Free allocated packet
161 // --- Client Channels
162 tVFS_Node *UDP_Channel_Init(tInterface *Interface)
165 new = calloc( sizeof(tUDPChannel), 1 );
166 new->Interface = Interface;
167 new->Node.ImplPtr = new;
168 new->Node.NumACLs = 1;
169 new->Node.ACLs = &gVFS_ACL_EveryoneRW;
170 new->Node.Read = UDP_Channel_Read;
171 new->Node.Write = UDP_Channel_Write;
172 new->Node.IOCtl = UDP_Channel_IOCtl;
173 new->Node.Close = UDP_Channel_Close;
175 Mutex_Acquire(&glUDP_Channels);
176 new->Next = gpUDP_Channels;
177 gpUDP_Channels = new;
178 Mutex_Release(&glUDP_Channels);
184 * \brief Read from the channel file (wait for a packet)
186 Uint64 UDP_Channel_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
188 tUDPChannel *chan = Node->ImplPtr;
193 if(chan->LocalPort == 0) return 0;
195 while(chan->Queue == NULL) Threads_Yield();
199 VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "UDP_Channel_Read");
200 SHORTLOCK(&chan->lQueue);
201 if(chan->Queue == NULL) {
202 SHORTREL(&chan->lQueue);
206 chan->Queue = pack->Next;
208 chan->QueueEnd = NULL;
209 VFS_MarkAvaliable(Node, 0); // Nothing left
211 SHORTREL(&chan->lQueue);
215 // Check that the header fits
217 ofs = 4 + IPStack_GetAddressSize(pack->Remote.AddrType);
224 ep->Port = pack->Remote.Port;
225 ep->AddrType = pack->Remote.AddrType;
226 memcpy(&ep->Addr, &pack->Remote.Addr, IPStack_GetAddressSize(pack->Remote.AddrType));
229 if(Length > ofs + pack->Length) Length = ofs + pack->Length;
230 memcpy((char*)Buffer + ofs, pack->Data, Length - ofs);
232 // Free cached packet
239 * \brief Write to the channel file (send a packet)
241 Uint64 UDP_Channel_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
243 tUDPChannel *chan = Node->ImplPtr;
247 if(chan->LocalPort == 0) return 0;
250 ofs = 2 + 2 + IPStack_GetAddressSize( ep->AddrType );
252 data = (char*)Buffer + ofs;
254 UDP_SendPacketTo(chan, ep->AddrType, &ep->Addr, ep->Port, Buffer, (size_t)Length - ofs);
260 * \brief Names for channel IOCtl Calls
262 static const char *casIOCtls_Channel[] = {
271 * \brief Channel IOCtls
273 int UDP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data)
275 tUDPChannel *chan = Node->ImplPtr;
276 ENTER("pNode iID pData", Node, ID, Data);
279 BASE_IOCTLS(DRV_TYPE_MISC, "UDP Channel", 0x100, casIOCtls_Channel);
281 case 4: // getset_localport (returns bool success)
282 if(!Data) LEAVE_RET('i', chan->LocalPort);
283 if(!CheckMem( Data, sizeof(Uint16) ) ) {
284 LOG("Invalid pointer %p", Data);
288 chan->LocalPort = *(Uint16*)Data;
289 // Permissions check (Ports lower than 1024 are root-only)
290 if(chan->LocalPort != 0 && chan->LocalPort < 1024) {
291 if( Threads_GetUID() != 0 ) {
292 LOG("Attempt by non-superuser to listen on port %i", chan->LocalPort);
297 // Allocate a random port if requested
298 if( chan->LocalPort == 0 )
299 chan->LocalPort = UDP_int_AllocatePort();
302 // Else, mark the requested port as used
303 if( UDP_int_MarkPortAsUsed(chan->LocalPort) == 0 ) {
304 LOG("Port %i us currently in use", chan->LocalPort);
312 case 5: // getset_remoteport (returns bool success)
313 if(!Data) LEAVE_RET('i', chan->Remote.Port);
314 if(!CheckMem( Data, sizeof(Uint16) ) ) {
315 LOG("Invalid pointer %p", Data);
318 chan->Remote.Port = *(Uint16*)Data;
321 case 6: // getset_remotemask (returns bool success)
322 if(!Data) LEAVE_RET('i', chan->RemoteMask);
323 if(!CheckMem(Data, sizeof(int))) LEAVE_RET('i', -1);
324 if( !chan->Interface ) {
325 LOG("Can't set remote mask on NULL interface");
328 if( *(int*)Data > IPStack_GetAddressSize(chan->Interface->Type) )
330 chan->RemoteMask = *(int*)Data;
333 case 7: // set_remoteaddr (returns bool success)
334 if( !chan->Interface ) {
335 LOG("Can't set remote address on NULL interface");
338 if(!CheckMem(Data, IPStack_GetAddressSize(chan->Interface->Type))) {
339 LOG("Invalid pointer");
342 memcpy(&chan->Remote.Addr, Data, IPStack_GetAddressSize(chan->Interface->Type));
349 * \brief Close and destroy an open channel
351 void UDP_Channel_Close(tVFS_Node *Node)
353 tUDPChannel *chan = Node->ImplPtr;
356 // Remove from the main list first
357 Mutex_Acquire(&glUDP_Channels);
358 if(gpUDP_Channels == chan)
359 gpUDP_Channels = gpUDP_Channels->Next;
362 for(prev = gpUDP_Channels;
363 prev->Next && prev->Next != chan;
366 Log_Warning("UDP", "Bookeeping Fail, channel %p is not in main list", chan);
368 prev->Next = prev->Next->Next;
370 Mutex_Release(&glUDP_Channels);
373 SHORTLOCK(&chan->lQueue);
378 chan->Queue = tmp->Next;
381 SHORTREL(&chan->lQueue);
383 // Free channel structure
388 * \return Port Number on success, or zero on failure
390 Uint16 UDP_int_AllocatePort()
393 Mutex_Acquire(&glUDP_Ports);
395 for( i = UDP_ALLOC_BASE; i < 0x10000; i += 32 )
396 if( gUDP_Ports[i/32] != 0xFFFFFFFF )
398 if(i == 0x10000) return 0;
401 if( !(gUDP_Ports[i/32] & (1 << (i%32))) )
404 Mutex_Release(&glUDP_Ports);
408 * \brief Allocate a specific port
409 * \return Boolean Success
411 int UDP_int_MarkPortAsUsed(Uint16 Port)
413 Mutex_Acquire(&glUDP_Ports);
414 if( gUDP_Ports[Port/32] & (1 << (Port%32)) ) {
416 Mutex_Release(&glUDP_Ports);
418 gUDP_Ports[Port/32] |= 1 << (Port%32);
419 Mutex_Release(&glUDP_Ports);
424 * \brief Free an allocated port
426 void UDP_int_FreePort(Uint16 Port)
428 Mutex_Acquire(&glUDP_Ports);
429 gUDP_Ports[Port/32] &= ~(1 << (Port%32));
430 Mutex_Release(&glUDP_Ports);