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 MAX_PACKET_SIZE 2048
18 void Link_RegisterType(Uint16 Type, tPacketCallback Callback);
19 void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, tIPStackBuffer *Buffer);
20 int Link_HandlePacket(tAdapter *Adapter, tIPStackBuffer *Buffer);
22 void Link_InitCRC(void);
23 Uint32 Link_CalculateCRC(tIPStackBuffer *Buffer);
24 Uint32 Link_CalculatePartialCRC(Uint32 CRC, const void *Data, int Length);
27 int giRegisteredTypes = 0;
28 int giRegisteredTypeSpace = 0;
31 tPacketCallback Callback;
33 int gbLink_CRCTableGenerated = 0;
34 Uint32 gaiLink_CRCTable[256];
38 * \fn void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
39 * \brief Registers a callback for a specific packet type
41 * \todo Make thread safe (place a mutex on the list)
43 void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
48 for( i = giRegisteredTypes; i -- ; )
50 if(gaRegisteredTypes[i].Type == Type) {
51 Log_Warning("Net Link", "Attempt to register 0x%x twice", Type);
55 if(gaRegisteredTypes[i].Callback == NULL) break;
60 giRegisteredTypeSpace += 5;
61 tmp = realloc(gaRegisteredTypes, giRegisteredTypeSpace*sizeof(*gaRegisteredTypes));
63 Log_Warning("Net Link",
64 "Out of heap space! (Attempted to allocate %i)",
65 giRegisteredTypeSpace*sizeof(*gaRegisteredTypes)
69 gaRegisteredTypes = tmp;
70 i = giRegisteredTypes;
74 gaRegisteredTypes[i].Callback = Callback;
75 gaRegisteredTypes[i].Type = Type;
79 * \fn void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, void *Buffer)
80 * \brief Formats and sends a packet on the specified interface
82 void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, tIPStackBuffer *Buffer)
84 int length = IPStack_Buffer_GetLength(Buffer);
85 int ofs = (4 - (length & 3)) & 3;
86 Uint8 buf[sizeof(tEthernetHeader) + ofs + 4];
87 Uint32 *checksum = (void*)(buf + sizeof(tEthernetHeader) + ofs);
88 tEthernetHeader *hdr = (void*)buf;
90 Log_Log("Net Link", "Sending %i bytes to %02x:%02x:%02x:%02x:%02x:%02x (Type 0x%x)",
91 length, To.B[0], To.B[1], To.B[2], To.B[3], To.B[4], To.B[5], Type);
94 memcpy(&hdr->Src, Adapter->HWAddr, 6); // TODO: Remove hard coded 6
95 hdr->Type = htons(Type);
96 memset(hdr, 0, ofs+4); // zero padding and checksum
98 if( (Adapter->Type->Flags & ADAPTERFLAG_OFFLOAD_MAC) )
99 IPStack_Buffer_AppendSubBuffer(Buffer, sizeof(tEthernetHeader), ofs, hdr, NULL, NULL);
102 IPStack_Buffer_AppendSubBuffer(Buffer, sizeof(tEthernetHeader), ofs + 4, hdr, NULL, NULL);
103 *checksum = htonl( Link_CalculateCRC(Buffer) );
104 Log_Debug("Net Link", "Non-Offloaded: 0x%x, 0x%x", *checksum, ntohl(*checksum));
107 Log_Log("Net Link", " from %02x:%02x:%02x:%02x:%02x:%02x",
108 hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
109 hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5]
112 Adapter_SendPacket(Adapter, Buffer);
115 int Link_HandlePacket(tAdapter *Adapter, tIPStackBuffer *Buffer)
118 void *data = IPStack_Buffer_CompactBuffer(Buffer, &len);
120 tEthernetHeader *hdr = (void*)data;
122 if(len < sizeof(tEthernetHeader)) {
123 Log_Log("Net Link", "Recieved an undersized packet (%i < %i)",
124 len, sizeof(tEthernetHeader));
130 "Packet from %02x:%02x:%02x:%02x:%02x:%02x"
131 " to %02x:%02x:%02x:%02x:%02x:%02x (Type=%04x)",
132 hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
133 hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5],
134 hdr->Dest.B[0], hdr->Dest.B[1], hdr->Dest.B[2],
135 hdr->Dest.B[3], hdr->Dest.B[4], hdr->Dest.B[5],
138 // Uint32 checksum = *(Uint32*)(data + len + 4);
139 //Log_Log("NET", "Checksum 0x%08x", checksum);
140 // TODO: Check checksum
142 // Check if there is a registered callback for this packet type
144 for( i = giRegisteredTypes; i--; )
146 if(gaRegisteredTypes[i].Type == ntohs(hdr->Type)) break;
150 Log_Log("Net Link", "Unregistered type 0x%x", ntohs(hdr->Type));
157 gaRegisteredTypes[i].Callback(
160 len - sizeof(tEthernetHeader),
169 // From http://www.cl.cam.ac.uk/research/srg/bluebook/21/crc/node6.html
170 #define QUOTIENT 0x04c11db7
171 void Link_InitCRC(void)
176 for (i = 0; i < 256; i++)
179 for (j = 0; j < 8; j++)
181 if (crc & 0x80000000)
182 crc = (crc << 1) ^ QUOTIENT;
186 gaiLink_CRCTable[i] = crc;
189 gbLink_CRCTableGenerated = 1;
192 Uint32 Link_CalculateCRC(tIPStackBuffer *Buffer)
194 Uint32 ret = 0xFFFFFFFF;
199 while( (id = IPStack_Buffer_GetBuffer(Buffer, id, &length, &data)) != -1 )
201 ret = Link_CalculatePartialCRC(ret, data, length);
207 Uint32 Link_CalculatePartialCRC(Uint32 CRC, const void *Data, int Length)
209 // x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
210 const Uint32 *data = Data;
212 for( int i = 0; i < Length/4; i++ )
214 CRC = (CRC << 8 | *data++) ^ gaiLink_CRCTable[CRC >> 24];