X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FIPStack%2Farp.c;h=82382635872475bec621a4f8d7fc8cb5dec58a90;hb=11e9a26f9aa039eb2b4edcf55c1295e640b5999a;hp=fab74f8504117abab67cbe5f9a596a80a20bc795;hpb=be53e78f163ec7e0e5271d41650476bf5e1de571;p=tpg%2Facess2.git diff --git a/Modules/IPStack/arp.c b/Modules/IPStack/arp.c index fab74f85..82382635 100644 --- a/Modules/IPStack/arp.c +++ b/Modules/IPStack/arp.c @@ -1,18 +1,22 @@ /* * Acess2 IP Stack * - Address Resolution Protocol + * - Part of the IPv4 protocol */ #define DEBUG 0 #include "ipstack.h" #include "arp.h" #include "link.h" +#define ARPv6 0 #define ARP_CACHE_SIZE 64 #define ARP_MAX_AGE (60*60*1000) // 1Hr // === IMPORTS === extern tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast); +#if ARPv6 extern tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast); +#endif // === PROTOTYPES === int ARP_Initialise(); @@ -27,7 +31,8 @@ struct sARP_Cache4 { Sint64 LastUsed; } *gaARP_Cache4; int giARP_Cache4Space; -tSpinlock glARP_Cache4; +tMutex glARP_Cache4; +#if ARPv6 struct sARP_Cache6 { tIPv6 IP; tMacAddr MAC; @@ -35,7 +40,8 @@ struct sARP_Cache6 { Sint64 LastUsed; } *gaARP_Cache6; int giARP_Cache6Space; -tSpinlock glARP_Cache6; +tMutex glARP_Cache6; +#endif int giARP_LastUpdateID = 0; // === CODE === @@ -49,9 +55,11 @@ int ARP_Initialise() 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; @@ -65,10 +73,26 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) int lastID; int i; struct sArpRequest4 req; + Sint64 timeout; ENTER("pInterface xAddress", Interface, Address); - LOCK( &glARP_Cache4 ); + // 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( route ) { + // If the next hop is defined, use it + // - 0.0.0.0 as the next hop means "no next hop / direct" + if( ((tIPv4*)route->NextHop)->L != 0 ) { + // Recursion: see /Recursion/ + return ARP_Resolve4(Interface, *(tIPv4*)route->NextHop); + } + } + } + + // Check ARP Cache + Mutex_Acquire( &glARP_Cache4 ); for( i = 0; i < giARP_Cache4Space; i++ ) { if(gaARP_Cache4[i].IP.L != Address.L) continue; @@ -76,7 +100,7 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) // Check if the entry needs to be refreshed if( now() - gaARP_Cache4[i].LastUpdate > ARP_MAX_AGE ) break; - RELEASE( &glARP_Cache4 ); + 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], @@ -85,7 +109,7 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) LEAVE('-'); return gaARP_Cache4[i].MAC; } - RELEASE( &glARP_Cache4 ); + Mutex_Release( &glARP_Cache4 ); lastID = giARP_LastUpdateID; @@ -99,28 +123,38 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) req.SWSize = 4; req.Request = htons(1); req.SourceMac = Interface->Adapter->MacAddr; - req.SourceIP = Interface->IP4.Address; + 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) Threads_Yield(); + while(lastID == giARP_LastUpdateID && now() < timeout) + Threads_Yield(); + + if( now() >= timeout ) break; // Timeout + lastID = giARP_LastUpdateID; - LOCK( &glARP_Cache4 ); + Mutex_Acquire( &glARP_Cache4 ); for( i = 0; i < giARP_Cache4Space; i++ ) { if(gaARP_Cache4[i].IP.L != Address.L) continue; - RELEASE( &glARP_Cache4 ); + Mutex_Release( &glARP_Cache4 ); return gaARP_Cache4[i].MAC; } - RELEASE( &glARP_Cache4 ); + Mutex_Release( &glARP_Cache4 ); + } + { + tMacAddr ret = {{0,0,0,0,0,0}}; + return ret; } } @@ -134,7 +168,7 @@ void ARP_UpdateCache4(tIPv4 SWAddr, tMacAddr HWAddr) int oldest = 0; // Find an entry for the IP address in the cache - LOCK(&glARP_Cache4); + Mutex_Acquire(&glARP_Cache4); for( i = giARP_Cache4Space; i--; ) { if(gaARP_Cache4[oldest].LastUpdate > gaARP_Cache4[i].LastUpdate) { @@ -161,9 +195,10 @@ void ARP_UpdateCache4(tIPv4 SWAddr, tMacAddr HWAddr) gaARP_Cache4[i].MAC = HWAddr; gaARP_Cache4[i].LastUpdate = now(); giARP_LastUpdateID ++; - RELEASE(&glARP_Cache4); + Mutex_Release(&glARP_Cache4); } +#if ARPv6 /** * \brief Updates the ARP Cache entry for an IPv6 Address */ @@ -174,7 +209,7 @@ void ARP_UpdateCache6(tIPv6 SWAddr, tMacAddr HWAddr) int oldest = 0; // Find an entry for the MAC address in the cache - LOCK(&glARP_Cache6); + Mutex_Acquire(&glARP_Cache6); for( i = giARP_Cache6Space; i--; ) { if(gaARP_Cache6[oldest].LastUpdate > gaARP_Cache6[i].LastUpdate) { @@ -195,8 +230,9 @@ void ARP_UpdateCache6(tIPv6 SWAddr, tMacAddr HWAddr) gaARP_Cache6[i].IP = SWAddr; gaARP_Cache6[i].LastUpdate = now(); giARP_LastUpdateID ++; - RELEASE(&glARP_Cache6); + Mutex_Release(&glARP_Cache6); } +#endif /** * \fn void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer) @@ -205,11 +241,13 @@ void ARP_UpdateCache6(tIPv6 SWAddr, tMacAddr HWAddr) void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer) { tArpRequest4 *req4 = Buffer; + #if ARPv6 tArpRequest6 *req6 = Buffer; + #endif tInterface *iface; // Sanity Check Packet - if( Length < sizeof(tArpRequest4) ) { + if( Length < (int)sizeof(tArpRequest4) ) { Log_Log("ARP", "Recieved undersized packet"); return ; } @@ -234,38 +272,30 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe } #endif - Log_Debug("ARP", "Request ID %i", ntohs(req4->Request)); - switch( ntohs(req4->Request) ) { case 1: // You want my IP? - Log_Debug("ARP", "ARP Request Address class %i", req4->SWSize); // Check what type of IP it is switch( req4->SWSize ) { case 4: - 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]); - //Log_Debug("ARP", "to MAC %02x:%02x:%02x:%02x:%02x:%02x", - // req4->DestMac.B[0], req4->DestMac.B[1], - // req4->DestMac.B[2], req4->DestMac.B[3], - // req4->DestMac.B[4], req4->DestMac.B[5]); 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 ) { - Log_Debug("ARP", "Caching sender's IP Address"); ARP_UpdateCache4(req4->SourceIP, req4->SourceMac); req4->DestIP = req4->SourceIP; req4->DestMac = req4->SourceMac; - req4->SourceIP = iface->IP4.Address; + req4->SourceIP = *(tIPv4*)iface->Address;; req4->SourceMac = Adapter->MacAddr; req4->Request = htons(2); Log_Debug("ARP", "Sending back us (%02x:%02x:%02x:%02x:%02x:%02x)", @@ -275,8 +305,9 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe Link_SendPacket(Adapter, 0x0806, req4->DestMac, sizeof(tArpRequest4), req4); } break; + #if ARPv6 case 6: - if( Length < sizeof(tArpRequest6) ) { + if( Length < (int)sizeof(tArpRequest6) ) { Log_Log("ARP", "Recieved undersized packet (IPv6)"); return ; } @@ -289,7 +320,7 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe { req6->DestIP = req6->SourceIP; req6->DestMac = req6->SourceMac; - req6->SourceIP = iface->IP6.Address; + req6->SourceIP = *(tIPv6*)iface->Address; req6->SourceMac = Adapter->MacAddr; req6->Request = htons(2); Log_Debug("ARP", "Sending back us (%02x:%02x:%02x:%02x:%02x:%02x)", @@ -299,6 +330,7 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe Link_SendPacket(Adapter, 0x0806, req6->DestMac, sizeof(tArpRequest6), req6); } break; + #endif default: Log_Debug("ARP", "Unknown Protocol Address size (%i)", req4->SWSize); return ; @@ -313,13 +345,15 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe case 4: ARP_UpdateCache4( req4->SourceIP, From ); break; + #if ARPv6 case 6: - if( Length < sizeof(tArpRequest6) ) { + if( Length < (int)sizeof(tArpRequest6) ) { Log_Debug("ARP", "Recieved undersized packet (IPv6)"); return ; } ARP_UpdateCache6( req6->SourceIP, From ); break; + #endif default: Log_Debug("ARP", "Unknown Protocol Address size (%i)", req4->SWSize); return ;