From ff1aacd48c7b616508c1d4e7a7ba03f741ee2cda Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 26 Feb 2010 22:29:03 +0800 Subject: [PATCH] UDP Packets are now sent and recieved correctly (server not tested) - 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" --- Kernel/Makefile.BuildNum | 2 +- Kernel/include/acess.h | 1 + Kernel/lib.c | 55 ++++++- Modules/IPStack/arp.c | 2 +- Modules/IPStack/icmp.c | 15 ++ Modules/IPStack/link.c | 6 +- Modules/IPStack/udp.c | 254 +++++++++++++++++++++++++++++--- Modules/IPStack/udp.h | 16 ++ Modules/Network/NE2000/ne2000.c | 7 +- Modules/USB/main.c | 1 - Modules/USB/uhci.c | 5 +- Modules/USB/usb.c | 12 ++ 12 files changed, 346 insertions(+), 30 deletions(-) diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index 51a99bb5..11d4581c 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 1450 +BUILD_NUM = 1460 diff --git a/Kernel/include/acess.h b/Kernel/include/acess.h index c4a1c5f8..d7f2b0d6 100644 --- a/Kernel/include/acess.h +++ b/Kernel/include/acess.h @@ -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); diff --git a/Kernel/lib.c b/Kernel/lib.c index f99f58ac..967c03ac 100644 --- a/Kernel/lib.c +++ b/Kernel/lib.c @@ -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) diff --git a/Modules/IPStack/arp.c b/Modules/IPStack/arp.c index 40649284..ec10f396 100644 --- a/Modules/IPStack/arp.c +++ b/Modules/IPStack/arp.c @@ -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; diff --git a/Modules/IPStack/icmp.c b/Modules/IPStack/icmp.c index 34e6eda4..cdc7126a 100644 --- a/Modules/IPStack/icmp.c +++ b/Modules/IPStack/icmp.c @@ -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; } } diff --git a/Modules/IPStack/link.c b/Modules/IPStack/link.c index 86cde858..0191efb8 100644 --- a/Modules/IPStack/link.c +++ b/Modules/IPStack/link.c @@ -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); } diff --git a/Modules/IPStack/udp.c b/Modules/IPStack/udp.c index fe13a3e1..760c9974 100644 --- a/Modules/IPStack/udp.c +++ b/Modules/IPStack/udp.c @@ -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) { diff --git a/Modules/IPStack/udp.h b/Modules/IPStack/udp.h index 36c36e15..2cc743ab 100644 --- a/Modules/IPStack/udp.h +++ b/Modules/IPStack/udp.h @@ -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 diff --git a/Modules/Network/NE2000/ne2000.c b/Modules/Network/NE2000/ne2000.c index 24d82782..7e23f54a 100644 --- a/Modules/Network/NE2000/ne2000.c +++ b/Modules/Network/NE2000/ne2000.c @@ -3,7 +3,7 @@ * * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc */ -#define DEBUG 0 +#define DEBUG 1 #define VERSION ((0<<8)|50) #include #include @@ -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(); diff --git a/Modules/USB/main.c b/Modules/USB/main.c index a992433b..28ce5e3b 100644 --- a/Modules/USB/main.c +++ b/Modules/USB/main.c @@ -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) diff --git a/Modules/USB/uhci.c b/Modules/USB/uhci.c index 55faeb06..e8cb7b71 100644 --- a/Modules/USB/uhci.c +++ b/Modules/USB/uhci.c @@ -45,7 +45,7 @@ int UHCI_Initialise() base = PCI_AssignPort( id, 4, 0x20 ); gUHCI_Controllers[i].IOBase = base; - LOG("Controller PCI #%i: IO Base = 0x%x", id, base); + Log("[USB ] Controller PCI #%i: IO Base = 0x%x", id, base); // Initialise Host ret = UHCI_Int_InitHost(&gUHCI_Controllers[i]); @@ -75,8 +75,9 @@ void UHCI_Cleanup() /** * \brief Sends a packet to a device endpoint */ -int UHCI_SendPacket(int ControllerId, int Device, int Endpoint, void *Data, int Length) +int UHCI_SendPacket(int ControllerId, int Length) { + //tUHCI_TD *td = UHCI_AllocateTD(); return 0; } diff --git a/Modules/USB/usb.c b/Modules/USB/usb.c index 3ac7bf8e..4663ce28 100644 --- a/Modules/USB/usb.c +++ b/Modules/USB/usb.c @@ -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 -- 2.20.1