⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m_arp.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * FILENAME: et_arp.c
 *
 * Copyright  2000 By InterNiche Technologies Inc. All rights reserved
 *
 * Ethernet (and similar media) arp code.
 * 
 * MODULE: INET
 *
 * ROUTINES: et_send(), send_arp(), 
 * ROUTINES: find_oldest_arp(), make_arp_entry(), arpReply(), arprcv(), 
 * ROUTINES: send_via_arp(), arp_stats(), 
 *
 * PORTABLE: yes
 */

#include "ipport.h"
#include "q.h"
#include "netbuf.h"
#include "net.h"
#include "ether.h"
#include "arp.h"
#include "ip.h"

#include "minip.h"      /* (yaxon add) */


struct arptabent *   arpcache;   /* last ARP entry used */
static u_long cachetime;         /* time we created arpcache entry */
int   arp_ageout  =  600;        /* APR table refresh age, in seconds */

/* arp stats - In addition to MIB-2 */
unsigned    arpReqsIn = 0;    /* requests received */
unsigned    arpReqsOut = 0;   /* requests sent */
unsigned    arpRepsIn = 0;    /* replys received */
unsigned    arpRepsOut = 0;   /* replys sent */

struct arptabent  arp_table[MAXARPS];     /* the actual table */


/* FUNCTION: et_send()
 *
 * et_send() - fill in outgoing ethernet-bound packet's ethernet 
 * header and send it. Header info is in arp entry passed and MIB 
 * info. 
 * 
 * PARAM1: PACKET pkt
 * PARAM2: struct arptabent * tp
 *
 * RETURNS: Returns 0 if OK, or the usual ENP_ errors 
 */

int
et_send(PACKET pkt, struct arptabent * tp)
{
   struct ethhdr *   ethhdr;
   IFMIB etif = m_netp->n_mib;    /* mib info for this ethernet interface */

   tp->lasttime = cticks;
   pkt->nb_prot -= ETHHDR_SIZE;  /* prepare for prepending ethernet header */
   pkt->nb_plen += ETHHDR_SIZE;
   ethhdr = (struct ethhdr*)(pkt->nb_prot + ETHHDR_BIAS);   /* prepare to prepend ethernet header */

   if ((char*)ethhdr < pkt->nb_buff)   /* sanity check pointer */
      panic("et_send: prepend");

   MEMCPY(ethhdr->e_dst, tp->t_phy_addr, 6);    /* copy dest MAC address into packet */
   MEMCPY(ethhdr->e_src, etif->ifPhysAddress, 6);  /* MAC src */
   ethhdr->e_type = ARPIP;    /* MAC prototcol  type, 0800 (IP) in net-endian */

#ifdef NP_DEBUG
   if(m_netp->pkt_send == NULL)
   {
      panic("et_send")
   }
#endif
   return(m_netp->pkt_send(pkt));   /* send packet to media */
}

#define  arpsize  (ETHHDR_SIZE   +  sizeof(struct  arp_hdr))

/* FUNCTION: send_arp()
 *
 * send_arp() - send an arp for outgoing ethernet packet pkt, which 
 * has no current arp table entry. This means making a partial entry 
 * and queuing the packet at the entry. Packet will be send when 
 * target IP host reply to the ARP we send herein. If no reply, 
 * timeout will eventually free packet. 
 *
 * 
 * PARAM1: PACKET pkt
 * PARAM2: ip_addr dest_ip
 *
 * RETURNS: Returns 0 if OK, or the usual ENP_ errors 
 */

int
send_arp(PACKET pkt, ip_addr dest_ip)
{
   struct arptabent *   oldest;
   struct ethhdr *   ethhdr;
   struct arp_hdr *  arphdr;
   IFMIB etif = m_netp->n_mib;    /* mib info for this ethernet interface */
   PACKET arppkt;

   if(dest_ip == 0xFFFFFFFF)     /* broadcast? */
   {
      /* get unused or oldest entry in table */
      oldest = make_arp_entry(dest_ip, m_netp);

      /* set MAC destination to ethernet broadcast (all FFs) */
      MEMSET(oldest->t_phy_addr, 0xFF, 6);
      return(et_send(pkt, oldest));
   }

   /* not broadcasting, so get a packet for an ARP request */
   LOCK_NET_RESOURCE(FREEQ_RESID); 
   arppkt = pk_alloc(arpsize);
   if (!arppkt)
   {
      pk_free(pkt);
      UNLOCK_NET_RESOURCE(FREEQ_RESID);
      return ENP_RESOURCE;
   }
   UNLOCK_NET_RESOURCE(FREEQ_RESID);
   arppkt->nb_prot = arppkt->nb_buff;
   arppkt->nb_plen = arpsize;
   arppkt->net = m_netp;

   /* get unused or oldest entry in table */
   oldest = make_arp_entry(dest_ip, m_netp);

   oldest->pending = pkt;           /* packet is "pended", not pk_free()d */

   /* build arp request packet */
   ethhdr = (struct ethhdr *)(arppkt->nb_buff + ETHHDR_BIAS);     /* ethernet header at start of buffer */
   arphdr = (struct arp_hdr *)(arppkt->nb_buff + ETHHDR_SIZE); /* arp header follows */
   arphdr->ar_hd = ARPHW;     /* net endian arp hardware type (ethernet) */
   arphdr->ar_pro = ARPIP;
   arphdr->ar_hln = 6;
   arphdr->ar_pln = 4;
   arphdr->ar_op = ARREQ;
   arphdr->ar_tpa = dest_ip;        /* target's IP address */
   arphdr->ar_spa = m_netp->n_ipaddr;   /* my IP address */
   MEMCPY(arphdr->ar_sha, etif->ifPhysAddress, 6);
   MEMSET(&(ethhdr->e_dst[0]), 0xFF, 6);     /* destination to broadcast (all FFs) */
   MEMCPY(ethhdr->e_src, etif->ifPhysAddress, 6);
   ethhdr->e_type = ET_ARP;   /* 0x0806 - ARP type on ethernet */

#ifdef NO_CC_PACKING    /* move ARP fields to proper network boundaries */
   {
      struct arp_wire * arwp  =  (struct  arp_wire *)arphdr;
      MEMMOVE(&arwp->data[AR_SHA], arphdr->ar_sha, 6);
      MEMMOVE(&arwp->data[AR_SPA], &arphdr->ar_spa, 4);
      MEMMOVE(&arwp->data[AR_THA], arphdr->ar_tha, 6);
      MEMMOVE(&arwp->data[AR_TPA], &arphdr->ar_tpa, 4);
   }
#endif   /* NO_CC_PACKING */

#ifdef NP_DEBUG
   if(m_netp->pkt_send == NULL)
   {
      panic("send_arp")
   }
#endif
   /* send arp request */
   m_netp->pkt_send(arppkt);  /* driver should free arppkt later */

   arpReqsOut++;
   return ENP_SEND_PENDING;
}


/* FUNCTION: find_oldest_arp()
 * 
 * Return LRU or first free entry in arp table - preperatory to 
 * making a new arp entry out of it. IP address passed is that of new 
 * entry so we can recycle previous entry for that IP if it exists. 
 *
 * PARAM1: ip_addr dest_ip
 *
 * RETURNS: LRU or first free entry in arp table
 */

struct arptabent * 
find_oldest_arp(ip_addr dest_ip)
{
   struct arptabent *   tp;
   struct arptabent *   oldest;

   /* find lru (or free) entry,  */
   oldest = arp_table;
   for (tp = arp_table; tp <= &arp_table[MAXARPS-1]; tp++)
   {
      if (tp->t_pro_addr == dest_ip)   /* ip addr already has entry */
      {
         tp->lasttime = cticks;
         return(tp);
      }
      if (!tp->t_pro_addr) /* entry is unused */
      {
         oldest = tp;   /* use free entry as "oldest" */
         /* need to keep scanning in case dest_ip already has an entry */
      }
      else if(oldest->lasttime > tp->lasttime)
      {
         oldest = tp;   /* found an older (LRU) entry */
      }
   }
   return oldest;
}

/* FUNCTION: make_arp_entry()
 *
 * make_arp_entry(ip_addr, NET) - find the first unused (or the 
 * oldest) arp table entry, and make a new entry for to prepare it 
 * for an arp reply. If the IP address already has an entry, the 
 * entry is returned with only the timestap modified. 
 *
 * PARAM1: ip_addr dest_ip
 * PARAM2: NET net
 *
 * RETURNS: Returns pointer to arp table entry selected. 
 */

struct arptabent *   
make_arp_entry(ip_addr dest_ip, NET net)
{
   struct arptabent *   oldest;

   /* find usable (or existing) ARP table entry */
   oldest = find_oldest_arp(dest_ip);

   /* partially fill in arp entry */
   oldest->createtime = cticks;

   /* If recycling entry, don't leak packets which may be stuck here */
   if ((oldest->pending) &&  
       (oldest->t_pro_addr != dest_ip)) /* don't clear pending if recycling */
   {
      LOCK_NET_RESOURCE(FREEQ_RESID);
      pk_free(oldest->pending);
      UNLOCK_NET_RESOURCE(FREEQ_RESID);
      oldest->pending = NULL;
   }

   oldest->t_pro_addr = dest_ip;
   oldest->net = net;
   MEMSET(oldest->t_phy_addr, '\0', 6);   /* clear mac address */
   return oldest;
}



/* FUNCTION: arpReply()
 *
 * arpReply() - do arp reply to the passed arp request packet. packet 
 * must be freed (or reused) herein. 
 *
 * 
 * PARAM1: PACKET pkt
 *
 * RETURNS: void
 */

void
arpReply(PACKET pkt)
{
   PACKET outpkt;
   struct arp_hdr *  in;
   struct arp_hdr *  out;
   struct ethhdr *   ethout, *   ethin;

   LOCK_NET_RESOURCE(FREEQ_RESID);
   outpkt = pk_alloc(sizeof(struct arp_hdr));
   UNLOCK_NET_RESOURCE(FREEQ_RESID);
   if (!outpkt)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -