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("[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(1); // 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 gaARP_Cache4[i].MAC = HWAddr;
156 gaARP_Cache4[i].LastUpdate = now();
157 RELEASE(&glARP_Cache4);
161 * \brief Updates the ARP Cache entry for an IPv6 Address
163 void ARP_UpdateCache6(tIPv6 SWAddr, tMacAddr HWAddr)
169 // Find an entry for the MAC address in the cache
171 for( i = giARP_Cache6Space; i--; )
173 if(gaARP_Cache6[oldest].LastUpdate > gaARP_Cache6[i].LastUpdate) {
176 if( MAC_EQU(gaARP_Cache6[i].MAC, HWAddr) ) break;
177 if( gaARP_Cache6[i].LastUpdate == 0 && free == -1 ) free = i;
179 // If there was no match, we need to make one
185 gaARP_Cache6[i].MAC = HWAddr;
188 gaARP_Cache6[i].IP = SWAddr;
189 gaARP_Cache6[i].LastUpdate = now();
190 RELEASE(&glARP_Cache6);
194 * \fn void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
195 * \brief Called when an ARP packet is recieved
197 void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
199 tArpRequest4 *req4 = Buffer;
200 tArpRequest6 *req6 = Buffer;
203 // Sanity Check Packet
204 if( Length < sizeof(tArpRequest4) ) {
205 Log("[ARP ] Recieved undersized packet");
208 if( ntohs(req4->Type) != 0x0800 ) {
209 Log("[ARP ] Recieved a packet with a bad type 0x%x", ntohs(req4->Type));
212 if( req4->HWSize != 6 ) {
213 Log("[ARP ] Recieved a packet with HWSize != 6 (%i)", req4->HWSize);
216 if( !MAC_EQU(req4->SourceMac, From) ) {
217 Log("[ARP ] ARP spoofing detected", req4->HWSize);
221 Log("[ARP ] Request ID %i", ntohs(req4->Request));
223 switch( ntohs(req4->Request) )
225 case 1: // You want my IP?
226 Log("[ARP ] ARP Request Address class %i", req4->SWSize);
227 // Check what type of IP it is
228 switch( req4->SWSize )
231 Log("[ARP ] From MAC %02x:%02x:%02x:%02x:%02x:%02x",
232 req4->SourceMac.B[0], req4->SourceMac.B[1],
233 req4->SourceMac.B[2], req4->SourceMac.B[3],
234 req4->SourceMac.B[4], req4->SourceMac.B[5]);
235 Log("[ARP ] to MAC %02x:%02x:%02x:%02x:%02x:%02x",
236 req4->DestMac.B[0], req4->DestMac.B[1],
237 req4->DestMac.B[2], req4->DestMac.B[3],
238 req4->DestMac.B[4], req4->DestMac.B[5]);
239 Log("[ARP ] ARP Request IPv4 Address %i.%i.%i.%i",
240 req4->DestIP.B[0], req4->DestIP.B[1], req4->DestIP.B[2],
242 Log("[ARP ] from %i.%i.%i.%i",
243 req4->SourceIP.B[0], req4->SourceIP.B[1],
244 req4->SourceIP.B[2], req4->SourceIP.B[3]);
245 iface = IPv4_GetInterface(Adapter, req4->DestIP, 0);
248 Log("[ARP ] Caching sender's IP Address");
249 ARP_UpdateCache4(req4->SourceIP, req4->SourceMac);
251 req4->DestIP = req4->SourceIP;
252 req4->DestMac = req4->SourceMac;
253 req4->SourceIP = iface->IP4.Address;
254 req4->SourceMac = Adapter->MacAddr;
255 req4->Request = htons(2);
256 Log("[ARP ] Hey, That's us!");
257 Log("[ARP ] Sending back %02x:%02x:%02x:%02x:%02x:%02x",
258 req4->SourceMac.B[0], req4->SourceMac.B[1],
259 req4->SourceMac.B[2], req4->SourceMac.B[3],
260 req4->SourceMac.B[4], req4->SourceMac.B[5]);
261 Link_SendPacket(Adapter, 0x0806, req4->DestMac, sizeof(tArpRequest4), req4);
265 if( Length < sizeof(tArpRequest6) ) {
266 Log("[ARP ] Recieved undersized packet (IPv6)");
269 iface = IPv6_GetInterface(Adapter, req6->DestIP, 0);
272 req6->DestIP = req6->SourceIP;
273 req6->DestMac = req6->SourceMac;
274 req6->SourceIP = iface->IP6.Address;
275 req6->SourceMac = Adapter->MacAddr;
276 req6->Request = htons(2);
277 Link_SendPacket(Adapter, 0x0806, req6->DestMac, sizeof(tArpRequest6), req6);
281 Log("[ARP ] Unknown Protocol Address size (%i)", req4->SWSize);
287 case 2: // Ooh! A response!
288 // Check what type of IP it is
289 switch( req4->SWSize )
292 ARP_UpdateCache4( req4->SourceIP, From );
295 if( Length < sizeof(tArpRequest6) ) {
296 Log("[ARP ] Recieved undersized packet (IPv6)");
299 ARP_UpdateCache6( req6->SourceIP, From );
302 Log("[ARP ] Unknown Protocol Address size (%i)", req4->SWSize);