UDP Packets are now sent and recieved correctly (server not tested)
authorJohn Hodge <[email protected]>
Fri, 26 Feb 2010 14:29:03 +0000 (22:29 +0800)
committerJohn Hodge <[email protected]>
Fri, 26 Feb 2010 14:29:03 +0000 (22:29 +0800)
- Also did some work on USB, only minor.
- Fixed a bug in IPStack/link.c that passed a non-aligned packet to the interface.
- Fixed channel being skipped if the IP _matches_ (should be skipped if it doesn't)
"Yo dawg, I heard you liek packets, so I sent you one"

12 files changed:
Kernel/Makefile.BuildNum
Kernel/include/acess.h
Kernel/lib.c
Modules/IPStack/arp.c
Modules/IPStack/icmp.c
Modules/IPStack/link.c
Modules/IPStack/udp.c
Modules/IPStack/udp.h
Modules/Network/NE2000/ne2000.c
Modules/USB/main.c
Modules/USB/uhci.c
Modules/USB/usb.c

index 51a99bb..11d4581 100644 (file)
@@ -1 +1 @@
-BUILD_NUM = 1450
+BUILD_NUM = 1460
index c4a1c5f..d7f2b0d 100644 (file)
@@ -303,6 +303,7 @@ extern char *strdup(const char *Str);
 extern int     strpos(const char *Str, char Ch);
 extern int     strpos8(const char *str, Uint32 search);
 extern void    itoa(char *buf, Uint num, int base, int minLength, char pad);
+extern int     atoi(const char *string);
 extern int     ReadUTF8(Uint8 *str, Uint32 *Val);
 extern int     WriteUTF8(Uint8 *str, Uint32 Val);
 extern int     ModUtil_SetIdent(char *Dest, char *Value);
index f99f58a..967c03a 100644 (file)
@@ -20,9 +20,62 @@ const short DAYS_BEFORE[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 3
 static Uint    giRandomState = RANDOM_SEED;
 
 // === CODE ===
+/**
+ * \brief Convert a string into an integer
+ */
+int atoi(const char *string)
+{
+        int    ret = 0;
+       
+       // Clear non-numeric characters
+       while( !('0' <= *string && *string <= '9') )    string++;
+       
+       if(*string == '0')
+       {
+               string ++;
+               if(*string == 'x')
+               {
+                       // Hex
+                       string ++;
+                       for( ;; ) {
+                               ret *= 16;
+                               if('0' <= *string && *string <= '9')
+                                       ret += *string - '0';
+                               else if('A' <= *string && *string <= 'F')
+                                       ret += *string - 'A' + 10;
+                               else if('a' <= *string && *string <= 'f')
+                                       ret += *string - 'a' + 10;
+                               else
+                                       break;
+                               string ++;
+                       }
+               }
+               else
+               {
+                       for( ;; )
+                       {
+                               ret *= 8;
+                               if('0' <= *string && *string <= '7')
+                                       ret += *string - '0';
+                               else
+                                       break;
+                       }
+               }
+       }
+       else
+       {
+               for( ; '0' <= *string && *string <= '9'; string++)
+               {
+                       ret *= 10;
+                       ret += *string - '0';
+               }
+       }
+       return ret;
+}
+
 static const char cUCDIGITS[] = "0123456789ABCDEF";
 /**
- * \fn static void itoa(char *buf, Uint num, int base, int minLength, char pad)
+ * \fn void itoa(char *buf, Uint num, int base, int minLength, char pad)
  * \brief Convert an integer into a character string
  */
 void itoa(char *buf, Uint num, int base, int minLength, char pad)
index 4064928..ec10f39 100644 (file)
@@ -93,7 +93,7 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address)
        Log("[ARP4 ] Asking for address %i.%i.%i.%i",
                Address.B[0], Address.B[1], Address.B[2], Address.B[3]
                );
-       req.HWType = htons(1);  // Ethernet
+       req.HWType = htons(0x0001);     // Ethernet
        req.Type   = htons(0x0800);
        req.HWSize = 6;
        req.SWSize = 4;
index 34e6eda..cdc7126 100644 (file)
@@ -59,6 +59,19 @@ void ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buff
                gICMP_PingSlots[hdr->ID].bArrived = 1;
                break;
        
+       // -- 3: Destination Unreachable
+       case ICMP_UNREACHABLE:
+               switch(hdr->Code)
+               {
+               case 3: // Port Unreachable
+                       Log("[ICMP ] Destination Unreachable (Port Unreachable)");
+                       break;
+               default:
+                       Log("[ICMP ] Destination Unreachable (Code %i)", hdr->Code);
+                       break;
+               }
+               break;
+       
        // -- 8: Echo Request
        case ICMP_ECHOREQ:
                if(hdr->Code != 0) {
@@ -72,6 +85,8 @@ void ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buff
                Log("[ICMP ] Checksum = 0x%04x", hdr->Checksum);
                IPv4_SendPacket(Interface, *(tIPv4*)Address, 1, ntohs(hdr->Sequence), Length, hdr);
                break;
+       default:
+               break;
        }
        
 }
index 86cde85..0191efb 100644 (file)
@@ -70,7 +70,7 @@ void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
  */
 void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, void *Buffer)
 {
-        int    bufSize = sizeof(tEthernetHeader) + Length + 4;
+        int    bufSize = sizeof(tEthernetHeader) + ((Length+3)&~3) + 4;
        Uint8   buf[bufSize];   // dynamic stack arrays ftw!
        tEthernetHeader *hdr = (void*)buf;
        
@@ -83,8 +83,8 @@ void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, vo
        
        memcpy(hdr->Data, Buffer, Length);
        
-       *(Uint32*) &hdr->Data[Length] = 0;
-       *(Uint32*) &hdr->Data[Length] = htonl( Link_CalculateCRC(buf, bufSize) );
+       *(Uint32*) &hdr->Data[bufSize-4] = 0;
+       *(Uint32*) &hdr->Data[bufSize-4] = htonl( Link_CalculateCRC(buf, bufSize) );
        
        VFS_Write(Adapter->DeviceFD, bufSize, buf);
 }
index fe13a3e..760c997 100644 (file)
@@ -14,7 +14,7 @@ void  UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
 // --- Listening Server
 tVFS_Node      *UDP_Server_Init(tInterface *Interface);
 char   *UDP_Server_ReadDir(tVFS_Node *Node, int ID);
-tVFS_Node      UDP_Server_FindDir(tVFS_Node *Node, char *Name);
+tVFS_Node      *UDP_Server_FindDir(tVFS_Node *Node, char *Name);
  int   UDP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data);
 void   UDP_Server_Close(tVFS_Node *Node);
 // --- Client Channels
@@ -29,11 +29,16 @@ Uint16      UDP_int_AllocatePort();
 void   UDP_int_FreePort(Uint16 Port);
 
 // === GLOBALS ===
+tSpinlock      glUDP_Servers;
+tUDPServer     *gpUDP_Servers;
+
 tSpinlock      glUDP_Channels;
 tUDPChannel    *gpUDP_Channels;
+
 tSpinlock      glUDP_Ports;
 Uint32 gUDP_Ports[0x10000/32];
-//tSocketFile  gUDP_ServerFile = {NULL, "udps", UDP_Server_Init};
+
+tSocketFile    gUDP_ServerFile = {NULL, "udps", UDP_Server_Init};
 tSocketFile    gUDP_ClientFile = {NULL, "udpc", UDP_Channel_Init};
 
 // === CODE ===
@@ -43,48 +48,45 @@ tSocketFile gUDP_ClientFile = {NULL, "udpc", UDP_Channel_Init};
  */
 void UDP_Initialise()
 {
+       IPStack_AddFile(&gUDP_ServerFile);
        IPStack_AddFile(&gUDP_ClientFile);
        IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket);
 }
 
 /**
- * \fn void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
- * \brief Handles a packet from the IP Layer
+ * \brief Scan a list of tUDPChannel's and find process the first match
+ * \return 0 if no match was found, -1 on error and 1 if a match was found
  */
-void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
+int UDP_int_ScanList(tUDPChannel *List, tInterface *Interface, void *Address, int Length, void *Buffer)
 {
        tUDPHeader      *hdr = Buffer;
        tUDPChannel     *chan;
        tUDPPacket      *pack;
         int    len;
        
-       Log("[UDP  ] hdr->SourcePort = %i", ntohs(hdr->SourcePort));
-       Log("[UDP  ] hdr->DestPort = %i", ntohs(hdr->DestPort));
-       Log("[UDP  ] hdr->Length = %i", ntohs(hdr->Length));
-       Log("[UDP  ] hdr->Checksum = 0x%x", ntohs(hdr->Checksum));
-       
-       // Check registered connections
-       LOCK(&glUDP_Channels);
-       for(chan = gpUDP_Channels;
+       for(chan = List;
                chan;
                chan = chan->Next)
        {
                if(chan->Interface != Interface)        continue;
+               //Log("[UDP  ] Local (0x%04x) == Dest (0x%04x)", chan->LocalPort, ntohs(hdr->DestPort));
                if(chan->LocalPort != ntohs(hdr->DestPort))     continue;
+               //Log("[UDP  ] Remote (0x%04x) == Source (0x%04x)", chan->RemotePort, ntohs(hdr->SourcePort));
                if(chan->RemotePort != ntohs(hdr->SourcePort))  continue;
                
                if(Interface->Type == 4) {
-                       if(IP4_EQU(chan->RemoteAddr.v4, *(tIPv4*)Address))      continue;
+                       if(!IP4_EQU(chan->RemoteAddr.v4, *(tIPv4*)Address))     continue;
                }
                else if(Interface->Type == 6) {
-                       if(IP6_EQU(chan->RemoteAddr.v6, *(tIPv6*)Address))      continue;
+                       if(!IP6_EQU(chan->RemoteAddr.v6, *(tIPv6*)Address))     continue;
                }
                else {
                        Warning("[UDP  ] Address type %i unknown", Interface->Type);
                        RELEASE(&glUDP_Channels);
-                       return ;
+                       return -1;
                }
                
+               Log("[UDP  ] Recieved packet for %p", chan);
                // Create the cached packet
                len = ntohs(hdr->Length);
                pack = malloc(sizeof(tUDPPacket) + len);
@@ -100,12 +102,50 @@ void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
                        chan->QueueEnd = chan->Queue = pack;
                RELEASE(&chan->lQueue);
                RELEASE(&glUDP_Channels);
-               return ;
+               return 1;
        }
+       return 0;
+}
+
+/**
+ * \fn void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
+ * \brief Handles a packet from the IP Layer
+ */
+void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
+{
+       tUDPHeader      *hdr = Buffer;
+       tUDPServer      *srv;
+        int    ret;
        
-       // TODO: Server/Listener
+       Log("[UDP  ] hdr->SourcePort = %i", ntohs(hdr->SourcePort));
+       Log("[UDP  ] hdr->DestPort = %i", ntohs(hdr->DestPort));
+       Log("[UDP  ] hdr->Length = %i", ntohs(hdr->Length));
+       Log("[UDP  ] hdr->Checksum = 0x%x", ntohs(hdr->Checksum));
        
+       // Check registered connections
+       LOCK(&glUDP_Channels);
+       ret = UDP_int_ScanList(gpUDP_Channels, Interface, Address, Length, Buffer);
        RELEASE(&glUDP_Channels);
+       if(ret != 0)    return ;
+       
+       
+       // TODO: Server/Listener
+       LOCK(&glUDP_Servers);
+       for(srv = gpUDP_Servers;
+               srv;
+               srv = srv->Next)
+       {
+               if(srv->Interface != Interface) continue;
+               if(srv->ListenPort != ntohs(hdr->DestPort))     continue;
+               ret = UDP_int_ScanList(srv->Channels, Interface, Address, Length, Buffer);
+               if(ret != 0)    break;
+               
+               // Add connection
+               Warning("[UDP  ] TODO - Add channel on connection");
+               //TODO
+       }
+       RELEASE(&glUDP_Servers);
+       
 }
 
 /**
@@ -136,6 +176,184 @@ void UDP_SendPacket(tUDPChannel *Channel, void *Data, size_t Length)
        }
 }
 
+// --- Listening Server
+tVFS_Node *UDP_Server_Init(tInterface *Interface)
+{
+       tUDPServer      *new;
+       new = calloc( sizeof(tUDPServer), 1 );
+       if(!new)        return NULL;
+       
+       new->Node.ImplPtr = new;
+       new->Node.Flags = VFS_FFLAG_DIRECTORY;
+       new->Node.NumACLs = 1;
+       new->Node.ACLs = &gVFS_ACL_EveryoneRX;
+       new->Node.ReadDir = UDP_Server_ReadDir;
+       new->Node.FindDir = UDP_Server_FindDir;
+       new->Node.IOCtl = UDP_Server_IOCtl;
+       new->Node.Close = UDP_Server_Close;
+       
+       LOCK(&glUDP_Servers);
+       new->Next = gpUDP_Servers;
+       gpUDP_Servers = new;
+       RELEASE(&glUDP_Servers);
+       
+       return &new->Node;
+}
+
+/**
+ * \brief Wait for a connection and return its ID in a string
+ */
+char *UDP_Server_ReadDir(tVFS_Node *Node, int ID)
+{
+       tUDPServer      *srv = Node->ImplPtr;
+       tUDPChannel     *chan;
+       char    *ret;
+       
+       if( srv->ListenPort == 0 )      return NULL;
+       
+       // Lock (so another thread can't collide with us here) and wait for a connection
+       LOCK( &srv->Lock );
+       while( srv->NewChannels == NULL )       Threads_Yield();
+       // Pop the connection off the new list
+       chan = srv->NewChannels;
+       srv->NewChannels = chan->Next;
+       // Release the lock
+       RELEASE( &srv->Lock );
+       
+       // Create the ID string and return it
+       ret = malloc(11+1);
+       sprintf(ret, "%i", chan->Node.ImplInt);
+       
+       return ret;
+}
+
+/**
+ * \brief Take a string and find the channel
+ */
+tVFS_Node *UDP_Server_FindDir(tVFS_Node *Node, char *Name)
+{
+       tUDPServer      *srv = Node->ImplPtr;
+       tUDPChannel     *chan;
+        int    id = atoi(Name);
+       
+       for(chan = srv->Channels;
+               chan;
+               chan = chan->Next)
+       {
+               if( chan->Node.ImplInt < id )   continue;
+               if( chan->Node.ImplInt > id )   break;  // Go sorted lists!
+               
+               return &chan->Node;
+       }
+       
+       return NULL;
+}
+
+/**
+ * \brief Names for server IOCtl Calls
+ */
+static const char *casIOCtls_Server[] = {
+       DRV_IOCTLNAMES,
+       "getset_listenport",
+       NULL
+       };
+/**
+ * \brief Channel IOCtls
+ */
+int UDP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+       tUDPServer      *srv = Node->ImplPtr;
+       
+       ENTER("pNode iID pData", Node, ID, Data);
+       switch(ID)
+       {
+       BASE_IOCTLS(DRV_TYPE_MISC, "UDP Server", 0x100, casIOCtls_Server);
+       
+       case 4: // getset_localport (returns bool success)
+               if(!Data)       LEAVE_RET('i', srv->ListenPort);
+               if(!CheckMem( Data, sizeof(Uint16) ) ) {
+                       LOG("Invalid pointer %p", Data);
+                       LEAVE_RET('i', -1);
+               }
+               // Set port
+               srv->ListenPort = *(Uint16*)Data;
+               // Permissions check (Ports lower than 1024 are root-only)
+               if(srv->ListenPort != 0 && srv->ListenPort < 1024) {
+                       if( Threads_GetUID() != 0 ) {
+                               LOG("Attempt by non-superuser to listen on port %i", srv->ListenPort);
+                               srv->ListenPort = 0;
+                               LEAVE_RET('i', -1);
+                       }
+               }
+               // Allocate a random port if requested
+               if( srv->ListenPort == 0 )
+                       srv->ListenPort = UDP_int_AllocatePort();
+               else
+               {
+                       // Else, mark the requested port as used
+                       if( UDP_int_MarkPortAsUsed(srv->ListenPort) == 0 ) {
+                               LOG("Port %i us currently in use", srv->ListenPort);
+                               srv->ListenPort = 0;
+                               LEAVE_RET('i', -1);
+                       }
+                       LEAVE_RET('i', 1);
+               }
+               LEAVE_RET('i', 1);
+       
+       default:
+               LEAVE_RET('i', -1);
+       }
+       LEAVE_RET('i', 0);
+}
+
+void UDP_Server_Close(tVFS_Node *Node)
+{
+       tUDPServer      *srv = Node->ImplPtr;
+       tUDPServer      *prev;
+       tUDPChannel     *chan;
+       tUDPPacket      *tmp;
+       
+       
+       // Remove from the main list first
+       LOCK(&glUDP_Servers);
+       if(gpUDP_Servers == srv)
+               gpUDP_Servers = gpUDP_Servers->Next;
+       else
+       {
+               for(prev = gpUDP_Servers;
+                       prev->Next && prev->Next != srv;
+                       prev = prev->Next);
+               if(!prev->Next)
+                       Warning("[UDP  ] Bookeeping Fail, server %p is not in main list", srv);
+               else
+                       prev->Next = prev->Next->Next;
+       }
+       RELEASE(&glUDP_Servers);
+       
+       
+       LOCK(&srv->Lock);
+       for(chan = srv->Channels;
+               chan;
+               chan = chan->Next)
+       {
+               // Clear Queue
+               LOCK(&chan->lQueue);
+               while(chan->Queue)
+               {
+                       tmp = chan->Queue;
+                       chan->Queue = tmp->Next;
+                       free(tmp);
+               }
+               RELEASE(&chan->lQueue);
+               
+               // Free channel structure
+               free(chan);
+       }
+       RELEASE(&srv->Lock);
+       
+       free(srv);
+}
+
 // --- Client Channels
 tVFS_Node *UDP_Channel_Init(tInterface *Interface)
 {
index 36c36e1..2cc743a 100644 (file)
@@ -9,6 +9,7 @@
 #include "ipv4.h"
 
 typedef struct sUDPHeader      tUDPHeader;
+typedef struct sUDPServer      tUDPServer;
 typedef struct sUDPPacket      tUDPPacket;
 typedef struct sUDPChannel     tUDPChannel;
 
@@ -44,4 +45,19 @@ struct sUDPChannel
        tUDPPacket      *QueueEnd;
 };
 
+struct sUDPServer
+{
+       struct sUDPServer       *Next;
+       
+       tVFS_Node       Node;
+       
+       tInterface      *Interface;
+       Uint16  ListenPort;
+        int    NextID;
+        int    NumChannels;
+       tUDPChannel     *Channels;
+       tSpinlock       Lock;
+       tUDPChannel     * volatile NewChannels;
+};
+
 #endif
index 24d8278..7e23f54 100644 (file)
@@ -3,7 +3,7 @@
  * 
  * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
  */
-#define        DEBUG   0
+#define        DEBUG   1
 #define VERSION        ((0<<8)|50)
 #include <acess.h>
 #include <modules.h>
@@ -309,7 +309,7 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        // Sanity Check Length
        if(Length > TX_BUF_SIZE*256) {
                Warning(
-                       "Ne2k_Write - Attempting to send over TX_BUF_SIZE(%i) bytes (%i)",
+                       "Ne2k_Write - Attempting to send over TX_BUF_SIZE*256 (%i) bytes (%i)",
                        TX_BUF_SIZE*256, Length
                        );
                LEAVE('i', 0);
@@ -339,8 +339,9 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        outb(Card->IOBase + CMD, 0|0x10|0x2);   // Page 0, Remote Write, Start
        
        // Send Data
-       for(rem = Length; rem; rem -= 2)
+       for(rem = Length; rem > 0; rem -= 2) {
                outw(Card->IOBase + 0x10, *buf++);
+       }
        
        while( inb(Card->IOBase + ISR) == 0 )   // Wait for Remote DMA Complete
                ;       //Proc_Yield();
index a992433..28ce5e3 100644 (file)
@@ -74,7 +74,6 @@ tVFS_Node *USB_FindDir(tVFS_Node *Node, char *Name)
 }
 
 /**
- * \fn int USB_IOCtl(tVFS_Node *Node, int Id, void *Data)
  * \brief Handles IOCtl Calls to the USB driver
  */
 int USB_IOCtl(tVFS_Node *Node, int Id, void *Data)
index 55faeb0..e8cb7b7 100644 (file)
@@ -45,7 +45,7 @@ int UHCI_Initialise()
                base = PCI_AssignPort( id, 4, 0x20 );\r
                gUHCI_Controllers[i].IOBase = base;\r
                \r
-               LOG("Controller PCI #%i: IO Base = 0x%x", id, base);\r
+               Log("[USB  ] Controller PCI #%i: IO Base = 0x%x", id, base);\r
                \r
                // Initialise Host\r
                ret = UHCI_Int_InitHost(&gUHCI_Controllers[i]);\r
@@ -75,8 +75,9 @@ void UHCI_Cleanup()
 /**\r
  * \brief Sends a packet to a device endpoint\r
  */\r
-int UHCI_SendPacket(int ControllerId, int Device, int Endpoint, void *Data, int Length)\r
+int UHCI_SendPacket(int ControllerId, int Length)\r
 {\r
+       //tUHCI_TD      *td = UHCI_AllocateTD();\r
        return 0;\r
 }\r
 \r
index 3ac7bf8..4663ce2 100644 (file)
@@ -19,3 +19,15 @@ void USB_MakeToken(void *Buf, int PID, int Addr, int EndP)
        tok[1] = Addr | ((EndP&1)<<7);
        tok[2] = (EndP >> 1) | crc;
 }
+
+#if 0
+void USB_SendPacket(int Controller, int PID, int Dev, int Endpoint, void *Data, int Length)
+{
+       uint8_t buf[Length/*+??*/];
+       switch(Controller & 0xF00)
+       {
+       case 1:
+               UHCI_SendPacket(Controller & 0xFF);
+       }
+}
+#endif

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