📄 arp.c
字号:
/*********************************************************************************
File: arp.c
Date:
Version: 0.1
Author: Jari Lahti (jari.lahti@violasystems.com)
Description: arp (address resolution protocol) functions
Version Info:
*********************************************************************************/
#include "opentcp.h"
//extern UINT8 RemoteEthernet[]; //Host Ethernet Address
//extern UINT32 IP_RemoteAdd; //Remote IP Address
//extern UINT32 IP_LocalAdd; //My IP address
struct arpentry arptable[ARP_TSIZE];
UINT8 ArpTimer;
UINT8 Process_ARP (struct otcp_ethframe* frame)
{
/* Checks received Ethernet Frame to see if it's an ARP */
/* If valid ARP response, updates ARP cache */
/* If ARP request, sends response */
/* Return values: FALSE = No ARP, TRUE = Was ARP */
/* if ARP detected, upper layer protocols must skip it */
UINT8 temp;
/* Check if ARP packet*/
if( frame->protocol == ARP_ETHCODE )
{
/* Yep, ARP */
NETWORK_RECEIVE_INITIALIZE(frame->bufindex);
/* Is it long enough? */
if( frame->framesize < (2*MAXHWALEN + 2*MAXPRALEN + 2 + 6) )
{
/* Somehow corrupted ARP packet */
DEBUGOUT("Corrupted ARP packet\n\r");
NETWORK_RECEIVE_END();
return(TRUE);
}
/* Ignore next 6 bytes: <HW type>, <Protocol type> */
/* <HW address len> and <Protocol address len> */
for(temp=0; temp<6; temp++)
RECEIVE_NETWORK_B();
DEBUGOUT("Incoming ARP..\n\r");
/* Check if request or response */
if( RECEIVE_NETWORK_B() == 0x00)
{
temp = RECEIVE_NETWORK_B(); //get opcode
//debugout(temp);
if( temp == ARP_REQUEST )
{
DEBUGOUT(" ARP REQUEST Received..\n\r");
ARPSendResponse();
}
else if( temp == ARP_REPLY )
{
DEBUGOUT("ARP Response Received..\n\r");
ARPGetResponse();
}
/* Wasn't request or response or all done, dump it */
}
//NETWORK_RECEIVE_END();
return(TRUE);
}
/* Wasn't ARP, don't touch the packet */
return(FALSE);
}
void ARPSendResponse(void)
{
UINT8 rem_hwadr[MAXHWALEN];
UINT32 rem_ip;
UINT32 ltemp;
UINT8 i;
/* Record Sender's HW address */
for( i=0; i < MAXHWALEN; i++ )
rem_hwadr[i] = RECEIVE_NETWORK_B();
/* Read Sender's IP Address */
rem_ip = 0;
for( i=0; i<MAXPRALEN; i++)
{
rem_ip <<= 8;
rem_ip |= RECEIVE_NETWORK_B();
}
/* Skip Target HW address */
RECEIVE_NETWORK_B();
RECEIVE_NETWORK_B();
RECEIVE_NETWORK_B();
RECEIVE_NETWORK_B();
RECEIVE_NETWORK_B();
RECEIVE_NETWORK_B();
/* Is The Packet For Us? */
ltemp = 0;
for( i=0; i<MAXPRALEN; i++)
{
ltemp <<= 8;
ltemp |= RECEIVE_NETWORK_B();
}
if( ltemp != localmachine.localip )
{
return; /* No */
}
DEBUGOUT("Preparing for ARP Reply\n\r");
/* OK. Now send reply */
NETWORK_SEND_INITIALIZE(TXBUF_ENET);
/* Add datalink (Ethernet addresses) information */
for( i=0; i<MAXHWALEN; i++)
{
otcp_txframe.destination[i] = rem_hwadr[i];
}
for( i=0; i<MAXHWALEN; i++)
{
otcp_txframe.source[i] = localmachine.localHW[i];
}
otcp_txframe.protocol = PROTOCOL_ARP;
NETWORK_ADD_DATALINK(&otcp_txframe);
/* PUT ARP Data */
SEND_NETWORK_B( (BYTE)(AR_HARDWARE>>8) ); /* Hardware Type */
SEND_NETWORK_B( (BYTE)AR_HARDWARE );
SEND_NETWORK_B(0x08); /* Protocol Type */
SEND_NETWORK_B(0x00);
SEND_NETWORK_B(MAXHWALEN); /* HW Adr Len */
SEND_NETWORK_B(MAXPRALEN); /* Protocol Adr. Len*/
SEND_NETWORK_B( 0x00 ); /* ARP Opcode */
SEND_NETWORK_B( 0x02 );
SEND_NETWORK_B((UINT8)(localmachine.localHW[0])); /* Address fields */
SEND_NETWORK_B((UINT8)(localmachine.localHW[1]));
SEND_NETWORK_B((UINT8)(localmachine.localHW[2]));
SEND_NETWORK_B((UINT8)(localmachine.localHW[3]));
SEND_NETWORK_B((UINT8)(localmachine.localHW[4]));
SEND_NETWORK_B((UINT8)(localmachine.localHW[5]));
SEND_NETWORK_B((UINT8)(localmachine.localip>>24));
SEND_NETWORK_B((UINT8)(localmachine.localip>>16));
SEND_NETWORK_B((UINT8)(localmachine.localip>>8));
SEND_NETWORK_B((UINT8)(localmachine.localip));
SEND_NETWORK_B((UINT8)rem_hwadr[0]);
SEND_NETWORK_B((UINT8)rem_hwadr[1]);
SEND_NETWORK_B((UINT8)rem_hwadr[2]);
SEND_NETWORK_B((UINT8)rem_hwadr[3]);
SEND_NETWORK_B((UINT8)rem_hwadr[4]);
SEND_NETWORK_B((UINT8)rem_hwadr[5]);
SEND_NETWORK_B((UINT8)(rem_ip>>24));
SEND_NETWORK_B((UINT8)(rem_ip>>16));
SEND_NETWORK_B((UINT8)(rem_ip>>8));
SEND_NETWORK_B((UINT8)rem_ip);
NETWORK_COMPLETE_SEND(0x0040); /* Send the packet */
DEBUGOUT("ARP Reply Sent..\n\r");
/* Add the Sender's info to cache because we can */
arpadd(rem_ip, &otcp_txframe.destination[0], ARP_TEMP_IP);
return;
}
void ARPGetResponse(void)
{
struct arpentry *qstruct;
UINT8 rem_hwadr[MAXHWALEN];
UINT32 rem_ip;
UINT32 ltemp;
UINT8 i;
UINT8 j;
/* Read Sender's HW address */
for( i=0; i < MAXHWALEN; i++ )
rem_hwadr[i-1] = RECEIVE_NETWORK_B();
/* Read Sender's IP Address */
rem_ip = 0;
for( i=0; i<MAXPRALEN; i++)
{
rem_ip <<= 8;
rem_ip |= RECEIVE_NETWORK_B();
}
/* Skip our HW Address */
for(i=0; i<MAXHWALEN; i++)
RECEIVE_NETWORK_B();
/* Is The Packet For Us? */
ltemp = 0;
for( i=0; i<MAXPRALEN; i++)
{
ltemp <<= 8;
ltemp |= RECEIVE_NETWORK_B();
}
if( ltemp != localmachine.localip )
return; /* No */
DEBUGOUT("Now entering to process ARP Reply..\n\r");
/* Are we waiting for that reply? */
for( i=1; i<ARP_TSIZE; i++ )
{
qstruct = &arptable[i];
if( qstruct->state == ARP_FREE )
continue;
if( qstruct->state == ARP_RESERVED )
continue;
if( rem_ip == qstruct->pradr )
{
/* We are caching that IP, refresh it */
DEBUGOUT("Refreshing ARP cache from Reply..\n\r");
for( j=0; j<MAXHWALEN; j++ )
qstruct->hwadr[j] = rem_hwadr[j];
qstruct->ttl = ARP_TIMEOUT;
qstruct->retries = ARP_MAXRETRY;
qstruct->state = ARP_RESOLVED;
/* Done */
break;
}
}
}
/******************************************************************************
Function: arpsendreq
Parameters: UINT8 entry - Entry to ARP table
Return val: none
Date: 01.11.2001
Desc: Send ARP request of given entry
*******************************************************************************/
void arpsendreq (UINT8 entry)
{
struct arpentry *qstruct;
UINT8 i;
qstruct = &arptable[entry];
NETWORK_SEND_INITIALIZE(TXBUF_ENET);
/* Add datalink (Ethernet addresses) information */
for( i=0; i<MAXHWALEN; i++)
{
otcp_txframe.destination[i] = 0xFF;
}
for( i=0; i<MAXHWALEN; i++)
{
otcp_txframe.source[i] = localmachine.localHW[i];
}
otcp_txframe.protocol = PROTOCOL_ARP;
NETWORK_ADD_DATALINK(&otcp_txframe);
/* PUT ARP Data */
SEND_NETWORK_B( (BYTE) (AR_HARDWARE>>8) ); /* Hardware Type */
SEND_NETWORK_B( (BYTE) AR_HARDWARE );
SEND_NETWORK_B(0x08); /* Protocol Type */
SEND_NETWORK_B(0x00);
SEND_NETWORK_B(MAXHWALEN); /* HW Adr Len */
SEND_NETWORK_B(MAXPRALEN); /* Protocol Adr. Len*/
SEND_NETWORK_B( (BYTE)(ARP_REQUEST>>8)); /* ARP Opcode */
SEND_NETWORK_B( (BYTE) ARP_REQUEST );
SEND_NETWORK_B((UINT8)localmachine.localHW[0]); /* Address fields */
SEND_NETWORK_B((UINT8)localmachine.localHW[1]);
SEND_NETWORK_B((UINT8)localmachine.localHW[2]);
SEND_NETWORK_B((UINT8)localmachine.localHW[3]);
SEND_NETWORK_B((UINT8)localmachine.localHW[4]);
SEND_NETWORK_B((UINT8)localmachine.localHW[5]);
SEND_NETWORK_B((UINT8)(localmachine.localip>>24));
SEND_NETWORK_B((UINT8)(localmachine.localip>>16));
SEND_NETWORK_B((UINT8)(localmachine.localip>>8));
SEND_NETWORK_B((UINT8)localmachine.localip);
SEND_NETWORK_B((UINT8)0xFF);
SEND_NETWORK_B((UINT8)0xFF);
SEND_NETWORK_B((UINT8)0xFF);
SEND_NETWORK_B((UINT8)0xFF);
SEND_NETWORK_B((UINT8)0xFF);
SEND_NETWORK_B((UINT8)0xFF);
SEND_NETWORK_B((UINT8)(qstruct->pradr>>24));
SEND_NETWORK_B((UINT8)(qstruct->pradr>>16));
SEND_NETWORK_B((UINT8)(qstruct->pradr>>8));
SEND_NETWORK_B((UINT8)qstruct->pradr);
/* Packet assembled now, just send it ... */
NETWORK_COMPLETE_SEND(0x0040); /* Min packet size */
DEBUGOUT("ARP Request Sent\n\r");
}
/******************************************************************************
Function: arpalloc
Parameters: UINT8 type - type of ARP entry
Return val: positive - pointer to allocated arp entry
(-1) - entry not found (entries used up)
Date: 01.11.2001
Desc: Allocate arp entry for given type. Chooses the unused entry if
one exists. Otherwice deletes entries in round-robin fashion.
Static entries are not deleted/reallocated.
*******************************************************************************/
INT8 arpalloc (UINT8 type)
{
struct arpentry *qstruct;
INT8 i;
static UINT8 aenext = 1; /* Cache Manager */
INT16 found;
/* Try to find free entry */
found = -1;
for( i=0; i<ARP_TSIZE; i++ )
{
if( arptable[i].state == ARP_FREE )
{
found = i;
break;
}
}
if(found != (-1) )
{
qstruct = &arptable[found];
qstruct->state = ARP_RESERVED;
qstruct->type = type;
return( (UINT8)found );
}
/* if no success, try ro find first temporary entry */
/* on round-robin fashion */
for( i=0; i<ARP_TSIZE; i++ )
{
if( arptable[aenext].type == ARP_TEMP_IP)
{
found = aenext;
break;
}
/* Move to next entry */
aenext = (aenext + 1);
if( aenext >= ARP_TSIZE )
aenext = 1;
}
/* Was there free or temporary entries? */
if( found == (-1) )
return(-1);
/* Next time start from next entry */
aenext = (aenext + 1);
if( aenext >= ARP_TSIZE )
aenext = 1;
qstruct = &arptable[found];
/* Set ARP initial parameters */
qstruct->state = ARP_RESERVED;
qstruct->type = type;
/* Was return(i)!!! <-wrong!! */
return((UINT8)found);
}
/******************************************************************************
Function: arpadd
Parameters: UINT32 pra - protocol address
UINT8* hwadr - Ethernet MAC address (6 bytes)
UINT8 type - type of address allocated if not found
Return val: INT8 (-1) - Not succesful (no ARP entries)
0 - Address already in cache, refreshed
1 - New entry created
Date: 10.7.2002
Desc: Add given IP address and MAC address to ARP cache
*******************************************************************************/
INT8 arpadd (UINT32 pra, UINT8* hwadr, UINT8 type)
{
struct arpentry *qstruct;
INT8 i;
INT8 j;
for( i=0; i<ARP_TSIZE; i++ )
{
qstruct = &arptable[i];
if( qstruct->state == ARP_FREE )
continue;
if( (qstruct->pradr == pra) && (pra != IP_BROADCAST_ADDRESS))
{
/* The address is in cache, refresh it */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -