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;
120 if(len < sizeof(tEthernetHeader)) {
121 Log_Log("Net Link", "Recieved an undersized packet (%i < %i)",
122 len, sizeof(tEthernetHeader));
128 "Packet from %02x:%02x:%02x:%02x:%02x:%02x"
129 " to %02x:%02x:%02x:%02x:%02x:%02x (Type=%04x)",
130 hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
131 hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5],
132 hdr->Dest.B[0], hdr->Dest.B[1], hdr->Dest.B[2],
133 hdr->Dest.B[3], hdr->Dest.B[4], hdr->Dest.B[5],
136 checksum = *(Uint32*)&hdr->Data[len-sizeof(tEthernetHeader)-4];
137 //Log_Log("NET", "Checksum 0x%08x", checksum);
138 // TODO: Check checksum
140 // Check if there is a registered callback for this packet type
141 for( i = giRegisteredTypes; i--; )
143 if(gaRegisteredTypes[i].Type == ntohs(hdr->Type)) break;
147 Log_Log("Net Link", "Unregistered type 0x%x", ntohs(hdr->Type));
154 gaRegisteredTypes[i].Callback(
157 len - sizeof(tEthernetHeader),
166 // From http://www.cl.cam.ac.uk/research/srg/bluebook/21/crc/node6.html
167 #define QUOTIENT 0x04c11db7
168 void Link_InitCRC(void)
173 for (i = 0; i < 256; i++)
176 for (j = 0; j < 8; j++)
178 if (crc & 0x80000000)
179 crc = (crc << 1) ^ QUOTIENT;
183 gaiLink_CRCTable[i] = crc;
186 gbLink_CRCTableGenerated = 1;
189 Uint32 Link_CalculateCRC(tIPStackBuffer *Buffer)
191 Uint32 ret = 0xFFFFFFFF;
196 while( (id = IPStack_Buffer_GetBuffer(Buffer, id, &length, &data)) != -1 )
198 ret = Link_CalculatePartialCRC(ret, data, length);
204 Uint32 Link_CalculatePartialCRC(Uint32 CRC, const void *Data, int Length)
206 // x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
207 const Uint32 *data = Data;
209 for( int i = 0; i < Length/4; i++ )
211 CRC = (CRC << 8 | *data++) ^ gaiLink_CRCTable[CRC >> 24];