From 0f48b41ce8edd3b6d549d641b35901e4b51a5132 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 23 Nov 2009 17:18:49 +0800 Subject: [PATCH] More work on IPStack (Also fixed Proc_SpawnWorker) - Fixed structures in IPStack not being packed - Fixed instances when byte orders were not handled - Added stub UDP support - Added copious ammounts of debug code to IPStack - Added packet reception to NE2000 driver - Changed autoconf in ifconfig to set the IP to 10.0.0.55 --- Kernel/Makefile.BuildNum | 2 +- Kernel/arch/x86/mm_virt.c | 19 ++- Kernel/arch/x86/proc.c | 11 +- Modules/IPStack/Makefile | 5 +- Modules/IPStack/arp.c | 26 +++- Modules/IPStack/arp.h | 4 +- Modules/IPStack/icmp.c | 12 +- Modules/IPStack/ipstack.h | 8 +- Modules/IPStack/ipv4.c | 66 ++++++++- Modules/IPStack/ipv4.h | 12 +- Modules/IPStack/link.c | 92 ++++++++++++- Modules/IPStack/main.c | 4 +- Modules/IPStack/udp.c | 36 +++++ Modules/IPStack/udp.h | 22 +++ Modules/NE2000/ne2000.c | 155 ++++++++++++++++++++-- Usermode/Applications/ifconfig_src/main.c | 13 +- 16 files changed, 434 insertions(+), 53 deletions(-) create mode 100644 Modules/IPStack/udp.c create mode 100644 Modules/IPStack/udp.h diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index 92b8fa6d..a8d43110 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 1020 +BUILD_NUM = 1039 diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index 9892998d..c29db507 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -15,7 +15,7 @@ #include #define KERNEL_STACKS 0xF0000000 -#define KERNEL_STACK_SIZE 0x00002000 +#define KERNEL_STACK_SIZE 0x00008000 #define KERNEL_STACKS_END 0xFD000000 #define WORKER_STACKS 0x00100000 // Thread0 Only! #define WORKER_STACK_SIZE KERNEL_STACK_SIZE @@ -628,19 +628,23 @@ tVAddr MM_NewWorkerStack() giLastUsedWorker = base; // We have one base = WORKER_STACKS + base * WORKER_STACK_SIZE; + //Log(" MM_NewWorkerStack: base = 0x%x", base); // Acquire the lock for the temp fractal mappings LOCK(&gilTempFractal); // Set the temp fractals to TID0's address space - *gTmpCR3 = (Uint)gaInitPageDir | 3; + *gTmpCR3 = ((Uint)gaInitPageDir - KERNEL_BASE) | 3; + //Log(" MM_NewWorkerStack: *gTmpCR3 = 0x%x", *gTmpCR3); INVLPG( gaTmpDir ); + // Check if the directory is mapped (we are assuming that the stacks - // will fit neatly in a directory + // will fit neatly in a directory) + //Log(" MM_NewWorkerStack: gaTmpDir[ 0x%x ] = 0x%x", base>>22, gaTmpDir[ base >> 22 ]); if(gaTmpDir[ base >> 22 ] == 0) { gaTmpDir[ base >> 22 ] = MM_AllocPhys() | 3; - INVLPG( &gaTmpTable[ (base>>22) & ~0x3FF ] ); + INVLPG( &gaTmpTable[ (base>>12) & ~0x3FF ] ); } // Mapping Time! @@ -649,6 +653,7 @@ tVAddr MM_NewWorkerStack() pages[ addr >> 12 ] = MM_AllocPhys(); gaTmpTable[ (base + addr) >> 12 ] = pages[addr>>12] | 3; } + *gTmpCR3 = 0; // Release the temp mapping lock RELEASE(&gilTempFractal); @@ -656,6 +661,9 @@ tVAddr MM_NewWorkerStack() oldstack = (esp + KERNEL_STACK_SIZE-1) & ~(KERNEL_STACK_SIZE-1); esp = oldstack - esp; // ESP as an offset in the stack + // Make `base` be the top of the stack + base += WORKER_STACK_SIZE; + i = (WORKER_STACK_SIZE>>12) - 1; // Copy the contents of the old stack to the new one, altering the addresses // `addr` is refering to bytes from the stack base (mem downwards) @@ -672,10 +680,11 @@ tVAddr MM_NewWorkerStack() else // Seems not, best leave it alone tmpPage[j] = stack[j]; } - MM_FreeTemp((Uint)tmpPage); + MM_FreeTemp((tVAddr)tmpPage); i --; } + //Log("MM_NewWorkerStack: RETURN 0x%x", base); return base; } diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index f9c5ba1f..60f015b2 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -337,13 +337,14 @@ int Proc_SpawnWorker() memcpy(new, &gThreadZero, sizeof(tThread)); // Set Thread ID new->TID = giNextTID++; - // Set kernel stack + // Create a new worker stack (in PID0's address space) + // The stack is relocated by this code new->KernelStack = MM_NewWorkerStack(); // Get ESP and EBP based in the new stack __asm__ __volatile__ ("mov %%esp, %0": "=r"(esp)); __asm__ __volatile__ ("mov %%ebp, %0": "=r"(ebp)); - esp = cur->KernelStack - (new->KernelStack - esp); + esp = new->KernelStack - (cur->KernelStack - esp); ebp = new->KernelStack - (cur->KernelStack - ebp); // Save core machine state @@ -357,6 +358,9 @@ int Proc_SpawnWorker() // Set EIP as parent new->SavedState.EIP = eip; + // Mark as active + new->Status = THREAD_STAT_ACTIVE; + Threads_AddActive( new ); return new->TID; } @@ -557,7 +561,8 @@ void Proc_Scheduler(int CPU) gTSSs[CPU].ESP0 = thread->KernelStack; // Set address space - __asm__ __volatile__ ("mov %0, %%cr3"::"a"(gCurrentThread->MemState.CR3)); + if( gCurrentThread->MemState.CR3 != 0 ) + __asm__ __volatile__ ("mov %0, %%cr3"::"a"(gCurrentThread->MemState.CR3)); // Switch threads __asm__ __volatile__ ( "mov %1, %%esp\n\t" // Restore ESP diff --git a/Modules/IPStack/Makefile b/Modules/IPStack/Makefile index 6226f4f4..6c26f2d3 100644 --- a/Modules/IPStack/Makefile +++ b/Modules/IPStack/Makefile @@ -1,7 +1,10 @@ # # -OBJ = main.o link.o arp.o ipv4.o ipv6.o +OBJ = main.o link.o arp.o +OBJ += ipv4.o icmp.o +OBJ += ipv6.o +OBJ += udp.o NAME = IPStack -include ../Makefile.tpl diff --git a/Modules/IPStack/arp.c b/Modules/IPStack/arp.c index cc194e90..2ee4fac6 100644 --- a/Modules/IPStack/arp.c +++ b/Modules/IPStack/arp.c @@ -95,21 +95,43 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe return; } - switch( req4->Request ) + Log("[ARP ] Request ID %i", ntohs(req4->Request)); + + switch( ntohs(req4->Request) ) { case 1: // You want my IP? + Log("[ARP ] ARP Request Address class %i", req4->SWSize); // Check what type of IP it is switch( req4->SWSize ) { case 4: + Log("[ARP ] From MAC %02x:%02x:%02x:%02x:%02x:%02x", + req4->SourceMac.B[0], req4->SourceMac.B[1], + req4->SourceMac.B[2], req4->SourceMac.B[3], + req4->SourceMac.B[4], req4->SourceMac.B[5]); + Log("[ARP ] to MAC %02x:%02x:%02x:%02x:%02x:%02x", + req4->DestMac.B[0], req4->DestMac.B[1], + req4->DestMac.B[2], req4->DestMac.B[3], + req4->DestMac.B[4], req4->DestMac.B[5]); + Log("[ARP ] ARP Request IPv4 Address %i.%i.%i.%i", + req4->DestIP.B[0], req4->DestIP.B[1], req4->DestIP.B[2], + req4->DestIP.B[3]); + Log("[ARP ] from %i.%i.%i.%i", + req4->SourceIP.B[0], req4->SourceIP.B[1], + req4->SourceIP.B[2], req4->SourceIP.B[3]); iface = IPv4_GetInterface(Adapter, req4->DestIP, 0); if( iface ) { - IP4_SET(req4->DestIP, req4->SourceIP); + req4->DestIP = req4->SourceIP; req4->DestMac = req4->SourceMac; req4->SourceIP = iface->IP4.Address; req4->SourceMac = Adapter->MacAddr; req4->Request = htons(2); + Log("[ARP ] Hey, That's us!"); + Log("[ARP ] Sending back %02x:%02x:%02x:%02x:%02x:%02x", + req4->SourceMac.B[0], req4->SourceMac.B[1], + req4->SourceMac.B[2], req4->SourceMac.B[3], + req4->SourceMac.B[4], req4->SourceMac.B[5]); Link_SendPacket(Adapter, 0x0806, req4->DestMac, sizeof(tArpRequest4), req4); } break; diff --git a/Modules/IPStack/arp.h b/Modules/IPStack/arp.h index 64f07c3e..07cdb64d 100644 --- a/Modules/IPStack/arp.h +++ b/Modules/IPStack/arp.h @@ -19,7 +19,7 @@ struct sArpRequest4 { tIPv4 SourceIP; tMacAddr DestMac; tIPv4 DestIP; -}; +} __attribute__((packed)); struct sArpRequest6 { Uint16 HWType; @@ -30,6 +30,6 @@ struct sArpRequest6 { tIPv6 SourceIP; tMacAddr DestMac; tIPv6 DestIP; -}; +} __attribute__((packed)); #endif diff --git a/Modules/IPStack/icmp.c b/Modules/IPStack/icmp.c index 4eb4fa40..5d53cc6c 100644 --- a/Modules/IPStack/icmp.c +++ b/Modules/IPStack/icmp.c @@ -3,11 +3,12 @@ * - ICMP Handling */ #include "ipstack.h" +#include "ipv4.h" #include "icmp.h" // === PROTOTYPES === void ICMP_Initialise(); -void ICMP_GetPacket(tInterface *Interface, int Length, void *Buffer); +void ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer); // === GLOBALS === @@ -18,7 +19,7 @@ void ICMP_GetPacket(tInterface *Interface, int Length, void *Buffer); */ void ICMP_Initialise() { - + IPv4_RegisterCallback(IP4PROT_ICMP, ICMP_GetPacket); } /** @@ -27,6 +28,11 @@ void ICMP_Initialise() */ void ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer) { - //tICMPHeader *hdr = Buffer; + tICMPHeader *hdr = Buffer; + Log("[ICMP ] hdr->Type = %i", hdr->Type); + Log("[ICMP ] hdr->Code = %i", hdr->Code); + Log("[ICMP ] hdr->Checksum = 0x%x", ntohs(hdr->Checksum)); + Log("[ICMP ] hdr->ID = 0x%x", ntohs(hdr->ID)); + Log("[ICMP ] hdr->Sequence = 0x%x", ntohs(hdr->Sequence)); } diff --git a/Modules/IPStack/ipstack.h b/Modules/IPStack/ipstack.h index 8c88daca..9315f402 100644 --- a/Modules/IPStack/ipstack.h +++ b/Modules/IPStack/ipstack.h @@ -19,16 +19,16 @@ typedef void (*tIPCallback)(tInterface *Interface, void *Address, int Length, vo union uIPv4 { Uint32 L; Uint8 B[4]; -}; +} __attribute__((packed)); union uIPv6 { Uint32 L[4]; Uint8 B[16]; -}; +} __attribute__((packed)); struct sMacAddr { Uint8 B[6]; -}; +} __attribute__((packed)); struct sInterface { struct sInterface *Next; @@ -78,6 +78,6 @@ static const tMacAddr cMAC_BROADCAST = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}; #define htonl(in) BigEndian32(in) #define ntonb(v) (v) #define ntohs(in) BigEndian16(in) -#define ntohl(in) BigEndian16(in) +#define ntohl(in) BigEndian32(in) #endif diff --git a/Modules/IPStack/ipv4.c b/Modules/IPStack/ipv4.c index 9723d8d7..7e7c5854 100644 --- a/Modules/IPStack/ipv4.c +++ b/Modules/IPStack/ipv4.c @@ -8,9 +8,12 @@ // === IMPORTS === extern tInterface *gIP_Interfaces; +extern void ICMP_Initialise(); +extern void UDP_Initialise(); // === PROTOTYPES === int IPv4_Initialise(); + int IPv4_RegisterCallback(int ID, tIPCallback Callback); void IPv4_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer); tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast); Uint32 IPv4_Netmask(int FixedBits); @@ -24,10 +27,24 @@ tIPCallback gaIPv4_Callbacks[256]; */ int IPv4_Initialise() { + ICMP_Initialise(); + UDP_Initialise(); Link_RegisterType(IPV4_ETHERNET_ID, IPv4_int_GetPacket); return 1; } +/** + * \fn int IPv4_RegisterCallback( int ID, tIPCallback Callback ) + * \brief Registers a callback + */ +int IPv4_RegisterCallback(int ID, tIPCallback Callback) +{ + if( ID < 0 || ID > 255 ) return 0; + if( gaIPv4_Callbacks[ID] ) return 0; + gaIPv4_Callbacks[ID] = Callback; + return 1; +} + /** * \fn void IPv4_int_GetPacket(tInterface *Adapter, tMacAddr From, int Length, void *Buffer) * \brief Process an IPv4 Packet @@ -40,18 +57,41 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff int dataLength; if(Length < sizeof(tIPv4Header)) return; + //Log("[IPv4 ] Version = %i", hdr->Version); + Log("[IPv4 ] HeaderLength = %i", hdr->HeaderLength); + Log("[IPv4 ] DiffServices = %i", hdr->DiffServices); + //Log("[IPv4 ] TotalLength = %i", ntohs(hdr->TotalLength) ); + //Log("[IPv4 ] Identifcation = %i", ntohs(hdr->Identifcation) ); + //Log("[IPv4 ] TTL = %i", hdr->TTL ); + Log("[IPv4 ] Protocol = %i", hdr->Protocol ); + //Log("[IPv4 ] HeaderChecksum = 0x%x", ntohs(hdr->HeaderChecksum) ); + Log("[IPv4 ] Source = %i.%i.%i.%i", + hdr->Source.B[0], hdr->Source.B[1], hdr->Source.B[2], hdr->Source.B[3] ); + Log("[IPv4 ] Destination = %i.%i.%i.%i", + hdr->Destination.B[0], hdr->Destination.B[1], + hdr->Destination.B[2], hdr->Destination.B[3] ); + // Check that the version IS IPv4 - if(hdr->Version != 4) return; + if(hdr->Version != 4) { + Log("[IPv4 ] hdr->Version(%i) != 4", hdr->Version); + return; + } // Check Header checksum //TODO // Check Packet length - if(hdr->TotalLength > Length) return; + if( ntohs(hdr->TotalLength) > Length) { + Log("[IPv4 ] hdr->TotalLength(%i) > Length(%i)", hdr->TotalLength, Length); + return; + } // Get Interface (allowing broadcasts) - iface = IPv4_GetInterface(Adapter, hdr->Source, 1); - if(!iface) return; // Not for us? Well, let's ignore it + iface = IPv4_GetInterface(Adapter, hdr->Destination, 1); + if(!iface) { + Log("[IPv4 ] Ignoring Packet (Not for us)"); + return; // Not for us? Well, let's ignore it + } // Defragment //TODO @@ -71,6 +111,9 @@ tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast) { tInterface *iface = NULL; Uint32 netmask; + Uint32 addr, this; + + addr = ntohl( Address.L ); for( iface = gIP_Interfaces; iface; iface = iface->Next) { @@ -81,10 +124,20 @@ tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast) if( !Broadcast ) continue; + this = ntohl( iface->IP4.Address.L ); + // Check for broadcast netmask = IPv4_Netmask(iface->IP4.SubnetBits); - if( (Address.L & netmask) == (iface->IP4.Address.L & netmask) - && (Address.L & ~netmask) == (0xFFFFFFFF & ~netmask) ) + + //Log("netmask = 0x%08x", netmask); + //Log("addr = 0x%08x", addr); + //Log("this = 0x%08x", this); + //Log("%08x == %08x && %08x == %08x", + // (addr & netmask), (this & netmask), + // (addr & ~netmask), (0xFFFFFFFF & ~netmask) + // ); + if( (addr & netmask) == (this & netmask) + && (addr & ~netmask) == (0xFFFFFFFF & ~netmask) ) return iface; } return NULL; @@ -100,5 +153,6 @@ Uint32 IPv4_Netmask(int FixedBits) Uint32 ret = 0xFFFFFFFF; ret >>= (32-FixedBits); ret <<= (32-FixedBits); + // Returs a little endian netmask return ret; } diff --git a/Modules/IPStack/ipv4.h b/Modules/IPStack/ipv4.h index 67b3dc83..b092becb 100644 --- a/Modules/IPStack/ipv4.h +++ b/Modules/IPStack/ipv4.h @@ -12,9 +12,10 @@ typedef struct sIPv4Header tIPv4Header; struct sIPv4Header { struct { - unsigned Version: 4; // = 4 + // Spec says Version is first, but stupid bit ordering unsigned HeaderLength: 4; // in 4-byte chunks - }; + unsigned Version: 4; // = 4 + } __attribute__((packed)); Uint8 DiffServices; // Differentiated Services Uint16 TotalLength; Uint16 Identifcation; @@ -24,7 +25,7 @@ struct sIPv4Header unsigned DontFragment: 1; unsigned MoreFragments: 1; unsigned FragOffLow: 5; - }; + } __attribute__((packed)); Uint8 FragOffHi; // Number of 8-byte blocks from the original start Uint8 TTL; // Max number of hops effectively @@ -35,7 +36,7 @@ struct sIPv4Header tIPv4 Destination; Uint8 Options[]; -}; +} __attribute__((packed)); #define IP4PROT_ICMP 1 #define IP4PROT_TCP 6 @@ -43,4 +44,7 @@ struct sIPv4Header #define IPV4_ETHERNET_ID 0x0800 +// === FUNCTIONS === +extern int IPv4_RegisterCallback(int ID, tIPCallback Callback); + #endif diff --git a/Modules/IPStack/link.c b/Modules/IPStack/link.c index 4489b522..cb59f0f1 100644 --- a/Modules/IPStack/link.c +++ b/Modules/IPStack/link.c @@ -8,12 +8,21 @@ // === CONSTANTS === #define MAX_PACKET_SIZE 2048 +// === PROTOTYPES === +void Link_RegisterType(Uint16 Type, tPacketCallback Callback); +void Link_InitCRC(); +Uint32 Link_CalculateCRC(void *Data, int Length); +void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, void *Buffer); +void Link_WatchDevice(tAdapter *Adapter); + // === GLOBALS === int giRegisteredTypes = 0; struct { Uint16 Type; tPacketCallback Callback; } *gaRegisteredTypes; + int gbLink_CRCTableGenerated = 0; +Uint32 gaiLink_CRCTable[256]; // === CODE === /** @@ -26,6 +35,9 @@ void Link_RegisterType(Uint16 Type, tPacketCallback Callback) { int i; void *tmp; + + Type = htons(Type); // Set to network order + for( i = giRegisteredTypes; i -- ; ) { if(gaRegisteredTypes[i].Type == Type) { @@ -58,16 +70,23 @@ 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; - Uint8 buf[bufSize]; + int bufSize = sizeof(tEthernetHeader) + Length + 4; + Uint8 buf[bufSize]; // dynamic stack arrays ftw! tEthernetHeader *hdr = (void*)buf; + Log("[NET ] Sending %i bytes to %02x:%02x:%02x:%02x:%02x:%02x (Type 0x%x)", + Length, To.B[0], To.B[1], To.B[2], To.B[3], To.B[4], To.B[5], Type); + hdr->Dest = To; hdr->Src = Adapter->MacAddr; hdr->Type = htons(Type); memcpy(hdr->Data, Buffer, Length); + *(Uint32*) &hdr->Data[Length] = 0; + *(Uint32*) &hdr->Data[Length] = htonl( Link_CalculateCRC(buf, bufSize) ); + + VFS_Write(Adapter->DeviceFD, bufSize, buf); } @@ -89,12 +108,16 @@ void Link_WatchDevice(tAdapter *Adapter) return ; } + if( !gbLink_CRCTableGenerated ) + Link_InitCRC(); + // Child Thread while(Adapter->DeviceFD != -1) { Uint8 buf[MAX_PACKET_SIZE]; tEthernetHeader *hdr = (void*)buf; int ret, i; + Uint32 checksum; // Wait for a packet (Read on a network device is blocking) ret = VFS_Read(Adapter->DeviceFD, MAX_PACKET_SIZE, buf); @@ -105,13 +128,27 @@ void Link_WatchDevice(tAdapter *Adapter) continue; } + Log("[NET ] Packet from %02x:%02x:%02x:%02x:%02x:%02x", + hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2], + hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5] + ); + Log("[NET ] to %02x:%02x:%02x:%02x:%02x:%02x", + hdr->Dest.B[0], hdr->Dest.B[1], hdr->Dest.B[2], + hdr->Dest.B[3], hdr->Dest.B[4], hdr->Dest.B[5] + ); + checksum = *(Uint32*)&hdr->Data[ret-sizeof(tEthernetHeader)-4]; + Log("[NET ] Checksum 0x%08x", checksum); + // Check if there is a registered callback for this packet type for( i = giRegisteredTypes; i--; ) { - if(gaRegisteredTypes[i].Type == hdr->Type) continue; + if(gaRegisteredTypes[i].Type == hdr->Type) break; } // No? Ignore it - if( i == -1 ) continue; + if( i == -1 ) { + Log("[NET ] Unregistered type 0x%x", ntohs(hdr->Type)); + continue; + } // Call the callback gaRegisteredTypes[i].Callback( @@ -124,3 +161,50 @@ void Link_WatchDevice(tAdapter *Adapter) Log("[NET ] Watcher terminated (file closed)"); } + +// From http://www.cl.cam.ac.uk/research/srg/bluebook/21/crc/node6.html +#define QUOTIENT 0x04c11db7 +void Link_InitCRC(void) +{ + int i, j; + Uint32 crc; + + for (i = 0; i < 256; i++) + { + crc = i << 24; + for (j = 0; j < 8; j++) + { + if (crc & 0x80000000) + crc = (crc << 1) ^ QUOTIENT; + else + crc = crc << 1; + } + gaiLink_CRCTable[i] = crc; + } + + gbLink_CRCTableGenerated = 1; +} + +Uint32 Link_CalculateCRC(void *Data, int Length) +{ + // x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 + Uint32 result; + int i; + Uint32 *data = Data; + + if(Length < 4) return 0; + + result = *data++ << 24; + result |= *data++ << 16; + result |= *data++ << 8; + result |= *data++; + result = ~ result; + Length -= 4; + + for( i = 0; i < Length; i++ ) + { + result = (result << 8 | *data++) ^ gaiLink_CRCTable[result >> 24]; + } + + return ~result; +} diff --git a/Modules/IPStack/main.c b/Modules/IPStack/main.c index 05e28974..7f1e02f4 100644 --- a/Modules/IPStack/main.c +++ b/Modules/IPStack/main.c @@ -12,7 +12,8 @@ #include // === IMPORTS === - int ARP_Initialise(); +extern int ARP_Initialise(); +extern int IPv4_Initialise(); // === PROTOTYPES === int IPStack_Install(char **Arguments); @@ -54,6 +55,7 @@ int IPStack_Install(char **Arguments) // Install Handlers ARP_Initialise(); + IPv4_Initialise(); if(Arguments) { diff --git a/Modules/IPStack/udp.c b/Modules/IPStack/udp.c new file mode 100644 index 00000000..c57f284c --- /dev/null +++ b/Modules/IPStack/udp.c @@ -0,0 +1,36 @@ +/* + * Acess2 IP Stack + * - UDP Handling + */ +#include "ipstack.h" +#include "udp.h" + +// === PROTOTYPES === +void UDP_Initialise(); +void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer); + +// === GLOBALS === + +// === CODE === +/** + * \fn void TCP_Initialise() + * \brief Initialise the TCP Layer + */ +void UDP_Initialise() +{ + 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 + */ +void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer) +{ + tUDPHeader *hdr = Buffer; + + 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)); +} diff --git a/Modules/IPStack/udp.h b/Modules/IPStack/udp.h new file mode 100644 index 00000000..be2ff64e --- /dev/null +++ b/Modules/IPStack/udp.h @@ -0,0 +1,22 @@ +/* + * Acess2 IP Stack + * - UDP Definitions + */ +#ifndef _UDP_H_ +#define _UDP_H_ + +#include "ipstack.h" +#include "ipv4.h" + +typedef struct sUDPHeader tUDPHeader; + +struct sUDPHeader +{ + Uint16 SourcePort; + Uint16 DestPort; + Uint16 Length; + Uint16 Checksum; + Uint8 Data[]; +}; + +#endif diff --git a/Modules/NE2000/ne2000.c b/Modules/NE2000/ne2000.c index 3717a99c..7f951543 100644 --- a/Modules/NE2000/ne2000.c +++ b/Modules/NE2000/ne2000.c @@ -3,7 +3,7 @@ * * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc */ -#define DEBUG 1 +#define DEBUG 0 #define VERSION ((0<<8)|50) #include #include @@ -20,6 +20,7 @@ #define TX_FIRST (MEM_START+RX_BUF_SIZE) #define TX_LAST (MEM_END) #define TX_BUF_SIZE 0x40 +#define MAX_PACKET_QUEUE 10 static const struct { Uint16 Vendor; @@ -60,11 +61,18 @@ enum eNe2k_Page0Write { IMR //!< interrupt mask register (init) }; +enum eNe2k_Page1Read { + CURR = 7 //!< current page +}; + // === TYPES === typedef struct sNe2k_Card { Uint16 IOBase; //!< IO Port Address from PCI Uint8 IRQ; //!< IRQ Assigned from PCI + int NumWaitingPackets; + int NextRXPage; + int NextMemPage; //!< Next Card Memory page to use Uint8 Buffer[RX_BUF_SIZE]; @@ -80,6 +88,7 @@ char *Ne2k_ReadDir(tVFS_Node *Node, int Pos); tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name); int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data); Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); +Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length); void Ne2k_IRQHandler(int IntNum); @@ -120,8 +129,8 @@ int Ne2k_Install(char **Options) // Enumerate Cards k = 0; - gpNe2k_Cards = malloc( giNe2k_CardCount * sizeof(tCard) ); - memsetd(gpNe2k_Cards, 0, giNe2k_CardCount * sizeof(tCard) / 4); + gpNe2k_Cards = calloc( giNe2k_CardCount, sizeof(tCard) ); + for( i = 0; i < NUM_COMPAT_DEVICES; i ++ ) { count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 ); @@ -133,6 +142,7 @@ int Ne2k_Install(char **Options) gpNe2k_Cards[ k ].IOBase = base; gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id ); gpNe2k_Cards[ k ].NextMemPage = 64; + gpNe2k_Cards[ k ].NextRXPage = RX_FIRST; // Install IRQ Handler IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler); @@ -143,6 +153,8 @@ int Ne2k_Install(char **Options) outb( base + ISR, 0x80 ); // Initialise Card + outb( base + CMD, 0x40|0x21 ); // Page 1, No DMA, Stop + outb( base + CURR, RX_FIRST ); // Current RX page outb( base + CMD, 0x21 ); // No DMA and Stop outb( base + DCR, 0x49 ); // Set WORD mode outb( base + IMR, 0x00 ); @@ -156,12 +168,12 @@ int Ne2k_Install(char **Options) outb( base + CMD, 0x0A ); // Remote Read, Start // Read MAC Address - gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10); inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10); inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10); inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10); inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10); inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10); inb(base+0x10); + gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10);// inb(base+0x10); + gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10);// inb(base+0x10); + gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10);// inb(base+0x10); + gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10);// inb(base+0x10); + gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10);// inb(base+0x10); + gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10);// inb(base+0x10); outb( base+PSTART, RX_FIRST); // Set Receive Start outb( base+BNRY, RX_LAST-1); // Set Boundary Page @@ -197,6 +209,7 @@ int Ne2k_Install(char **Options) gpNe2k_Cards[ k ].Node.NumACLs = 0; // Root Only gpNe2k_Cards[ k ].Node.CTime = now(); gpNe2k_Cards[ k ].Node.Write = Ne2k_Write; + gpNe2k_Cards[ k ].Node.Read = Ne2k_Read; gpNe2k_Cards[ k ].Node.IOCtl = Ne2k_IOCtl; } } @@ -331,7 +344,7 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) for(rem = Length; rem; rem -= 2) outw(Card->IOBase + 0x10, *buf++); - while( inb(Card->IOBase + ISR) == 0) // Wait for Remote DMA Complete + while( inb(Card->IOBase + ISR) == 0 ) // Wait for Remote DMA Complete ; //Proc_Yield(); outb( Card->IOBase + ISR, 0x40 ); // ACK Interrupt @@ -346,6 +359,106 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) return Length; } +/** + * \fn Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \brief Wait for and read a packet from the network card + */ +Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + tCard *Card = (tCard*)Node->ImplPtr; + Uint8 page; + Uint8 data[256]; + int i; + struct { + Uint8 Status; + Uint8 NextPacketPage; + Uint16 Length; // Little Endian + } *pktHdr; + + ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + + while(Card->NumWaitingPackets == 0) Threads_Yield(); + + // Make sure that the card is in page 0 + outb(Card->IOBase + CMD, 0|0x22); // Page 0, Start, NoDMA + + // Get BOUNDARY + page = Card->NextRXPage; + + // Set up transfer + outb(Card->IOBase + RBCR0, 0); + outb(Card->IOBase + RBCR1, 1); // 256-bytes + outb(Card->IOBase + RSAR0, 0x00); // Page Offset + outb(Card->IOBase + RSAR1, page); // Page Number + + outb(Card->IOBase + CMD, 0|0x08|0x2); // Page 0, Remote Read, Start + + // Clear Remote DMA Flag + outb(Card->IOBase + ISR, 0x40); // Bit 6 + + // Read data + for(i = 0; i < 128; i ++) + ((Uint16*)data)[i] = inw(Card->IOBase + 0x10); + + pktHdr = (void*)data; + //Log("Ne2k_Read: Recieved packet (%i bytes)", pktHdr->Length); + + // Have we read all the required bytes yet? + if(pktHdr->Length < 256 - 4) + { + if(Length > pktHdr->Length) + Length = pktHdr->Length; + memcpy(Buffer, &data[4], Length); + page ++; + if(page == RX_LAST+1) page = RX_FIRST; + } + // No? oh damn, now we need to allocate a buffer + else { + int j = 256/2; + char *buf = malloc( (pktHdr->Length + 4 + 255) & ~255 ); + + if(!buf) { + LEAVE('i', -1); + return -1; + } + + memcpy(buf, data, 256); + + page ++; + while(page != pktHdr->NextPacketPage) + { + if(page == RX_LAST+1) page = RX_FIRST; + + outb(Card->IOBase + RBCR0, 0); + outb(Card->IOBase + RBCR1, 1); // 256-bytes + outb(Card->IOBase + RSAR0, 0x00); // Page Offset + outb(Card->IOBase + RSAR1, page); // Page Number + outb(Card->IOBase + CMD, 0|0x08|0x2); // Page 0, Remote Read, Start + + for(i = 0; i < 128; i ++) + ((Uint16*)buf)[j+i] = inw(Card->IOBase + 0x10); + j += 128; + page ++; + } + + if(Length > pktHdr->Length) + Length = pktHdr->Length; + memcpy(Buffer, &buf[4], Length); + } + + // Write BNRY + if(page == RX_FIRST) + outb( Card->IOBase + BNRY, RX_LAST ); + else + outb( Card->IOBase + BNRY, page-1 ); + // Set next RX Page and decrement the waiting list + Card->NextRXPage = page; + Card->NumWaitingPackets --; + + LEAVE('i', Length); + return Length; +} + /** * \fn Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length) */ @@ -367,10 +480,28 @@ Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length) void Ne2k_IRQHandler(int IntNum) { int i; + Uint8 byte; for( i = 0; i < giNe2k_CardCount; i++ ) { - if(gpNe2k_Cards[i].IRQ == IntNum) { - LOG("Clearing interrupts on card %i (0x%x)\n", i, inb( gpNe2k_Cards[i].IOBase + ISR )); + if(gpNe2k_Cards[i].IRQ == IntNum) + { + byte = inb( gpNe2k_Cards[i].IOBase + ISR ); + + // 0: Packet recieved (no error) + if( byte & 1 ) + { + gpNe2k_Cards[i].NumWaitingPackets ++; + if( gpNe2k_Cards[i].NumWaitingPackets > MAX_PACKET_QUEUE ) + gpNe2k_Cards[i].NumWaitingPackets = MAX_PACKET_QUEUE; + } + // 1: Packet sent (no error) + // 2: Recieved with error + // 3: Transmission Halted (Excessive Collisions) + // 4: Recieve Buffer Exhausted + // 5: + // 6: Remote DMA Complete + // 7: Reset + //LOG("Clearing interrupts on card %i (was 0x%x)\n", i, byte); outb( gpNe2k_Cards[i].IOBase + ISR, 0xFF ); // Reset All return ; } diff --git a/Usermode/Applications/ifconfig_src/main.c b/Usermode/Applications/ifconfig_src/main.c index 47798a83..ea8dcb8e 100644 --- a/Usermode/Applications/ifconfig_src/main.c +++ b/Usermode/Applications/ifconfig_src/main.c @@ -135,8 +135,9 @@ int DoAutoConfig( char *Device ) { int tmp, fd; char path[sizeof(IPSTACK_ROOT)+5+1]; // ip000 - uint8_t addr[4] = {192,168,1,39}; - uint8_t gw[4] = {192,168,1,1}; + uint8_t addr[4] = {10,0,0,55}; + uint8_t gw[4] = {10,0,0,1}; + int subnet = 8; tmp = AddInterface(Device); if( tmp < 0 ) return tmp; @@ -158,14 +159,16 @@ int DoAutoConfig( char *Device ) // Set Address ioctl(fd, ioctl(fd, 3, "set_address"), addr); // Set Subnet - tmp = 24; - ioctl(fd, ioctl(fd, 3, "getset_subnet"), &tmp); + ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet); // Set Gateway ioctl(fd, ioctl(fd, 3, "set_gateway"), gw); close(fd); - printf("Set address to 192.168.1.39/24 (GW: 192.168.1.1)\n"); + printf("Set address to %i.%i.%i.%i/%i (GW: %i.%i.%i.%i)\n", + addr[0], addr[1], addr[2], addr[3], + subnet, + gw[0], gw[1], gw[2], gw[3]); return 0; } -- 2.20.1