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);
86 Uint8 buf[sizeof(tEthernetHeader) + ofs + 4];
87 tEthernetHeader *hdr = (void*)buf;
89 if( ofs == 4 ) ofs = 0;
91 Log_Log("Net Link", "Sending %i bytes to %02x:%02x:%02x:%02x:%02x:%02x (Type 0x%x)",
92 length, To.B[0], To.B[1], To.B[2], To.B[3], To.B[4], To.B[5], Type);
95 memcpy(&hdr->Src, Adapter->HWAddr, 6); // TODO: Remove hard coded 6
96 hdr->Type = htons(Type);
97 *(Uint32*)(buf + sizeof(tEthernetHeader) + ofs) = 0;
99 IPStack_Buffer_AppendSubBuffer(Buffer, sizeof(tEthernetHeader), ofs + 4, hdr, NULL, NULL);
101 *(Uint32*)(buf + sizeof(tEthernetHeader) + ofs) = htonl( Link_CalculateCRC(Buffer) );
103 Log_Log("Net Link", " from %02x:%02x:%02x:%02x:%02x:%02x",
104 hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
105 hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5]
108 Adapter_SendPacket(Adapter, Buffer);
111 int Link_HandlePacket(tAdapter *Adapter, tIPStackBuffer *Buffer)
114 void *data = IPStack_Buffer_CompactBuffer(Buffer, &len);
116 tEthernetHeader *hdr = (void*)data;
118 if(len < sizeof(tEthernetHeader)) {
119 Log_Log("Net Link", "Recieved an undersized packet (%i < %i)",
120 len, sizeof(tEthernetHeader));
126 "Packet from %02x:%02x:%02x:%02x:%02x:%02x"
127 " to %02x:%02x:%02x:%02x:%02x:%02x (Type=%04x)",
128 hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
129 hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5],
130 hdr->Dest.B[0], hdr->Dest.B[1], hdr->Dest.B[2],
131 hdr->Dest.B[3], hdr->Dest.B[4], hdr->Dest.B[5],
134 // Uint32 checksum = *(Uint32*)(data + len + 4);
135 //Log_Log("NET", "Checksum 0x%08x", checksum);
136 // TODO: Check checksum
138 // Check if there is a registered callback for this packet type
140 for( i = giRegisteredTypes; i--; )
142 if(gaRegisteredTypes[i].Type == ntohs(hdr->Type)) break;
146 Log_Log("Net Link", "Unregistered type 0x%x", ntohs(hdr->Type));
153 gaRegisteredTypes[i].Callback(
156 len - sizeof(tEthernetHeader),
165 // From http://www.cl.cam.ac.uk/research/srg/bluebook/21/crc/node6.html
166 #define QUOTIENT 0x04c11db7
167 void Link_InitCRC(void)
172 for (i = 0; i < 256; i++)
175 for (j = 0; j < 8; j++)
177 if (crc & 0x80000000)
178 crc = (crc << 1) ^ QUOTIENT;
182 gaiLink_CRCTable[i] = crc;
185 gbLink_CRCTableGenerated = 1;
188 Uint32 Link_CalculateCRC(tIPStackBuffer *Buffer)
190 Uint32 ret = 0xFFFFFFFF;
195 while( (id = IPStack_Buffer_GetBuffer(Buffer, id, &length, &data)) != -1 )
197 ret = Link_CalculatePartialCRC(ret, data, length);
203 Uint32 Link_CalculatePartialCRC(Uint32 CRC, const void *Data, int Length)
205 // x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
206 const Uint32 *data = Data;
208 for( int i = 0; i < Length/4; i++ )
210 CRC = (CRC << 8 | *data++) ^ gaiLink_CRCTable[CRC >> 24];