www.pudn.com > uCOSII上实现的tcpip.rar > zarp.c
#include "./include/zarp.h"
#include "./include/zeth.h"
#define ARP_LIVING_TIME 100 /*100 seconds*/
#define ARP_ITEM_NUM 20
STRUCT_BEGIN
typedef struct _arp_header
{
ethaddr_t dest_hwaddr;
ethaddr_t src_hwaddr;
u16_t eth_type;
u16_t hwtype;
u16_t proto;
u16_t _hwlen_protolen;
u16_t opcode;
ethaddr_t shwaddr;
ipaddr_t sipaddr;
ethaddr_t dhwaddr;
ipaddr_t dipaddr;
}arp_header_t;
STRUCT_END
typedef struct _arp_item
{
ethaddr_t hwaddr;
ipaddr_t ipaddr;
u16_t ctime;
}arp_item_t;
static arp_item_t arp_table[ARP_ITEM_NUM];
#define NTOHS
#define HTONS
#define ARPH_HWLEN(hdr) (NTOHS((hdr)->_hwlen_protolen) >> 8)
#define ARPH_PROTOLEN(hdr) (NTOHS((hdr)->_hwlen_protolen) & 0xff)
#define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = HTONS(ARPH_PROTOLEN(hdr) | ((len) << 8))
#define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = HTONS((len) | (ARPH_HWLEN(hdr) << 8))
void add_arp_item(ipaddr_t *ipaddr, ethaddr_t *hwaddr)
{
u8_t i,j,olditem = 0;
u16_t oldtime = 0xffff; /*MAX VALUE*/
for ( i = 0; i < ARP_ITEM_NUM; i++)
{
if ( arp_table[i].ipaddr == *ipaddr)
{
for (j = 0; j < 6; j++)
arp_table[i].hwaddr.addr[j] = hwaddr->addr[j];
arp_table[i].ctime = sys_get_time() / 100;
return;
}
if ( arp_table[i].ctime < oldtime)
{
oldtime = arp_table[i].ctime;
olditem = i;
}
}
for (j = 0; j < 6; j++)
arp_table[olditem].hwaddr.addr[j] = hwaddr->addr[j];
arp_table[olditem].ipaddr = *ipaddr;
arp_table[olditem].ctime = sys_get_time() / 100;
return;
}
void arp_init(void)
{
u8_t i;
for ( i = 0; i < ARP_ITEM_NUM; i++)
{
arp_table[i].ipaddr = IPADDRANY;
arp_table[i].ctime = 0;
}
}
zbuffer_t * arp_arp_input(znetif_t *pnetif, zbuffer_t *pbuffer)
{
arp_header_t *pheader;
u8_t i;
if ( pbuffer->tot_len < sizeof( arp_header_t ) )
{
return NULL;
}
pheader =(arp_header_t *) pbuffer->pdata;
switch ( pheader->opcode )
{
case ARP_REQUEST:
{
if ( pheader->dipaddr == pnetif->ipaddr )
{
pheader->opcode = ARP_REPLY;
pheader->dipaddr = pheader->sipaddr;
pheader->sipaddr = pnetif->ipaddr;
for (i = 0; i < 6; i++)
{
pheader->dhwaddr.addr[i] = pheader->shwaddr.addr[i];
pheader->shwaddr.addr[i] = pnetif->hwaddr.addr[i];
pheader->dest_hwaddr.addr[i] = pheader->dhwaddr.addr[i];
pheader->src_hwaddr.addr[i] = pnetif->hwaddr.addr[i];
}
pheader->hwtype = htons(HWTYPE_ETHERNET);
ARPH_HWLEN_SET(pheader, 6);
pheader->proto = ETHTYPE_IP;
ARPH_PROTOLEN_SET(pheader, sizeof( ipaddr_t));
pheader->eth_type = htons(ETHTYPE_ARP);
return pbuffer;
}
break;
}
case ARP_REPLY:
{
if (pheader->dipaddr == pnetif->ipaddr)
{
add_arp_item(&pheader->sipaddr, &pheader->shwaddr);
return NULL;
}
break;
}
default:
break;
}
return NULL;
}
u8_t arp_lookup(ethaddr_t *hwaddr, ipaddr_t *ipaddr)
{
u8_t i, j;
u16_t ctime;
sys_enter_critical();
for ( i = 0; i < ARP_ITEM_NUM; i++)
{
if ( arp_table[i].ipaddr == *ipaddr)
{
ctime = sys_get_time() / 100;
if ( (ctime - arp_table[i].ctime ) >ARP_LIVING_TIME)
{
arp_table[i].ipaddr = IPADDRANY; /*this must be refresh*/
return -1;
}
for ( j = 0; j < 6; j++)
hwaddr->addr[j] = arp_table[i].hwaddr.addr[j];
sys_exit_critical();
return 0;
}
}
sys_exit_critical();
return -1;
}
u8_t arp_query(ethaddr_t *hwaddr, ipaddr_t *ipaddr)
{
zbuffer_t *pbuffer;
arp_header_t *parpheader;
u8_t i;
pbuffer = zbuffer_new(sizeof(arp_header_t));
if ( pbuffer == NULL)
return -1;
parpheader = (arp_header_t *)pbuffer->pdata;
for(i = 0; i < 6; ++i)
{
parpheader->dhwaddr.addr[i] = 0x00;
parpheader->shwaddr.addr[i] = default_netif.hwaddr.addr[i];
}
for(i = 0; i < 6; ++i)
{
parpheader->dest_hwaddr.addr[i] = 0xff;
parpheader->src_hwaddr.addr[i] = default_netif.hwaddr.addr[i];
}
parpheader->eth_type = ETHTYPE_ARP;
parpheader->dipaddr = *ipaddr;
parpheader->sipaddr = default_netif.ipaddr;
parpheader->hwtype = HWTYPE_ETHERNET;
ARPH_HWLEN_SET(parpheader, 6);
parpheader->proto = ETHTYPE_IP;
parpheader->opcode = ARP_REQUEST;
ARPH_PROTOLEN_SET(parpheader, sizeof(ipaddr_t) );
i = 0;
while( i < 5)
{
default_netif.netif_tx(&default_netif, pbuffer);
sys_delay(20);
i++;
if ( arp_lookup(hwaddr, ipaddr) == 0 )
{
zbuffer_delete(pbuffer);
return 0;
}
}
zbuffer_delete(pbuffer);
return -1;
}