3 * - Address Resolution Protocol
10 #define ARP_CACHE_SIZE 64
11 #define ARP_MAX_AGE (60*60*1000) // 1Hr
14 extern tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast);
15 extern tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast);
19 tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address);
20 void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer);
29 int giARP_Cache4Space;
30 tSpinlock glARP_Cache4;
37 int giARP_Cache6Space;
38 tSpinlock glARP_Cache6;
39 int giARP_LastUpdateID = 0;
43 * \fn int ARP_Initialise()
44 * \brief Initalise the ARP section
48 gaARP_Cache4 = malloc( ARP_CACHE_SIZE * sizeof(struct sARP_Cache4) );
49 memset( gaARP_Cache4, 0, ARP_CACHE_SIZE * sizeof(struct sARP_Cache4) );
50 giARP_Cache4Space = ARP_CACHE_SIZE;
52 gaARP_Cache6 = malloc( ARP_CACHE_SIZE * sizeof(struct sARP_Cache6) );
53 memset( gaARP_Cache6, 0, ARP_CACHE_SIZE * sizeof(struct sARP_Cache6) );
54 giARP_Cache6Space = ARP_CACHE_SIZE;
56 Link_RegisterType(0x0806, ARP_int_GetPacket);
61 * \brief Resolves a MAC address from an IPv4 address
63 tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address)
67 struct sArpRequest4 req;
69 ENTER("pInterface xAddress", Interface, Address);
71 LOCK( &glARP_Cache4 );
72 for( i = 0; i < giARP_Cache4Space; i++ )
74 if(gaARP_Cache4[i].IP.L != Address.L) continue;
76 // Check if the entry needs to be refreshed
77 if( now() - gaARP_Cache4[i].LastUpdate > ARP_MAX_AGE ) break;
79 RELEASE( &glARP_Cache4 );
80 LOG("Return %x:%x:%x:%x:%x:%x",
81 gaARP_Cache4[i].MAC.B[0], gaARP_Cache4[i].MAC.B[1],
82 gaARP_Cache4[i].MAC.B[2], gaARP_Cache4[i].MAC.B[3],
83 gaARP_Cache4[i].MAC.B[4], gaARP_Cache4[i].MAC.B[5]
86 return gaARP_Cache4[i].MAC;
88 RELEASE( &glARP_Cache4 );
90 lastID = giARP_LastUpdateID;
93 Log_Log("ARP4", "Asking for address %i.%i.%i.%i",
94 Address.B[0], Address.B[1], Address.B[2], Address.B[3]
96 req.HWType = htons(0x0001); // Ethernet
97 req.Type = htons(0x0800);
100 req.Request = htons(1);
101 req.SourceMac = Interface->Adapter->MacAddr;
102 req.SourceIP = Interface->IP4.Address;
103 req.DestMac = cMAC_BROADCAST;
104 req.DestIP = Address;
107 Link_SendPacket(Interface->Adapter, 0x0806, req.DestMac, sizeof(struct sArpRequest4), &req);
112 while(lastID == giARP_LastUpdateID) Threads_Yield();
113 lastID = giARP_LastUpdateID;
115 LOCK( &glARP_Cache4 );
116 for( i = 0; i < giARP_Cache4Space; i++ )
118 if(gaARP_Cache4[i].IP.L != Address.L) continue;
120 RELEASE( &glARP_Cache4 );
121 return gaARP_Cache4[i].MAC;
123 RELEASE( &glARP_Cache4 );
128 * \brief Updates the ARP Cache entry for an IPv4 Address
130 void ARP_UpdateCache4(tIPv4 SWAddr, tMacAddr HWAddr)
136 // Find an entry for the IP address in the cache
138 for( i = giARP_Cache4Space; i--; )
140 if(gaARP_Cache4[oldest].LastUpdate > gaARP_Cache4[i].LastUpdate) {
143 if( gaARP_Cache4[i].IP.L == SWAddr.L ) break;
144 if( gaARP_Cache4[i].LastUpdate == 0 && free == -1 ) free = i;
146 // If there was no match, we need to make one
152 gaARP_Cache4[i].IP = SWAddr;
155 Log_Log("ARP4", "Caching %i.%i.%i.%i (%02x:%02x:%02x:%02x:%02x:%02x) in %i",
156 SWAddr.B[0], SWAddr.B[1], SWAddr.B[2], SWAddr.B[3],
157 HWAddr.B[0], HWAddr.B[1], HWAddr.B[2], HWAddr.B[3], HWAddr.B[4], HWAddr.B[5],
161 gaARP_Cache4[i].MAC = HWAddr;
162 gaARP_Cache4[i].LastUpdate = now();
163 giARP_LastUpdateID ++;
164 RELEASE(&glARP_Cache4);
168 * \brief Updates the ARP Cache entry for an IPv6 Address
170 void ARP_UpdateCache6(tIPv6 SWAddr, tMacAddr HWAddr)
176 // Find an entry for the MAC address in the cache
178 for( i = giARP_Cache6Space; i--; )
180 if(gaARP_Cache6[oldest].LastUpdate > gaARP_Cache6[i].LastUpdate) {
183 if( MAC_EQU(gaARP_Cache6[i].MAC, HWAddr) ) break;
184 if( gaARP_Cache6[i].LastUpdate == 0 && free == -1 ) free = i;
186 // If there was no match, we need to make one
192 gaARP_Cache6[i].MAC = HWAddr;
195 gaARP_Cache6[i].IP = SWAddr;
196 gaARP_Cache6[i].LastUpdate = now();
197 giARP_LastUpdateID ++;
198 RELEASE(&glARP_Cache6);
202 * \fn void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
203 * \brief Called when an ARP packet is recieved
205 void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
207 tArpRequest4 *req4 = Buffer;
208 tArpRequest6 *req6 = Buffer;
211 // Sanity Check Packet
212 if( Length < sizeof(tArpRequest4) ) {
213 Log_Log("ARP", "Recieved undersized packet");
216 if( ntohs(req4->Type) != 0x0800 ) {
217 Log_Log("ARP", "Recieved a packet with a bad type 0x%x", ntohs(req4->Type));
220 if( req4->HWSize != 6 ) {
221 Log_Log("ARP", "Recieved a packet with HWSize != 6 (%i)", req4->HWSize);
224 #if ARP_DETECT_SPOOFS
225 if( !MAC_EQU(req4->SourceMac, From) ) {
226 Log_Log("ARP", "ARP spoofing detected "
227 "(%02x%02x:%02x%02x:%02x%02x != %02x%02x:%02x%02x:%02x%02x)",
228 req4->SourceMac.B[0], req4->SourceMac.B[1], req4->SourceMac.B[2],
229 req4->SourceMac.B[3], req4->SourceMac.B[4], req4->SourceMac.B[5],
230 From.B[0], From.B[1], From.B[2],
231 From.B[3], From.B[4], From.B[5]
237 Log_Debug("ARP", "Request ID %i", ntohs(req4->Request));
239 switch( ntohs(req4->Request) )
241 case 1: // You want my IP?
242 Log_Debug("ARP", "ARP Request Address class %i", req4->SWSize);
243 // Check what type of IP it is
244 switch( req4->SWSize )
247 Log_Debug("ARP", "From MAC %02x:%02x:%02x:%02x:%02x:%02x",
248 req4->SourceMac.B[0], req4->SourceMac.B[1],
249 req4->SourceMac.B[2], req4->SourceMac.B[3],
250 req4->SourceMac.B[4], req4->SourceMac.B[5]);
251 Log_Debug("ARP", "to MAC %02x:%02x:%02x:%02x:%02x:%02x",
252 req4->DestMac.B[0], req4->DestMac.B[1],
253 req4->DestMac.B[2], req4->DestMac.B[3],
254 req4->DestMac.B[4], req4->DestMac.B[5]);
255 Log_Debug("ARP", "ARP Request IPv4 Address %i.%i.%i.%i",
256 req4->DestIP.B[0], req4->DestIP.B[1], req4->DestIP.B[2],
258 Log_Debug("ARP", "from %i.%i.%i.%i",
259 req4->SourceIP.B[0], req4->SourceIP.B[1],
260 req4->SourceIP.B[2], req4->SourceIP.B[3]);
261 iface = IPv4_GetInterface(Adapter, req4->DestIP, 0);
264 Log_Debug("ARP", "Caching sender's IP Address");
265 ARP_UpdateCache4(req4->SourceIP, req4->SourceMac);
267 req4->DestIP = req4->SourceIP;
268 req4->DestMac = req4->SourceMac;
269 req4->SourceIP = iface->IP4.Address;
270 req4->SourceMac = Adapter->MacAddr;
271 req4->Request = htons(2);
272 Log_Debug("ARP", "Hey, That's us!");
273 Log_Debug("ARP", "Sending back %02x:%02x:%02x:%02x:%02x:%02x",
274 req4->SourceMac.B[0], req4->SourceMac.B[1],
275 req4->SourceMac.B[2], req4->SourceMac.B[3],
276 req4->SourceMac.B[4], req4->SourceMac.B[5]);
277 Link_SendPacket(Adapter, 0x0806, req4->DestMac, sizeof(tArpRequest4), req4);
281 if( Length < sizeof(tArpRequest6) ) {
282 Log_Debug("ARP", "Recieved undersized packet (IPv6)");
285 iface = IPv6_GetInterface(Adapter, req6->DestIP, 0);
288 req6->DestIP = req6->SourceIP;
289 req6->DestMac = req6->SourceMac;
290 req6->SourceIP = iface->IP6.Address;
291 req6->SourceMac = Adapter->MacAddr;
292 req6->Request = htons(2);
293 Link_SendPacket(Adapter, 0x0806, req6->DestMac, sizeof(tArpRequest6), req6);
297 Log_Debug("ARP", "Unknown Protocol Address size (%i)", req4->SWSize);
303 case 2: // Ooh! A response!
304 // Check what type of IP it is
305 switch( req4->SWSize )
308 ARP_UpdateCache4( req4->SourceIP, From );
311 if( Length < sizeof(tArpRequest6) ) {
312 Log_Debug("ARP", "Recieved undersized packet (IPv6)");
315 ARP_UpdateCache6( req6->SourceIP, From );
318 Log_Debug("ARP", "Unknown Protocol Address size (%i)", req4->SWSize);
325 Warning("[ARP ] Unknown Request ID %i", ntohs(req4->Request));