X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FIPStack%2Farp.c;h=0ba0fd359aa58b08bc543022c211aa05d1da6105;hb=25f19babe7a0ab75d04ff7e6f98f7bcb65fb8941;hp=cc194e90806849560fb0d01c44a42e15de8540b5;hpb=6c5a509b5e14e097ca537c539bc9babe3b8f0c4c;p=tpg%2Facess2.git diff --git a/Modules/IPStack/arp.c b/Modules/IPStack/arp.c index cc194e90..0ba0fd35 100644 --- a/Modules/IPStack/arp.c +++ b/Modules/IPStack/arp.c @@ -7,6 +7,7 @@ #include "link.h" #define ARP_CACHE_SIZE 64 +#define ARP_MAX_AGE (60*60*1000) // 1Hr // === IMPORTS === extern tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast); @@ -23,8 +24,11 @@ struct sARP_Cache { tIPv4 IP4; tIPv6 IP6; Sint64 LastUpdate; + Sint64 LastUsed; } *gaARP_Cache; int giARP_CacheSpace; + int giARP_LastUpdateID = 0; +tSpinlock glARP_Cache; // === CODE === /** @@ -41,6 +45,45 @@ int ARP_Initialise() return 1; } +/** + * \brief Resolves a MAC address from an IPv4 address + */ +tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) +{ + int lastID; + int i; + + LOCK( &glARP_Cache ); + for( i = 0; i < giARP_CacheSpace; i++ ) + { + if(gaARP_Cache[i].IP4.L != Address.L) continue; + + // Check if the entry needs to be refreshed + if( now() - gaARP_Cache[i].LastUpdate > ARP_MAX_AGE ) break; + + RELEASE( &glARP_Cache ); + return gaARP_Cache[i].MAC; + } + RELEASE( &glARP_Cache ); + + lastID = giARP_LastUpdateID; + ARP_int_Resolve4(Interface, Address); + for(;;) + { + while(lastID == giARP_LastUpdateID) Threads_Yield(); + + LOCK( &glARP_Cache ); + for( i = 0; i < giARP_CacheSpace; i++ ) + { + if(gaARP_Cache[i].IP4.L != Address.L) continue; + + RELEASE( &glARP_Cache ); + return gaARP_Cache[i].MAC; + } + RELEASE( &glARP_Cache ); + } +} + /** * \fn int ARP_int_Resolve4(tInterface *Interface, tIPv4 Address) * \brief Request the network to resolve an IPv4 Address @@ -95,21 +138,43 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe return; } - switch( req4->Request ) + Log("[ARP ] Request ID %i", ntohs(req4->Request)); + + switch( ntohs(req4->Request) ) { case 1: // You want my IP? + Log("[ARP ] ARP Request Address class %i", req4->SWSize); // Check what type of IP it is switch( req4->SWSize ) { case 4: + Log("[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("[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("[ARP ] ARP Request IPv4 Address %i.%i.%i.%i", + req4->DestIP.B[0], req4->DestIP.B[1], req4->DestIP.B[2], + req4->DestIP.B[3]); + Log("[ARP ] from %i.%i.%i.%i", + req4->SourceIP.B[0], req4->SourceIP.B[1], + req4->SourceIP.B[2], req4->SourceIP.B[3]); iface = IPv4_GetInterface(Adapter, req4->DestIP, 0); if( iface ) { - IP4_SET(req4->DestIP, req4->SourceIP); + req4->DestIP = req4->SourceIP; req4->DestMac = req4->SourceMac; req4->SourceIP = iface->IP4.Address; req4->SourceMac = Adapter->MacAddr; req4->Request = htons(2); + Log("[ARP ] Hey, That's us!"); + Log("[ARP ] Sending back %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); } break; @@ -138,6 +203,7 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe case 2: // Ooh! A response! // Find an entry for the MAC address in the cache + LOCK(&glARP_Cache); for( i = giARP_CacheSpace; i--; ) { if(gaARP_Cache[oldest].LastUpdate > gaARP_Cache[i].LastUpdate) { @@ -168,10 +234,12 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe break; default: Log("[ARP ] Unknown Protocol Address size (%i)", req4->SWSize); + RELEASE(&glARP_Cache); return ; } gaARP_Cache[i].LastUpdate = now(); + RELEASE(&glARP_Cache); break; } }