X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FIPStack%2Farp.c;h=d9422f03f0052ccb0304cb6e95d9f9f68c57ddf1;hb=HEAD;hp=abaea27584599a4e7d662503e64a5da903637054;hpb=48743e39650eb1ef988380e9d95f27fd40d3a9ce;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/IPStack/arp.c b/KernelLand/Modules/IPStack/arp.c index abaea275..d9422f03 100644 --- a/KernelLand/Modules/IPStack/arp.c +++ b/KernelLand/Modules/IPStack/arp.c @@ -7,9 +7,14 @@ #include "ipstack.h" #include "arp.h" #include "link.h" +#include "ipv4.h" // For IPv4_Netmask +#include "include/adapters_int.h" // for MAC addr +#include +#include +#include "hwaddr_cache.h" #define ARPv6 0 -#define ARP_CACHE_SIZE 64 +#define ARP_CACHE_SIZE 128 #define ARP_MAX_AGE (60*60*1000) // 1Hr // === IMPORTS === @@ -20,29 +25,9 @@ extern tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broad // === PROTOTYPES === int ARP_Initialise(); -tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address); void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer); // === GLOBALS === -struct sARP_Cache4 { - tIPv4 IP; - tMacAddr MAC; - Sint64 LastUpdate; - Sint64 LastUsed; -} *gaARP_Cache4; - int giARP_Cache4Space; -tMutex glARP_Cache4; -#if ARPv6 -struct sARP_Cache6 { - tIPv6 IP; - tMacAddr MAC; - Sint64 LastUpdate; - Sint64 LastUsed; -} *gaARP_Cache6; - int giARP_Cache6Space; -tMutex glARP_Cache6; -#endif -volatile int giARP_LastUpdateID = 0; // === CODE === /** @@ -51,90 +36,13 @@ volatile int giARP_LastUpdateID = 0; */ int ARP_Initialise() { - gaARP_Cache4 = malloc( ARP_CACHE_SIZE * sizeof(struct sARP_Cache4) ); - memset( gaARP_Cache4, 0, ARP_CACHE_SIZE * sizeof(struct sARP_Cache4) ); - giARP_Cache4Space = ARP_CACHE_SIZE; - - #if ARPv6 - gaARP_Cache6 = malloc( ARP_CACHE_SIZE * sizeof(struct sARP_Cache6) ); - memset( gaARP_Cache6, 0, ARP_CACHE_SIZE * sizeof(struct sARP_Cache6) ); - giARP_Cache6Space = ARP_CACHE_SIZE; - #endif - Link_RegisterType(0x0806, ARP_int_GetPacket); return 1; } -/** - * \brief Resolves a MAC address from an IPv4 address - */ -tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) +void ARP_Request4(tInterface *Interface, tIPv4 Address) { - int lastID; - int i; struct sArpRequest4 req; - Sint64 timeout; - - ENTER("pInterface xAddress", Interface, Address); - - // Check for broadcast - if( Address.L == -1 ) - { - LOG("Broadcast"); - LEAVE('-'); - return cMAC_BROADCAST; - } - - // Check routing tables if not on this subnet - if( IPStack_CompareAddress(4, &Address, Interface->Address, Interface->SubnetBits) == 0 ) - { - tRoute *route = IPStack_FindRoute(4, Interface, &Address); - // If the next hop is defined, use it - // - 0.0.0.0 as the next hop means "no next hop / direct" - if( route && ((tIPv4*)route->NextHop)->L != 0 ) - { - // Recursion: see /Recursion/ - LOG("Recursing with %s", IPStack_PrintAddress(4, route->NextHop)); - LEAVE('-'); - return ARP_Resolve4(Interface, *(tIPv4*)route->NextHop); - } - // No route, fall though - } - else - { - Uint32 netmask; - // Check for broadcast - netmask = IPv4_Netmask(Interface->SubnetBits); - if( (Address.L & ~netmask) == (0xFFFFFFFF & ~netmask) ) - { - LOG("Local Broadcast"); - LEAVE('-'); - return cMAC_BROADCAST; - } - } - - // Check ARP Cache - Mutex_Acquire( &glARP_Cache4 ); - for( i = 0; i < giARP_Cache4Space; i++ ) - { - if(gaARP_Cache4[i].IP.L != Address.L) continue; - - // Check if the entry needs to be refreshed - if( now() - gaARP_Cache4[i].LastUpdate > ARP_MAX_AGE ) break; - - Mutex_Release( &glARP_Cache4 ); - LOG("Return %x:%x:%x:%x:%x:%x", - 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] - ); - LEAVE('-'); - return gaARP_Cache4[i].MAC; - } - Mutex_Release( &glARP_Cache4 ); - - lastID = giARP_LastUpdateID; - // Create request Log_Log("ARP4", "Asking for address %i.%i.%i.%i", Address.B[0], Address.B[1], Address.B[2], Address.B[3] @@ -144,125 +52,18 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) req.HWSize = 6; req.SWSize = 4; req.Request = htons(1); - req.SourceMac = Interface->Adapter->MacAddr; + memcpy(&req.SourceMac, Interface->Adapter->HWAddr, 6); // TODO: Remove hard size req.SourceIP = *(tIPv4*)Interface->Address; req.DestMac = cMAC_BROADCAST; req.DestIP = Address; - - // Send Request - Link_SendPacket(Interface->Adapter, 0x0806, req.DestMac, sizeof(struct sArpRequest4), &req); - - 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); -} + // Assumes only a header and footer at link layer + tIPStackBuffer *buffer = IPStack_Buffer_CreateBuffer(3); + IPStack_Buffer_AppendSubBuffer(buffer, sizeof(struct sArpRequest4), 0, &req, NULL, NULL); -#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); + // Send Request + Link_SendPacket(Interface->Adapter, 0x0806, req.DestMac, buffer); } -#endif /** * \fn void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer) @@ -309,30 +110,37 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe switch( req4->SWSize ) { case 4: - Log_Debug("ARP", "ARP Request IPv4 Address %i.%i.%i.%i from %i.%i.%i.%i", - req4->DestIP.B[0], req4->DestIP.B[1], req4->DestIP.B[2], - req4->DestIP.B[3], - req4->SourceIP.B[0], req4->SourceIP.B[1], - req4->SourceIP.B[2], req4->SourceIP.B[3]); - Log_Debug("ARP", " from MAC %02x:%02x:%02x:%02x:%02x:%02x", - req4->SourceMac.B[0], req4->SourceMac.B[1], - req4->SourceMac.B[2], req4->SourceMac.B[3], - req4->SourceMac.B[4], req4->SourceMac.B[5]); iface = IPv4_GetInterface(Adapter, req4->DestIP, 0); if( iface ) { - ARP_UpdateCache4(req4->SourceIP, req4->SourceMac); + Log_Debug("ARP", "ARP Request IPv4 Address %i.%i.%i.%i from %i.%i.%i.%i" + " (%02x:%02x:%02x:%02x:%02x:%02x)", + req4->DestIP.B[0], req4->DestIP.B[1], req4->DestIP.B[2], + req4->DestIP.B[3], + req4->SourceIP.B[0], req4->SourceIP.B[1], + req4->SourceIP.B[2], req4->SourceIP.B[3], + req4->SourceMac.B[0], req4->SourceMac.B[1], + req4->SourceMac.B[2], req4->SourceMac.B[3], + req4->SourceMac.B[4], req4->SourceMac.B[5]); + // Someone has ARPed us, let's cache them + HWCache_Set(Adapter, 4, &req4->SourceIP, &req4->SourceMac); req4->DestIP = req4->SourceIP; req4->DestMac = req4->SourceMac; req4->SourceIP = *(tIPv4*)iface->Address;; - req4->SourceMac = Adapter->MacAddr; + memcpy(&req4->SourceMac, Adapter->HWAddr, 6); // TODO: Remove hard size req4->Request = htons(2); Log_Debug("ARP", "Sending back us (%02x:%02x:%02x:%02x:%02x:%02x)", req4->SourceMac.B[0], req4->SourceMac.B[1], req4->SourceMac.B[2], req4->SourceMac.B[3], req4->SourceMac.B[4], req4->SourceMac.B[5]); - Link_SendPacket(Adapter, 0x0806, req4->DestMac, sizeof(tArpRequest4), req4); + + // Assumes only a header and footer at link layer + tIPStackBuffer *buffer = IPStack_Buffer_CreateBuffer(3); + IPStack_Buffer_AppendSubBuffer(buffer, + sizeof(struct sArpRequest4), 0, req4, + NULL, NULL); + Link_SendPacket(Adapter, 0x0806, req4->DestMac, buffer); } break; #if ARPv6 @@ -373,7 +181,7 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe switch( req4->SWSize ) { case 4: - ARP_UpdateCache4( req4->SourceIP, From ); + HWCache_Set(Adapter, 4, &req4->SourceIP, &From); break; #if ARPv6 case 6: @@ -381,7 +189,7 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe Log_Debug("ARP", "Recieved undersized packet (IPv6)"); return ; } - ARP_UpdateCache6( req6->SourceIP, From ); + HWCache_Set(Adapter, 6, &req6->SourceIP, &From ); break; #endif default: