+ timeout = now() + Interface->TimeoutDelay;
+
+ // Wait for a reply
+ for(;;)
+ {
+ while(lastID == giARP_LastUpdateID && now() < timeout) {
+ Threads_Yield();
+ }
+
+ if( now() >= timeout ) {
+ Log_Log("ARP4", "Timeout");
+ break; // Timeout
+ }
+
+ lastID = giARP_LastUpdateID;
+
+ Mutex_Acquire( &glARP_Cache4 );
+ for( i = 0; i < giARP_Cache4Space; i++ )
+ {
+ if(gaARP_Cache4[i].IP.L != Address.L) continue;
+
+ Mutex_Release( &glARP_Cache4 );
+ Log_Debug("ARP4", "Return %02x:%02x:%02x:%02x:%02x:%02x",
+ gaARP_Cache4[i].MAC.B[0], gaARP_Cache4[i].MAC.B[1],
+ gaARP_Cache4[i].MAC.B[2], gaARP_Cache4[i].MAC.B[3],
+ gaARP_Cache4[i].MAC.B[4], gaARP_Cache4[i].MAC.B[5]);
+ return gaARP_Cache4[i].MAC;
+ }
+ Mutex_Release( &glARP_Cache4 );
+ }
+ {
+ tMacAddr ret = {{0,0,0,0,0,0}};
+ return ret;
+ }
+}
+
+/**
+ * \brief Updates the ARP Cache entry for an IPv4 Address
+ */
+void ARP_UpdateCache4(tIPv4 SWAddr, tMacAddr HWAddr)
+{
+ int i;
+ int free = -1;
+ int oldest = 0;
+
+ // Find an entry for the IP address in the cache
+ Mutex_Acquire(&glARP_Cache4);
+ for( i = giARP_Cache4Space; i--; )
+ {
+ if(gaARP_Cache4[oldest].LastUpdate > gaARP_Cache4[i].LastUpdate) {
+ oldest = i;
+ }
+ if( gaARP_Cache4[i].IP.L == SWAddr.L ) break;
+ if( gaARP_Cache4[i].LastUpdate == 0 && free == -1 ) free = i;
+ }
+ // If there was no match, we need to make one
+ if(i == -1) {
+ if(free != -1)
+ i = free;
+ else
+ i = oldest;
+ }
+
+ Log_Log("ARP4", "Caching %i.%i.%i.%i (%02x:%02x:%02x:%02x:%02x:%02x) in %i",
+ SWAddr.B[0], SWAddr.B[1], SWAddr.B[2], SWAddr.B[3],
+ HWAddr.B[0], HWAddr.B[1], HWAddr.B[2], HWAddr.B[3], HWAddr.B[4], HWAddr.B[5],
+ i
+ );
+
+ gaARP_Cache4[i].IP = SWAddr;
+ gaARP_Cache4[i].MAC = HWAddr;
+ gaARP_Cache4[i].LastUpdate = now();
+ giARP_LastUpdateID ++;
+ Mutex_Release(&glARP_Cache4);
+}
+
+#if ARPv6
+/**
+ * \brief Updates the ARP Cache entry for an IPv6 Address
+ */
+void ARP_UpdateCache6(tIPv6 SWAddr, tMacAddr HWAddr)
+{
+ int i;
+ int free = -1;
+ int oldest = 0;
+
+ // Find an entry for the MAC address in the cache
+ Mutex_Acquire(&glARP_Cache6);
+ for( i = giARP_Cache6Space; i--; )
+ {
+ if(gaARP_Cache6[oldest].LastUpdate > gaARP_Cache6[i].LastUpdate) {
+ oldest = i;
+ }
+ if( MAC_EQU(gaARP_Cache6[i].MAC, HWAddr) ) break;
+ if( gaARP_Cache6[i].LastUpdate == 0 && free == -1 ) free = i;
+ }
+ // If there was no match, we need to make one
+ if(i == -1) {
+ if(free != -1)
+ i = free;
+ else
+ i = oldest;
+ gaARP_Cache6[i].MAC = HWAddr;
+ }
+
+ gaARP_Cache6[i].IP = SWAddr;
+ gaARP_Cache6[i].LastUpdate = now();
+ giARP_LastUpdateID ++;
+ Mutex_Release(&glARP_Cache6);