📄 arp.c
字号:
if (buf_ptr->mem_flags & NET_BCAST)
{
memcpy(mac_dest, NET_Ether_Broadaddr, DADDLEN);
return (NU_SUCCESS);
}
PUT32(temp, 0, ip_dest->sck_addr);
if (buf_ptr->mem_flags & NET_MCAST)
{
NET_MAP_IP_TO_ETHER_MULTI(temp, mac_dest);
return (NU_SUCCESS);
}
/* Check the ARP cache for the destination. If found, return. */
if ( (a_entry = ARP_Find_Entry(ip_dest)) != NU_NULL)
{
memcpy(mac_dest, a_entry->arp_mac_addr, DADDLEN);
return (NU_SUCCESS);
}
if ((stat = NU_Allocate_Memory(&System_Memory, (VOID **)&ar_entry,
sizeof(*ar_entry),
(UNSIGNED)NU_NO_SUSPEND)) != NU_SUCCESS)
{
return (stat);
}
ar_entry->ar_id = ARP_Res_Count++;
ar_entry->ar_device = int_face;
ar_entry->ar_dest = ip_dest->sck_addr;
ar_entry->ar_send_count = 0;
ar_entry->ar_task = 0; /* ar_task used only for RARP. */
ar_entry->ar_buf_ptr = buf_ptr;
ar_entry->ar_pkt_type = ARPREQ;
/* If there is already an ARP entry for this host then we do not want to
set an event, ie. don't send an ARP if we have already done so. */
for (current_ar_entry = ARP_Res_List.ar_head;
current_ar_entry != NU_NULL;
current_ar_entry = current_ar_entry->ar_next)
{
if (TLS_Comparen(&ar_entry->ar_dest, ¤t_ar_entry->ar_dest, 4))
break;
}
/* Order is not important. Simply add the new entry to the front of the
list. */
DLL_Enqueue((tqe_t *)&ARP_Res_List, (tqe_t *)ar_entry);
/* Set the event if one was not found. */
if (!current_ar_entry)
{
TLS_Put_Event (ARPRESOLVE, (UNSIGNED)ar_entry->ar_id);
}
return(NU_UNRESOLVED_ADDR);
} /* end ARP_Resolve */
/*************************************************************************
*
* FUNCTION
*
* ARP_Find_Entry
*
* DESCRIPTION
*
* This function searches the ARP cache for a matching entry.
*
* INPUTS
*
* *dest IP address for which an ethernet
* address is desired.
*
* OUTPUTS
*
* *ARP_ENTRY A pointer to an entry in the ARP cache. NULL
* on failure.
*
*************************************************************************/
ARP_ENTRY *ARP_Find_Entry(SCK_SOCKADDR_IP *dest)
{
INT i;
ARP_ENTRY *a_entry = NU_NULL;
/* Search the cache for the target IP number. */
for (i = 0; i < ARP_CACHE_LENGTH; i++)
{
if ( dest->sck_addr == ARP_Cache[i].arp_ip_addr)
{
/* We found the entry. */
a_entry = &ARP_Cache[i];
break;
}
}
/* If an entry was found, it has not timed out or is permanent,
and the entry is valid, the return a pointer to this entry. Else return NULL
*/
if ( a_entry && ((INT32_CMP((a_entry->arp_time + CACHETO),
NU_Retrieve_Clock()) > 0)
|| (a_entry->arp_flags & ARP_PERMANENT))
&& (a_entry->arp_flags & ARP_UP) )
return (a_entry);
else
return NU_NULL;
} /* ARP_Find_Entry */
/*************************************************************************
*
* FUNCTION
*
* ARP_Request
*
* DESCRIPTION
*
* Send an ARP request.
*
* INPUTS
*
* *device Pointer to the device.
* *tip The target IP number
* *thardware The target hardware address.
* protocol_type Either EARP or ERARP.
* arp_type Either ARPREQ or RARPQ.
*
* OUTPUTS
*
* NU_SUCCESS If success.
* -1 If error.
*
*************************************************************************/
STATUS ARP_Request(DV_DEVICE_ENTRY *device, UINT32 *tip, UINT8 *thardware,
UINT16 protocol_type, INT16 arp_type)
{
NET_BUFFER *buf_ptr;
ARP_MAC_HEADER mh;
STATUS stat;
/* Build the ARP request packet. The target hardware address is unknown at
this point, so pass in a string of NULL characters as the target hardware
address.
*/
if ((buf_ptr = ARP_Build_Pkt(device, *tip, thardware, arp_type)) == NU_NULL)
{
return -1;
}
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 this is not an IP datagram and
it should not try to resolve a hardware address. */
memcpy (mh.ar_mac.ar_mac_ether.dest, NET_Ether_Broadaddr, DADDLEN);
mh.ar_mac.ar_mac_ether.type = protocol_type;
mh.ar_family = SK_FAM_UNSPEC;
mh.ar_len = sizeof(mh);
/* Send the ARP Packet. */
stat = (*device->dev_output)(buf_ptr, device, (SCK_SOCKADDR_IP *)&mh, NU_NULL);
/* if the packet is not sent then free up the buffer space */
if (stat != NU_SUCCESS)
MEM_Buffer_Enqueue(&MEM_Buffer_Freelist, (NET_BUFFER *)buf_ptr);
return (NU_SUCCESS);
} /* ARP_Request */
/*************************************************************************
*
* FUNCTION
*
* ARP_Cache_Update
*
* DESCRIPTION
*
* Add an entry to the ARP cache.
*
* INPUTS
*
* ipn
* *hrdn
* flags
*
* OUTPUTS
*
* INT Index of entry made in ARP cache.
* -1 Entry was not found.
*
*************************************************************************/
INT ARP_Cache_Update(UINT32 ipn, UINT8 *hrdn, INT flags)
{
INT16 i, found = -1;
INT32 timer;
/*
* linear search to see if we already have this entry
*/
for (i=0; i < ARP_CACHE_LENGTH; i++)
if (ipn == ARP_Cache[i].arp_ip_addr)
{
found = i;
break;
}
/*
* if that IP number is not already here, take the oldest
* entry.
* If it is already here, update the info and reset the timer.
* These were pre-initialized to 0, so if any are blank, they
* will be
* taken first because they are faked to be oldest.
*/
if (found<0)
{
timer = ARP_Cache[0].arp_time;
found = 0;
for (i=1; i < ARP_CACHE_LENGTH; i++)
{
/* If this entry has timed-out and is not permanent then
reuse it. */
if ( (INT32_CMP(ARP_Cache[i].arp_time, timer) < 0) &&
( (ARP_Cache[i].arp_flags & ARP_PERMANENT) == 0) )
{ /* exclude gateways */
found = i;
timer = ARP_Cache[i].arp_time;
} /* end if ARP_Cache check */
} /* end for ARP_CACHE_LENGTH*/
} /* end if found < 0 */
/*
* do the update to the cache
*/
memcpy (ARP_Cache[found].arp_mac_addr, hrdn, DADDLEN);
ARP_Cache[found].arp_ip_addr = ipn;
ARP_Cache[found].arp_time = NU_Retrieve_Clock();
ARP_Cache[found].arp_flags = (ARP_UP | flags);
return (found);
} /* ARP_Cache_Update */
/*************************************************************************
*
* FUNCTION
*
* ARP_Event
*
* DESCRIPTION
*
* Process an ARP timer event.
*
* INPUTS
*
* id
*
* OUTPUTS
*
* None.
*
*************************************************************************/
VOID ARP_Event(UINT16 id)
{
ARP_RESOLVE_ENTRY *ar_entry;
UINT32 arp_host_ip;
for(ar_entry = ARP_Res_List.ar_head;
ar_entry != NU_NULL;
ar_entry = ar_entry->ar_next)
{
if (ar_entry->ar_id == id)
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -