6 #include <api_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, const void *Address, Uint16 Port, const void *Data, size_t Length);
16 // --- Client Channels
17 tVFS_Node *UDP_Channel_Init(tInterface *Interface);
18 size_t UDP_Channel_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
19 size_t UDP_Channel_Write(tVFS_Node *Node, off_t Offset, size_t Length, const 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 tVFS_NodeType gUDP_NodeType = {
29 .Read = UDP_Channel_Read,
30 .Write = UDP_Channel_Write,
31 .IOCtl = UDP_Channel_IOCtl,
32 .Close = UDP_Channel_Close
34 tMutex glUDP_Channels;
35 tUDPChannel *gpUDP_Channels;
38 Uint32 gUDP_Ports[0x10000/32];
40 tSocketFile gUDP_SocketFile = {NULL, "udp", UDP_Channel_Init};
44 * \fn void TCP_Initialise()
45 * \brief Initialise the TCP Layer
49 IPStack_AddFile(&gUDP_SocketFile);
50 //IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket, UDP_Unreachable);
51 IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket);
55 * \brief Scan a list of tUDPChannels and find process the first match
56 * \return 0 if no match was found, -1 on error and 1 if a match was found
58 int UDP_int_ScanList(tUDPChannel *List, tInterface *Interface, void *Address, int Length, void *Buffer)
60 tUDPHeader *hdr = Buffer;
69 // Match local endpoint
70 if(chan->Interface && chan->Interface != Interface) continue;
71 if(chan->LocalPort != ntohs(hdr->DestPort)) continue;
73 // Check for remote port restriction
74 if(chan->Remote.Port && chan->Remote.Port != ntohs(hdr->SourcePort))
76 // Check for remote address restriction
79 if(chan->Remote.AddrType != Interface->Type)
81 if(!IPStack_CompareAddress(Interface->Type, Address,
82 &chan->Remote.Addr, chan->RemoteMask)
87 Log_Log("UDP", "Recieved packet for %p", chan);
88 // Create the cached packet
89 len = ntohs(hdr->Length);
90 pack = malloc(sizeof(tUDPPacket) + len);
92 memcpy(&pack->Remote.Addr, Address, IPStack_GetAddressSize(Interface->Type));
93 pack->Remote.Port = ntohs(hdr->SourcePort);
94 pack->Remote.AddrType = Interface->Type;
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 VFS_MarkAvaliable(&chan->Node, 1);
106 Mutex_Release(&glUDP_Channels);
113 * \fn void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
114 * \brief Handles a packet from the IP Layer
116 void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
118 tUDPHeader *hdr = Buffer;
120 Log_Debug("UDP", "%i bytes :%i->:%i (Cksum 0x%04x)",
121 ntohs(hdr->Length), ntohs(hdr->SourcePort), ntohs(hdr->Length), ntohs(hdr->Checksum));
123 // Check registered connections
124 Mutex_Acquire(&glUDP_Channels);
125 UDP_int_ScanList(gpUDP_Channels, Interface, Address, Length, Buffer);
126 Mutex_Release(&glUDP_Channels);
130 * \brief Handle an ICMP Unrechable Error
132 void UDP_Unreachable(tInterface *Interface, int Code, void *Address, int Length, void *Buffer)
138 * \brief Send a packet
139 * \param Channel Channel to send the packet from
140 * \param Data Packet data
141 * \param Length Length in bytes of packet data
143 void UDP_SendPacketTo(tUDPChannel *Channel, int AddrType, const void *Address, Uint16 Port, const void *Data, size_t Length)
147 if(Channel->Interface && Channel->Interface->Type != AddrType) return ;
153 hdr.SourcePort = htons( Channel->LocalPort );
154 hdr.DestPort = htons( Port );
155 hdr.Length = htons( sizeof(tUDPHeader) + Length );
156 hdr.Checksum = 0; // Checksum can be zero on IPv4
157 // Pass on the the IPv4 Layer
158 tIPStackBuffer *buffer = IPStack_Buffer_CreateBuffer(2 + IPV4_BUFFERS);
159 IPStack_Buffer_AppendSubBuffer(buffer, Length, 0, Data, NULL, NULL);
160 IPStack_Buffer_AppendSubBuffer(buffer, sizeof(hdr), 0, &hdr, NULL, NULL);
161 // TODO: What if Channel->Interface is NULL here?
162 IPv4_SendPacket(Channel->Interface, *(tIPv4*)Address, IP4PROT_UDP, 0, buffer);
163 IPStack_Buffer_DestroyBuffer(buffer);
168 // --- Client Channels
169 tVFS_Node *UDP_Channel_Init(tInterface *Interface)
172 new = calloc( sizeof(tUDPChannel), 1 );
173 new->Interface = Interface;
174 new->Node.ImplPtr = new;
175 new->Node.NumACLs = 1;
176 new->Node.ACLs = &gVFS_ACL_EveryoneRW;
177 new->Node.Type = &gUDP_NodeType;
179 Mutex_Acquire(&glUDP_Channels);
180 new->Next = gpUDP_Channels;
181 gpUDP_Channels = new;
182 Mutex_Release(&glUDP_Channels);
188 * \brief Read from the channel file (wait for a packet)
190 size_t UDP_Channel_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
192 tUDPChannel *chan = Node->ImplPtr;
197 if(chan->LocalPort == 0) {
198 Log_Notice("UDP", "Channel %p sent with no local port", chan);
202 while(chan->Queue == NULL) Threads_Yield();
206 VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "UDP_Channel_Read");
207 SHORTLOCK(&chan->lQueue);
208 if(chan->Queue == NULL) {
209 SHORTREL(&chan->lQueue);
213 chan->Queue = pack->Next;
215 chan->QueueEnd = NULL;
216 VFS_MarkAvaliable(Node, 0); // Nothing left
218 SHORTREL(&chan->lQueue);
222 // Check that the header fits
223 addrlen = IPStack_GetAddressSize(pack->Remote.AddrType);
228 Log_Notice("UDP", "Insuficient space for header in buffer (%i < %i)", (int)Length, ofs);
233 ep->Port = pack->Remote.Port;
234 ep->AddrType = pack->Remote.AddrType;
235 memcpy(&ep->Addr, &pack->Remote.Addr, addrlen);
238 if(Length > ofs + pack->Length) Length = ofs + pack->Length;
239 memcpy((char*)Buffer + ofs, pack->Data, Length - ofs);
241 // Free cached packet
248 * \brief Write to the channel file (send a packet)
250 size_t UDP_Channel_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
252 tUDPChannel *chan = Node->ImplPtr;
253 const tUDPEndpoint *ep;
257 if(chan->LocalPort == 0) {
258 Log_Notice("UDP", "Write to channel %p with zero local port", chan);
263 ofs = 2 + 2 + IPStack_GetAddressSize( ep->AddrType );
265 data = (const char *)Buffer + ofs;
267 UDP_SendPacketTo(chan, ep->AddrType, &ep->Addr, ep->Port, data, (size_t)Length - ofs);
273 * \brief Names for channel IOCtl Calls
275 static const char *casIOCtls_Channel[] = {
284 * \brief Channel IOCtls
286 int UDP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data)
288 tUDPChannel *chan = Node->ImplPtr;
289 ENTER("pNode iID pData", Node, ID, Data);
292 BASE_IOCTLS(DRV_TYPE_MISC, "UDP Channel", 0x100, casIOCtls_Channel);
294 case 4: // getset_localport (returns bool success)
295 if(!Data) LEAVE_RET('i', chan->LocalPort);
296 if(!CheckMem( Data, sizeof(Uint16) ) ) {
297 LOG("Invalid pointer %p", Data);
301 chan->LocalPort = *(Uint16*)Data;
302 // Permissions check (Ports lower than 1024 are root-only)
303 if(chan->LocalPort != 0 && chan->LocalPort < 1024) {
304 if( Threads_GetUID() != 0 ) {
305 LOG("Attempt by non-superuser to listen on port %i", chan->LocalPort);
310 // Allocate a random port if requested
311 if( chan->LocalPort == 0 )
312 chan->LocalPort = UDP_int_AllocatePort();
315 // Else, mark the requested port as used
316 if( UDP_int_MarkPortAsUsed(chan->LocalPort) == 0 ) {
317 LOG("Port %i us currently in use", chan->LocalPort);
325 case 5: // getset_remoteport (returns bool success)
326 if(!Data) LEAVE_RET('i', chan->Remote.Port);
327 if(!CheckMem( Data, sizeof(Uint16) ) ) {
328 LOG("Invalid pointer %p", Data);
331 chan->Remote.Port = *(Uint16*)Data;
334 case 6: // getset_remotemask (returns bool success)
335 if(!Data) LEAVE_RET('i', chan->RemoteMask);
336 if(!CheckMem(Data, sizeof(int))) LEAVE_RET('i', -1);
337 if( !chan->Interface ) {
338 LOG("Can't set remote mask on NULL interface");
341 if( *(int*)Data > IPStack_GetAddressSize(chan->Interface->Type) )
343 chan->RemoteMask = *(int*)Data;
346 case 7: // set_remoteaddr (returns bool success)
347 if( !chan->Interface ) {
348 LOG("Can't set remote address on NULL interface");
351 if(!CheckMem(Data, IPStack_GetAddressSize(chan->Interface->Type))) {
352 LOG("Invalid pointer");
355 memcpy(&chan->Remote.Addr, Data, IPStack_GetAddressSize(chan->Interface->Type));
362 * \brief Close and destroy an open channel
364 void UDP_Channel_Close(tVFS_Node *Node)
366 tUDPChannel *chan = Node->ImplPtr;
369 // Remove from the main list first
370 Mutex_Acquire(&glUDP_Channels);
371 if(gpUDP_Channels == chan)
372 gpUDP_Channels = gpUDP_Channels->Next;
375 for(prev = gpUDP_Channels;
376 prev->Next && prev->Next != chan;
379 Log_Warning("UDP", "Bookeeping Fail, channel %p is not in main list", chan);
381 prev->Next = prev->Next->Next;
383 Mutex_Release(&glUDP_Channels);
386 SHORTLOCK(&chan->lQueue);
391 chan->Queue = tmp->Next;
394 SHORTREL(&chan->lQueue);
396 // Free channel structure
401 * \return Port Number on success, or zero on failure
403 Uint16 UDP_int_AllocatePort()
406 Mutex_Acquire(&glUDP_Ports);
408 for( i = UDP_ALLOC_BASE; i < 0x10000; i += 32 )
409 if( gUDP_Ports[i/32] != 0xFFFFFFFF )
411 if(i == 0x10000) return 0;
414 if( !(gUDP_Ports[i/32] & (1 << (i%32))) )
417 Mutex_Release(&glUDP_Ports);
421 * \brief Allocate a specific port
422 * \return Boolean Success
424 int UDP_int_MarkPortAsUsed(Uint16 Port)
426 Mutex_Acquire(&glUDP_Ports);
427 if( gUDP_Ports[Port/32] & (1 << (Port%32)) ) {
429 Mutex_Release(&glUDP_Ports);
431 gUDP_Ports[Port/32] |= 1 << (Port%32);
432 Mutex_Release(&glUDP_Ports);
437 * \brief Free an allocated port
439 void UDP_int_FreePort(Uint16 Port)
441 Mutex_Acquire(&glUDP_Ports);
442 gUDP_Ports[Port/32] &= ~(1 << (Port%32));
443 Mutex_Release(&glUDP_Ports);