2 * Acess2 Networking Stack
3 * - By John Hodge (thePowersGang)
6 * - Ethernet/802.3 Handling code
11 #include "include/buffer.h"
12 #include "include/adapters_int.h"
15 #define LINK_LOGPACKETS 0
16 #define VALIDATE_CHECKSUM 0
17 #define MAX_PACKET_SIZE 2048
22 tPacketCallback Callback;
27 void Link_RegisterType(Uint16 Type, tPacketCallback Callback);
28 void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, tIPStackBuffer *Buffer);
29 int Link_HandlePacket(tAdapter *Adapter, tIPStackBuffer *Buffer);
31 void Link_InitCRC(void);
32 Uint32 Link_CalculateCRC(tIPStackBuffer *Buffer);
33 Uint32 Link_CalculatePartialCRC(Uint32 CRC, const void *Data, int Length);
36 int giRegisteredTypes = 0;
37 int giRegisteredTypeSpace = 0;
38 tLink_PktType *gaRegisteredTypes;
39 int gbLink_CRCTableGenerated = 0;
40 Uint32 gaiLink_CRCTable[256];
44 * \fn void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
45 * \brief Registers a callback for a specific packet type
47 * \todo Make thread safe (place a mutex on the list)
49 void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
51 tLink_PktType *typeslot = NULL;
53 for( int i = 0; i < giRegisteredTypes; i ++)
55 if(gaRegisteredTypes[i].Type == Type) {
56 Log_Warning("Net Link", "Attempt to register 0x%x twice", Type);
60 if(gaRegisteredTypes[i].Callback == NULL)
62 typeslot = &gaRegisteredTypes[i];
69 if( giRegisteredTypes == giRegisteredTypeSpace )
71 giRegisteredTypeSpace += 5;
72 void *tmp = realloc(gaRegisteredTypes, giRegisteredTypeSpace*sizeof(tLink_PktType));
74 Log_Warning("Net Link",
75 "Out of heap space! (Attempted to allocate %i)",
76 giRegisteredTypeSpace*sizeof(tLink_PktType)
80 gaRegisteredTypes = tmp;
82 typeslot = &gaRegisteredTypes[giRegisteredTypes++];
85 typeslot->Callback = Callback;
86 typeslot->Type = Type;
90 * \brief Formats and sends a packet on the specified interface
92 void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, tIPStackBuffer *Buffer)
94 int length = IPStack_Buffer_GetLength(Buffer);
95 int ofs = (4 - (length & 3)) & 3;
96 Uint8 buf[sizeof(tEthernetHeader) + ofs + 4];
97 //Uint32 *checksum = (void*)(buf + sizeof(tEthernetHeader) + ofs);
98 tEthernetHeader *hdr = (void*)buf;
101 memcpy(&hdr->Src, Adapter->HWAddr, 6); // TODO: Remove hard coded 6
102 hdr->Type = htons(Type);
103 memset(hdr+1, 0, ofs+4); // zero padding and checksum
105 Log_Log("Net Link", "Sending %i bytes (Type 0x%x)"
106 " to %02x:%02x:%02x:%02x:%02x:%02x"
107 " from %02x:%02x:%02x:%02x:%02x:%02x",
109 To.B[0], To.B[1], To.B[2], To.B[3], To.B[4], To.B[5],
110 hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
111 hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5]
115 if( (Adapter->Type->Flags & ADAPTERFLAG_OFFLOAD_MAC) )
117 IPStack_Buffer_AppendSubBuffer(Buffer, sizeof(tEthernetHeader), ofs, hdr, NULL, NULL);
121 IPStack_Buffer_AppendSubBuffer(Buffer, sizeof(tEthernetHeader), ofs + 4, hdr, NULL, NULL);
122 *checksum = htonl( Link_CalculateCRC(Buffer) );
123 Log_Debug("Net Link", "Non-Offloaded: 0x%x, 0x%x", *checksum, ntohl(*checksum));
127 Adapter_SendPacket(Adapter, Buffer);
130 int Link_HandlePacket(tAdapter *Adapter, tIPStackBuffer *Buffer)
133 void *data = IPStack_Buffer_CompactBuffer(Buffer, &len);
135 tEthernetHeader *hdr = (void*)data;
137 if(len < sizeof(tEthernetHeader)) {
138 Log_Log("Net Link", "Recieved an undersized packet (%i < %i)",
139 len, sizeof(tEthernetHeader));
146 "eth%i Packet from %02x:%02x:%02x:%02x:%02x:%02x"
147 " to %02x:%02x:%02x:%02x:%02x:%02x (Type=%04x)",
149 hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
150 hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5],
151 hdr->Dest.B[0], hdr->Dest.B[1], hdr->Dest.B[2],
152 hdr->Dest.B[3], hdr->Dest.B[4], hdr->Dest.B[5],
157 #if VALIDATE_CHECKSUM
158 Uint32 checksum = *(Uint32*)(data + len + 4);
159 Log_Log("NET Link", "Checksum 0x%08x", checksum);
160 Uint32 calculated = Link_CalculateCRC(Buffer);
161 // TODO: Check checksum
164 Uint16 type = ntohs(hdr->Type);
165 // Check if there is a registered callback for this packet type
166 for( int i = giRegisteredTypes; i--; )
168 if(gaRegisteredTypes[i].Type == type)
171 gaRegisteredTypes[i].Callback(
174 len - sizeof(tEthernetHeader),
182 Log_Log("Net Link", "eth%i Unregistered type 0x%04x", Adapter->Index, type);
188 // From http://www.cl.cam.ac.uk/research/srg/bluebook/21/crc/node6.html
189 #define QUOTIENT 0x04c11db7
190 void Link_InitCRC(void)
192 for( int i = 0; i < 256; i++ )
194 Uint32 crc = i << 24;
195 for( int j = 0; j < 8; j++ )
198 crc = (crc << 1) ^ QUOTIENT;
202 gaiLink_CRCTable[i] = crc;
205 gbLink_CRCTableGenerated = 1;
208 Uint32 Link_CalculateCRC(tIPStackBuffer *Buffer)
210 Uint32 ret = 0xFFFFFFFF;
215 while( (id = IPStack_Buffer_GetBuffer(Buffer, id, &length, &data)) != -1 )
217 ret = Link_CalculatePartialCRC(ret, data, length);
223 Uint32 Link_CalculatePartialCRC(Uint32 CRC, const void *Data, int Length)
225 // x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
226 const Uint32 *data = Data;
228 for( int i = 0; i < Length/4; i++ )
230 CRC = (CRC << 8 | *data++) ^ gaiLink_CRCTable[CRC >> 24];