📄 arp.c
字号:
{
#if (INCLUDE_RARP == NU_TRUE)
/* Is this a RARP response to my RARP request. */
if((my_ip == NU_NULL) &&
(GET16(a_pkt, ARP_OP_OFFSET) == RARPR) &&
EQ_STRING(a_pkt, ARP_THA_OFFSET, device->dev_mac_addr, DADDLEN))
{
/* Search the ARP_Res_List for a match. */
for(ar_entry = ARP_Res_List.ar_head;
ar_entry != NU_NULL;
ar_entry = ar_entry->ar_next)
{
/* A match is found when we find an entry for a RARP request. */
if ( (ar_entry->ar_pkt_type == RARPQ) &&
(ar_entry->ar_device == device) )
break;
}
/* Was a match found. */
if (ar_entry)
{
/* Copy the newly discovered IP address. */
device->dev_addr.dev_ip_addr = target_ip_addr;
/* Clear the timer event. */
UTL_Timerunset(RARP_REQUEST, ar_entry->ar_id, 1);
/* Resume the task. */
NU_Resume_Task(ar_entry->ar_task);
}
}
#endif /* INCLUDE_RARP == NU_TRUE */
/* This packet was destined for someone else, so return. */
return (NU_SUCCESS);
}
GET_STRING(a_pkt, ARP_SHA_OFFSET, sha, DADDLEN);
/* If the source IP address is the same as mine then someone is trying to
use my IP address.
*/
if ( source_ip_addr == my_ip )
{
NERRS_Log_Error (NERR_RECOVERABLE, __FILE__, __LINE__);
}
/*
* check packet's desired IP address translation to see if it wants
* me to answer.
*/
if ( (GET16(a_pkt, ARP_OP_OFFSET) == ARPREQ) &&
(target_ip_addr == my_ip) )
{
/* keep the address for me */
ARP_Cache_Update (source_ip_addr, sha, NU_NULL);
/* Check to see if there are any packets pending the resolution of
this address. */
ARP_Check_Events(a_pkt);
/* Send a reply to the request. */
ARP_Reply(sha, source_ip_addr, device);
return (NU_SUCCESS);
}
/*
* Check for a reply that I probably asked for.
*/
if ((target_ip_addr == my_ip)
&& (GET16(a_pkt, ARP_OP_OFFSET) == ARPREP)
&& (GET16(a_pkt, ARP_HRD_OFFSET) == HARDWARE_TYPE)
&& (GET8(a_pkt, ARP_HLN_OFFSET) == DADDLEN)
&& (GET8(a_pkt, ARP_PLN_OFFSET) == 4))
{
ARP_Cache_Update (source_ip_addr, sha, NU_NULL);
/* Check to see if there are any packets pending the resolution of
this address. */
ARP_Check_Events(a_pkt);
return (NU_SUCCESS);
} /* end if this is a reply that we asked for */
return (NU_NO_ACTION);
} /* ARP_Interpret */
/**************************************************************************
*
* FUNCTION
*
* ARP_Check_Events
*
* DESCRIPTION
*
* This function checks to see if there are any packets pendind the
* resolution of a hardware address that was provided in either a
* recevied ARP response or an ARP request. If there is a pending
* packet, it will be transmitted.
*
* INPUTS
*
* *a_pkt Pointer to a received ARP packet.
*
* OUTPUTS
*
* No, oututs, but if a pending packet is found that packet is
* transmitted.
*
**************************************************************************/
VOID ARP_Check_Events(ARP_LAYER *a_pkt)
{
ARP_RESOLVE_ENTRY *ar_entry;
ARP_MAC_HEADER mh;
#if (INCLUDE_TCP == NU_TRUE)
TCP_PORT *prt;
#endif
STATUS status;
do
{
/* Are there any IP packets pending the resolution of a MAC address? If
so check to see if this ARP response resolves any of those.
*/
for (ar_entry = ARP_Res_List.ar_head;
ar_entry != NU_NULL;
ar_entry = ar_entry->ar_next)
{
if (ar_entry->ar_dest == GET32(a_pkt, ARP_SPA_OFFSET))
break;
}
/* Was a match found? */
if (ar_entry)
{
/* Clear the timer event. */
UTL_Timerunset(ARPRESOLVE, (UNSIGNED)ar_entry->ar_id, 1);
/* Send the pending IP packet. The IP packet has already been
formed. The route has previously been determined. All we have
to do here is build the Ethernet Header and send it.
*/
UTL_Zero(&mh, sizeof(mh));
/* This is a psuedo MAC hedaer that is passed to the MAC layer send function.
The MAC layer information that is know is filled in. A family of
SK_FAM_UNSPEC lets the MAC layer know that it should not try to
resolve a hardware address. */
GET_STRING(a_pkt, ARP_SHA_OFFSET, mh.ar_mac.ar_mac_ether.dest,
DADDLEN);
mh.ar_mac.ar_mac_ether.type = EIP;
mh.ar_family = SK_FAM_UNSPEC;
mh.ar_len = sizeof(mh);
/* Send the packet. */
status = (*ar_entry->ar_device->dev_output)(ar_entry->ar_buf_ptr,
ar_entry->ar_device,
(SCK_SOCKADDR_IP *)&mh, NU_NULL);
/* If the packet was not sent successfully then it needs to be
deallocated, else it will get lost. */
if(status != NU_SUCCESS)
{
/* If this buffer conatains a TCP packet, then it is possible
it will need to be directed to the freelist. This will be
the case if the TCP port was closed while the ARP was
doing it's thing. */
#if (INCLUDE_TCP == NU_TRUE)
if ( ar_entry->ar_buf_ptr->mem_tcp_data_len &&
(ar_entry->ar_buf_ptr->mem_port_index >= 0) )
{
/* It's possible the port closed during ARP, If so
deallocate the buffer to the free list.
*/
prt = TCP_Ports[(UINT16)ar_entry->ar_buf_ptr->mem_port_index];
if ((prt->state == SCLOSED) || (prt->state == STWAIT))
{
ar_entry->ar_buf_ptr->mem_dlist = &MEM_Buffer_Freelist;
}
}
#endif
/* The packet was not sent. Put it on to the dlist for this
buffer so that we can try to retransmit it again. */
MEM_One_Buffer_Chain_Free (ar_entry->ar_buf_ptr,
ar_entry->ar_buf_ptr->mem_dlist);
}
/* Deallocate this entry. */
DLL_Remove((tqe_t *)&ARP_Res_List, (tqe_t *)ar_entry);
NU_Deallocate_Memory(ar_entry);
}
} while (ar_entry);
} /* ARP_Check_Events */
/*************************************************************************
*
* FUNCTION
*
* ARP_Init
*
* DESCRIPTION
*
* Initialize the ARP module.
*
* INPUTS
*
* None
*
* OUTPUTS
*
* None
*
*************************************************************************/
VOID ARP_Init (VOID)
{
/* Clear the ARP Cache */
UTL_Zero(ARP_Cache, sizeof(ARP_ENTRY) * ARP_CACHE_LENGTH);
/* The resolve list is initially empty. */
ARP_Res_List.ar_head = NU_NULL;
ARP_Res_List.ar_tail = NU_NULL;
ARP_Res_Count = 0;
} /* ARP_Init */
/*************************************************************************
*
* FUNCTION
*
* ARP_Resolve
*
* DESCRIPTION
*
* This function attempts to resolve an ethernet hardware address.
* If unable to find an entry in the ARP cache it will queue the
* packet, an IP packet, that needs to be sent. An ARP event will
* be created to send an ARP request. The IP packet is transmitted
* once the address is resolved.
*
* INPUTS
*
* *int_face Pointer to the device to on.
* *ip_dest Pointer to the IP destination.
* *mac_dest Pointer to the hardware address.
* This will will be filled in if found.
* *buf_ptr Pointer to a buffer containing an IP
* packet.
*
* OUTPUTS
*
* NU_SUCCESS Indicates successful operation.
* NU_UNRESOLVED_ADDR Indicates the address is unresolved.
* The IP is queued pending resolution.
*
*************************************************************************/
STATUS ARP_Resolve(DV_DEVICE_ENTRY *int_face, SCK_SOCKADDR_IP *ip_dest,
UINT8 *mac_dest, NET_BUFFER *buf_ptr)
{
ARP_RESOLVE_ENTRY *ar_entry, *current_ar_entry;
STATUS stat;
ARP_ENTRY *a_entry;
UINT8 temp[4];
/* If this is a broadcast packet then simply return the ethernet broadcast
address. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -