X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FIPStack%2Flink.c;h=45311d0c007dbef3646d0bb6157a1100f31e1ddd;hb=845b6f9d90bb87b5e760e4d49aa93b0e003ab750;hp=8bca51fccb694328a1f3f9ab50a7438923cab477;hpb=48743e39650eb1ef988380e9d95f27fd40d3a9ce;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/IPStack/link.c b/KernelLand/Modules/IPStack/link.c index 8bca51fc..45311d0c 100644 --- a/KernelLand/Modules/IPStack/link.c +++ b/KernelLand/Modules/IPStack/link.c @@ -1,27 +1,41 @@ /* - * Acess2 IP Stack - * - Link/Media Layer Interface + * Acess2 Networking Stack + * - By John Hodge (thePowersGang) + * + * link.c + * - Ethernet/802.3 Handling code + * TODO: Rename file */ #include "ipstack.h" #include "link.h" +#include "include/buffer.h" +#include "include/adapters_int.h" // === CONSTANTS === +#define LINK_LOGPACKETS 0 +#define VALIDATE_CHECKSUM 0 #define MAX_PACKET_SIZE 2048 +// === TYPES === +typedef struct { + Uint16 Type; + tPacketCallback Callback; +} tLink_PktType; + + // === 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); +void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, tIPStackBuffer *Buffer); + int Link_HandlePacket(tAdapter *Adapter, tIPStackBuffer *Buffer); +// --- CRC --- +void Link_InitCRC(void); +Uint32 Link_CalculateCRC(tIPStackBuffer *Buffer); +Uint32 Link_CalculatePartialCRC(Uint32 CRC, const void *Data, int Length); // === GLOBALS === int giRegisteredTypes = 0; int giRegisteredTypeSpace = 0; -struct { - Uint16 Type; - tPacketCallback Callback; -} *gaRegisteredTypes; +tLink_PktType *gaRegisteredTypes; int gbLink_CRCTableGenerated = 0; Uint32 gaiLink_CRCTable[256]; @@ -34,192 +48,187 @@ Uint32 gaiLink_CRCTable[256]; */ void Link_RegisterType(Uint16 Type, tPacketCallback Callback) { - int i; - void *tmp; + tLink_PktType *typeslot = NULL; - for( i = giRegisteredTypes; i -- ; ) + for( int i = 0; i < giRegisteredTypes; i ++) { if(gaRegisteredTypes[i].Type == Type) { Log_Warning("Net Link", "Attempt to register 0x%x twice", Type); return ; } // Ooh! Free slot! - if(gaRegisteredTypes[i].Callback == NULL) break; + if(gaRegisteredTypes[i].Callback == NULL) + { + typeslot = &gaRegisteredTypes[i]; + break; + } } - if(i == -1) + if(typeslot == NULL) { - giRegisteredTypeSpace += 5; - tmp = realloc(gaRegisteredTypes, giRegisteredTypeSpace*sizeof(*gaRegisteredTypes)); - if(!tmp) { - Log_Warning("Net Link", - "Out of heap space! (Attempted to allocate %i)", - giRegisteredTypeSpace*sizeof(*gaRegisteredTypes) - ); - return ; + if( giRegisteredTypes == giRegisteredTypeSpace ) + { + giRegisteredTypeSpace += 5; + void *tmp = realloc(gaRegisteredTypes, giRegisteredTypeSpace*sizeof(tLink_PktType)); + if(!tmp) { + Log_Warning("Net Link", + "Out of heap space! (Attempted to allocate %i)", + giRegisteredTypeSpace*sizeof(tLink_PktType) + ); + return ; + } + gaRegisteredTypes = tmp; } - gaRegisteredTypes = tmp; - i = giRegisteredTypes; - giRegisteredTypes ++; + typeslot = &gaRegisteredTypes[giRegisteredTypes++]; } - gaRegisteredTypes[i].Callback = Callback; - gaRegisteredTypes[i].Type = Type; + typeslot->Callback = Callback; + typeslot->Type = Type; } /** - * \fn void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, void *Buffer) * \brief Formats and sends a packet on the specified interface */ -void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, void *Buffer) +void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, tIPStackBuffer *Buffer) { - int bufSize = sizeof(tEthernetHeader) + ((Length+3)&~3) + 4; - Uint8 buf[bufSize]; // dynamic stack arrays ftw! + int length = IPStack_Buffer_GetLength(Buffer); + int ofs = (4 - (length & 3)) & 3; + Uint8 buf[sizeof(tEthernetHeader) + ofs + 4]; + //Uint32 *checksum = (void*)(buf + sizeof(tEthernetHeader) + ofs); tEthernetHeader *hdr = (void*)buf; - - Log_Log("Net Link", "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; + memcpy(&hdr->Src, Adapter->HWAddr, 6); // TODO: Remove hard coded 6 hdr->Type = htons(Type); - - memcpy(hdr->Data, Buffer, Length); - - *(Uint32*) &hdr->Data[bufSize-4] = 0; - *(Uint32*) &hdr->Data[bufSize-4] = htonl( Link_CalculateCRC(buf, bufSize) ); - - VFS_Write(Adapter->DeviceFD, bufSize, buf); -} + memset(hdr+1, 0, ofs+4); // zero padding and checksum -void Link_WorkerThread(void *Ptr) -{ - tAdapter *Adapter = Ptr; - - Threads_SetName(Adapter->Device); - Log_Log("Net Link", "Thread %i watching '%s'", Threads_GetTID(), Adapter->Device); + Log_Log("Net Link", "Sending %i bytes (Type 0x%x)" + " to %02x:%02x:%02x:%02x:%02x:%02x" + " from %02x:%02x:%02x:%02x:%02x:%02x", + length, Type, + To.B[0], To.B[1], To.B[2], To.B[3], To.B[4], To.B[5], + hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2], + hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5] + ); - // Child Thread - while(Adapter->DeviceFD != -1) + #if 0 + if( (Adapter->Type->Flags & ADAPTERFLAG_OFFLOAD_MAC) ) + #endif + IPStack_Buffer_AppendSubBuffer(Buffer, sizeof(tEthernetHeader), ofs, hdr, NULL, NULL); + #if 0 + else { - 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) - //Log_Debug("NET", "Waiting on adapter FD#0x%x", Adapter->DeviceFD); - ret = VFS_Read(Adapter->DeviceFD, MAX_PACKET_SIZE, buf); - if(ret == -1) break; - - if(ret < sizeof(tEthernetHeader)) { - Log_Log("Net Link", "Recieved an undersized packet (%i < %i)", - ret, sizeof(tEthernetHeader)); - continue; - } - - Log_Log("Net Link", - "Packet from %02x:%02x:%02x:%02x:%02x:%02x" - " to %02x:%02x:%02x:%02x:%02x:%02x (Type=%04x)", - hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2], - hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5], - hdr->Dest.B[0], hdr->Dest.B[1], hdr->Dest.B[2], - hdr->Dest.B[3], hdr->Dest.B[4], hdr->Dest.B[5], - ntohs(hdr->Type) - ); - checksum = *(Uint32*)&hdr->Data[ret-sizeof(tEthernetHeader)-4]; - //Log_Log("NET", "Checksum 0x%08x", checksum); - // TODO: Check checksum - - // Check if there is a registered callback for this packet type - for( i = giRegisteredTypes; i--; ) - { - if(gaRegisteredTypes[i].Type == ntohs(hdr->Type)) break; - } - // No? Ignore it - if( i == -1 ) { - Log_Log("Net Link", "Unregistered type 0x%x", ntohs(hdr->Type)); - continue; - } - - // Call the callback - gaRegisteredTypes[i].Callback( - Adapter, - hdr->Src, - ret - sizeof(tEthernetHeader), - hdr->Data - ); + IPStack_Buffer_AppendSubBuffer(Buffer, sizeof(tEthernetHeader), ofs + 4, hdr, NULL, NULL); + *checksum = htonl( Link_CalculateCRC(Buffer) ); + Log_Debug("Net Link", "Non-Offloaded: 0x%x, 0x%x", *checksum, ntohl(*checksum)); } - - Log_Log("Net Link", "Watcher terminated (file closed)"); - - Threads_Exit(0, 0); + #endif + + Adapter_SendPacket(Adapter, Buffer); } -/** - * \fn void Link_WatchDevice(tAdapter *Adapter) - * \brief Spawns a worker thread to watch the specified adapter - */ -void Link_WatchDevice(tAdapter *Adapter) +int Link_HandlePacket(tAdapter *Adapter, tIPStackBuffer *Buffer) { - int tid; + size_t len = 0; + void *data = IPStack_Buffer_CompactBuffer(Buffer, &len); + + tEthernetHeader *hdr = (void*)data; - if( !gbLink_CRCTableGenerated ) - Link_InitCRC(); + if(len < sizeof(tEthernetHeader)) { + Log_Log("Net Link", "Recieved an undersized packet (%i < %i)", + len, sizeof(tEthernetHeader)); + free(data); + return 1; + } + + #if LINK_LOGPACKETS + Log_Log("Net Link", + "eth%i Packet from %02x:%02x:%02x:%02x:%02x:%02x" + " to %02x:%02x:%02x:%02x:%02x:%02x (Type=%04x)", + Adapter->Index, + hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2], + hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5], + hdr->Dest.B[0], hdr->Dest.B[1], hdr->Dest.B[2], + hdr->Dest.B[3], hdr->Dest.B[4], hdr->Dest.B[5], + ntohs(hdr->Type) + ); + #endif - tid = Proc_SpawnWorker(Link_WorkerThread, Adapter); // Create a new worker thread + #if VALIDATE_CHECKSUM + Uint32 checksum = *(Uint32*)(data + len + 4); + Log_Log("NET Link", "Checksum 0x%08x", checksum); + Uint32 calculated = Link_CalculateCRC(Buffer); + // TODO: Check checksum + #endif - if(tid < 0) { - Log_Warning("Net Link", "Unable to create watcher thread for '%s'", Adapter->Device); - return ; + Uint16 type = ntohs(hdr->Type); + // Check if there is a registered callback for this packet type + for( int i = giRegisteredTypes; i--; ) + { + if(gaRegisteredTypes[i].Type == type) + { + // Call the callback + gaRegisteredTypes[i].Callback( + Adapter, + hdr->Src, + len - sizeof(tEthernetHeader), + hdr->Data + ); + free(data); + return 0; + } } + // No? Ignore it + Log_Log("Net Link", "eth%i Unregistered type 0x%04x", Adapter->Index, type); - Log_Log("Net Link", "Watching '%s' using tid %i", Adapter->Device, tid); + free(data); + return 1; } // 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; - } + for( int i = 0; i < 256; i++ ) + { + Uint32 crc = i << 24; + for( int j = 0; j < 8; j++ ) + { + if( crc >> 31 ) + crc = (crc << 1) ^ QUOTIENT; + else + crc = crc << 1; + } + gaiLink_CRCTable[i] = crc; + } gbLink_CRCTableGenerated = 1; } -Uint32 Link_CalculateCRC(void *Data, int Length) +Uint32 Link_CalculateCRC(tIPStackBuffer *Buffer) +{ + Uint32 ret = 0xFFFFFFFF; + const void *data; + size_t length; + + int id = -1; + while( (id = IPStack_Buffer_GetBuffer(Buffer, id, &length, &data)) != -1 ) + { + ret = Link_CalculatePartialCRC(ret, data, length); + } + + return ~ret; +} + +Uint32 Link_CalculatePartialCRC(Uint32 CRC, const 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; + const Uint32 *data = Data; + + for( int i = 0; i < Length/4; i++ ) + { + CRC = (CRC << 8 | *data++) ^ gaiLink_CRCTable[CRC >> 24]; + } + + return CRC; }