📄 arp.c
字号:
/* Next time start from next entry */
aenext = (aenext + 1);
if( aenext >= ARP_TSIZE )
aenext = 1;
qstruct = &arp_table[found];
/* Set ARP initial parameters */
qstruct->state = ARP_RESERVED;
qstruct->type = type;
/* Was return(i)!!! <-wrong!! */
return((UINT8)found);
}
/** \brief Add given IP address and MAC address to ARP cache
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 10.07.2002
* \param pra - protocol address (assumed IPv4)
* \param hwadr - pointer to Ethernet MAC address (6 bytes)
* \param type - type of address allocated if not found. Can be one of the
* following:
* \li #ARP_FIXED_IP
* \li #ARP_TEMP_IP
* \return
* \li 0 - Address already in cache. Refreshed.
* \li 1 - New entry in ARP cache created
*
* New IP address is added to ARP cache based on the information
* supplied to function as parameters.
*/
INT8 arp_add (UINT32 pra, UINT8* hwadr, UINT8 type)
{
struct arp_entry *qstruct;
INT8 i;
INT8 j;
for( i=0; i<ARP_TSIZE; i++ ) {
qstruct = &arp_table[i];
if( qstruct->state == ARP_FREE )
continue;
if((qstruct->pradr == pra)&&(pra != IP_BROADCAST_ADDRESS)) {
/* The address is in cache, refresh it */
ARP_DEBUGOUT(" Refreshing Existing ARP Entry..\n\r");
for( j=0; j<MAXHWALEN; j++ )
qstruct->hwadr[j] = *hwadr++;
qstruct->ttl = ARP_TIMEOUT;
qstruct->retries = ARP_MAXRETRY;
qstruct->state = ARP_RESOLVED;
/* All OK */
return (0);
}
}
if(is_subnet(pra,&localmachine) == FALSE){
return (-1);
}
if( localmachine.defgw == pra ) {
if(localmachine.defgw != 0) {
type = ARP_FIXED_IP;
}
}
/* Address was'nt on cache. Need to allocate new one */
ARP_DEBUGOUT("Allocating New ARP Entry..\n\r");
i = arp_alloc(type);
if( i < 0 ) /* No Entries Left? */
return(-1);
/* Fill the fields */
qstruct = &arp_table[i];
qstruct->pradr = pra; /* Fill IP */
for(i=0; i<MAXHWALEN; i++)
qstruct->hwadr[i] = *hwadr++; /* Fill HW address */
qstruct->retries = ARP_MAXRETRY;
qstruct->ttl = ARP_TIMEOUT;
qstruct->state = ARP_RESOLVED;
ARP_DEBUGOUT("ARP Entry Created!..\n\r");
return(1);
}
/** \brief Find an ARP entry given a protocol address
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 01.11.2001
* \param pra - Protocol address (IPv4)
* \param machine - Pointer to configuration of network interface used
* \param type - Type of address allocated if not found. Can be one of the
* following:
* \li #ARP_FIXED_IP
* \li #ARP_TEMP_IP
* \return
* \li 0 - ARP entry not found or not ready yet (waiting for ARP response)
* \li struct arp_entry* - pointer to solved entry of ARP cache table
*
* This function tries to resolve IPv4 address by checking the ARP cache
* table and sending ARP requested if needed.
*/
struct arp_entry* arp_find (LWORD pra, struct netif *machine, UINT8 type)
{
struct arp_entry *qstruct;
INT8 i;
ARP_DEBUGOUT("Trying to find MAC address from ARP Cache\n\r");
/* Is the address in the cache */
for( i=0; i<ARP_TSIZE; i++ ) {
qstruct = &arp_table[i];
if( qstruct->state == ARP_FREE )
continue;
if( qstruct->pradr == pra) {
/* The address is in cache, is it valid? */
ARP_DEBUGOUT("Address In Cache\n\r");
if( qstruct->state < ARP_RESOLVED ) {
ARP_DEBUGOUT("Address in cache but unresolved :(\n\r");
return(0);
}
/* All OK */
return(qstruct);
}
}
/* The address wasn't on the cache. Is it in our Subnet? */
if( is_subnet(pra, machine) ) {
/* Yep, we need to send ARP REQUEST */
ARP_DEBUGOUT("Need to send ARP Request to local network..\n\r");
if( machine->defgw == pra ) {
if(machine->defgw != 0) {
type = ARP_FIXED_IP;
}
}
i = arp_alloc(type);
if( i < 0 ) /* No Entries Left? */
return(0);
/* Send Request after filling the fields */
qstruct = &arp_table[i];
qstruct->pradr = pra; /* Fill IP */
qstruct->hwadr[0] = 0xFF; /* Fill Broadcast IP */
qstruct->hwadr[1] = 0xFF;
qstruct->hwadr[2] = 0xFF;
qstruct->hwadr[3] = 0xFF;
qstruct->hwadr[4] = 0xFF;
qstruct->hwadr[5] = 0xFF;
qstruct->retries = ARP_MAXRETRY;
qstruct->ttl = ARP_RESEND;
arp_send_req( i );
qstruct->state = ARP_PENDING; /* Waiting for Reply */
return(0);
}
/* The Address belongst to the outern world, need to use MAC of */
/* Default Gateway */
ARP_DEBUGOUT("Need to use MAC of Default GW\n\r");
/* Check for Broadcast */
if(machine->defgw == 0) /* It's not specified */
return(0);
for( i=0; i<ARP_TSIZE; i++ ) {
qstruct = &arp_table[i];
if( qstruct->state == ARP_FREE )
continue;
if( qstruct->pradr == machine->defgw ) {
/* The address is in cache, is it valid? */
if( qstruct->state < ARP_RESOLVED ) {
ARP_DEBUGOUT("The Address of Def. GW is not Solved!\n\r");
return(0);
}
/* All OK */
ARP_DEBUGOUT(" >> Default Gateway MAC found!\n\r");
return(qstruct);
}
}
ARP_DEBUGOUT("Need to send ARP Request to default gateway..\n\r");
i = arp_alloc(ARP_FIXED_IP);
if( i < 0 ) /* No Entries Left? */
return(0);
/* Send Request after filling the fields */
qstruct = &arp_table[i];
qstruct->pradr = machine->defgw; /* Fill IP */
qstruct->hwadr[0] = 0xFF; /* Fill Broadcast IP */
qstruct->hwadr[1] = 0xFF;
qstruct->hwadr[2] = 0xFF;
qstruct->hwadr[3] = 0xFF;
qstruct->hwadr[4] = 0xFF;
qstruct->hwadr[5] = 0xFF;
qstruct->retries = ARP_MAXRETRY;
qstruct->ttl = ARP_RESEND;
arp_send_req( i );
qstruct->state = ARP_PENDING; /* Waiting for Reply */
return(0);
}
/** \brief Manage ARP cache periodically
* \ingroup periodic_functions
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 04.11.2001
* \warning
* \li Invoke this function periodically to ensure proper ARP
* cache behaviour
*
* Iterate through ARP cache aging entries. If timed-out entry is found,
* remove it (dynamic address) or update it (static address). This function
* must be called periodically by the system.
*
*/
void arp_manage (void)
{
struct arp_entry *qstruct;
UINT8 i,j;
static UINT8 aenext=0;
/* Check Timer before entering */
if( check_timer(arp_timer) )
return;
init_timer( arp_timer, ARP_MANG_TOUT*TIMERTIC);
/* DEBUGOUT("Managing ARP Cache\n\r"); */
for( i=0; i<ARP_TSIZE; i++ ) {
/* DEBUGOUT("."); */
qstruct = &arp_table[aenext];
j = aenext;
/* Take next entry next time */
aenext++;
if(aenext >= ARP_TSIZE)
aenext = 0;
if( qstruct->state == ARP_FREE )
continue;
/* TODO: How about ARP_RESERVED? */
if( qstruct->ttl > 0 ) /* Aging */
qstruct->ttl --;
if( qstruct->ttl == 0 ) { /* Timed Out? */
/* Do it for temporay entries */
ARP_DEBUGOUT("Found Timed out Entry..\n\r");
if( qstruct->type == ARP_TEMP_IP ) {
/* Release it? */
if( qstruct->state == ARP_RESOLVED ) {
ARP_DEBUGOUT("Releasing ARP Entry..\n\r");
qstruct->state = ARP_FREE;
continue;
}
/* Decrease retries left */
if( qstruct->retries > 0 )
qstruct->retries--;
if( qstruct->retries == 0 ) {
ARP_DEBUGOUT("ARP Replies Used up, releasing entry..\n\r");
qstruct->state = ARP_FREE;
continue;
}
/* So we need to resend ARP request */
ARP_DEBUGOUT("Trying to Resolve dynamic ARP Entry..\n\r");
qstruct->ttl = ARP_RESEND;
arp_send_req( j );
qstruct->state = ARP_PENDING; /* Waiting for Reply */
return;
}
/* Do it for Static Entries */
if( qstruct->type == ARP_FIXED_IP ) {
/* So we need to resend ARP request */
/* Do not try to refresh broadcast */
if(qstruct->pradr == IP_BROADCAST_ADDRESS) {
qstruct->ttl = ARP_TIMEOUT;
continue;
}
ARP_DEBUGOUT("Refreshing Static ARP Entry..\n\r");
if( qstruct->retries > 0 )
qstruct->retries--;
if( qstruct->retries == 0 )
qstruct->state = ARP_PENDING;
else
qstruct->state = ARP_REFRESHING;
qstruct->ttl = ARP_RESEND;
arp_send_req( j );
return;
}
}
}
}
/** \brief Initialize data structures for ARP processing
* \ingroup core_initializer
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 01.11.2001
* \warning
* \li Invoke this function at start-up to properly initialize
* ARP cache subsystem.
*
* Call this function to properly initialize ARP cache table and so that
* ARP allocates and initializes a timer for it's use.
*/
void arp_init (void)
{
struct arp_entry *qstruct;
INT8 i;
ARP_DEBUGOUT("Initializing ARP");
for( i=0; i<ARP_TSIZE; i++ ) {
qstruct = &arp_table[i];
qstruct->state = ARP_FREE;
qstruct->type = ARP_TEMP_IP;
ARP_DEBUGOUT(".");
}
arp_timer = get_timer();
init_timer(arp_timer, ARP_MANG_TOUT*TIMERTIC);
/* set broadcast entry */
qstruct = &arp_table[0];
qstruct->pradr = IP_BROADCAST_ADDRESS;
qstruct->state = ARP_RESOLVED;
qstruct->type = ARP_FIXED_IP;
qstruct->ttl = ARP_TIMEOUT;
qstruct->retries = ARP_MAXRETRY;
for(i=0; i<MAXHWALEN; i++)
qstruct->hwadr[i] = 0xFF;
ARP_DEBUGOUT("\n\r");
}
/** \brief Checks if a given IP address belongs to the subnet of a
given machine
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 05.11.2001
* \param ipadr - IP address under check
* \param machine - pointer to configuration of network parameters used
* \return
* \li #TRUE - ipadr belongs to subnet of given machine
* \li #FALSE - ipadr is NOT a part of subnet of given machine
*
* Based on information supplied in ipadr and machine parameters this
* function performs basic check if IP address is on the same subnet as
* the one defined for the machine.
*
*/
BYTE is_subnet (LWORD ipadr, struct netif* machine)
{
UINT32 ltemp;
ltemp = ipadr & machine->netmask; /* Get Subnet part */
ltemp ^= (machine->localip & machine->netmask); /* Compare to my IP */
if( ltemp )
return(FALSE);
return(TRUE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -