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

📄 arp.c

📁 用于嵌入式系统的TCP/IP协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
/***********************************************************************//*                                                                     *//*   Module:  tcp_ip/arp.c                                             *//*   Release: 2001.3                                                   *//*   Version: 2001.2                                                   *//*   Purpose: Implmentation of ARP and RARP protocols                  *//*                                                                     *//*---------------------------------------------------------------------*//*                                                                     *//*               Copyright 2001, Blunk Microsystems                    *//*                      ALL RIGHTS RESERVED                            *//*                                                                     *//*   Licensees have the non-exclusive right to use, modify, or extract *//*   this computer program for software development at a single site.  *//*   This program may be resold or disseminated in executable format   *//*   only. The source code may not be redistributed or resold.         *//*                                                                     *//***********************************************************************/#include "tcp_ipp.h"#include "ip/ip.h"#include <string.h>#include <stdlib.h>/***********************************************************************//* Configuration                                                       *//***********************************************************************/#define ARP_ALEN        6       /* max hardware address length */#define ARP_TSIZE       10      /* number of ARP cache entries */#define ARP_QSIZE       10      /* ARP cache entry queue size */#define ARP_TIMEOUT     (600 * TICKS_PER_SEC)   /* entry lifetime */#define ARP_RESEND      TICKS_PER_SEC   /* time between requests */#define ARP_ATTEMPTS    4       /* number of ARP request attempts *//***********************************************************************//* Symbol Definitions                                                  *//***********************************************************************//*** Definitions of codes used in operation field of ARP packet*/#define ARP_REQUEST     1       /* ARP request to resolve address */#define ARP_REPLY       2       /* reply to a resolve request */#define RARP_REQUEST    3       /* reverse ARP request (RARP packets) */#define RARP_REPLY      4       /* reply to a reverse request (RARP) *//*** State of ARP cache entry*/#define AES_FREE        0       /* entry is unused (initial value) */#define AES_PENDING     1       /* entry is used but incomplete */#define AES_RESOLVED    2       /* entry has been resolved *//*** RARP Timer Values*/#define K2_SECONDS      (TICKS_PER_SEC * 2)/*** Macros to access ARP packet addresses*/#define SenderHA(p) (&p->addresses[0])#define SenderPA(p) (&p->addresses[p->ha_len])#define TargetHA(p) (&p->addresses[p->ha_len + IP_ALEN])#define TargetPA(p) (&p->addresses[(p->ha_len * 2) + IP_ALEN])/*** arp_reply() flags*/#define BROADCAST       TRUE#define UNICAST         FALSE/***********************************************************************//* Type Definitions                                                    *//***********************************************************************//*** Format of ARP packet*/typedef struct arp{  ui16  hw_type;        /* hardware type */  ui16  pr_type;        /* protocol type */  ui8   ha_len;         /* hardware address length */  ui8   pa_len;         /* protocol address length */  ui16  operation;      /* ARP operation (see list above) */  ui8   addresses[20];  /* sender and target hw & proto addrs */  /*  ** addresses contains:  **   sender's hardware address  **   sender's protocol address  **   target's hardware address  **   target's protocol address  */} Arp;/*** Format of ARP cache entry*/typedef struct arpentry{  TcpTmr timer;             /* ARP entry timer */  Ni   *ni;                 /* pointer to interface structure */  NetBuf *qhead;            /* head of queue for this address */  NetBuf *qtail;            /* tail of queue for this address */  ui32 pr_addr;             /* protocol address */  ui8  qcount;              /* # of packets queued for this address */  ui8  attempts;            /* # of retries sent */  ui8  state;               /* state of this entry */  ui8  hw_addr[ARP_ALEN];   /* hardware address */} ArpEntry;/***********************************************************************//* Global Variable Definitions                                         *//***********************************************************************/static ArpEntry ArpTbl[ARP_TSIZE];static ArpEntry *OldestEntry;static ArpEntry *Entry;static int ArpCacheSize;static TcpTmr RarpTimer;static int RarpRetries;static ui8 ZeroHwAddr[MAX_ALEN];/***********************************************************************//* Local Function Prototypes                                           *//***********************************************************************/static ArpEntry *find_entry(ui32 ip_addr);static ArpEntry *alloc_entry(void);static void add_entry(Ni *ni, Arp *arp);static void free_queue(ArpEntry *arp_entry);static void send_request(ArpEntry *arp_entry);static void arp_reply(const Ni *ni, ui8 *ha, ui8 *pa, int brdcst);static void arp_timeout(void *object);#if TCP_PROBEstatic void got_arp(Arp *arp);#endifstatic void rarp_timeout(void *object);/***********************************************************************//* Global Function Definitions                                         *//***********************************************************************//***********************************************************************//*     ArpInit: Initialize ARP protocol                                *//*                                                                     *//***********************************************************************/void ArpInit(void){  ArpEntry *arp_entry;  /*-------------------------------------------------------------------*/  /* Initialize ARP table entries.                                     */  /*-------------------------------------------------------------------*/  for (arp_entry = ArpTbl; arp_entry < &ArpTbl[ARP_TSIZE]; ++arp_entry)  {    arp_entry->state = AES_FREE;    arp_entry->qhead = NULL;    arp_entry->qcount = 0;    arp_entry->timer.action = arp_timeout;    arp_entry->timer.object = arp_entry;    INIT_TMR(arp_entry->timer);  }  /*-------------------------------------------------------------------*/  /* Initialize pointers to first entries to search and to reuse.      */  /*-------------------------------------------------------------------*/  Entry = OldestEntry = &ArpTbl[0];  /*-------------------------------------------------------------------*/  /* Initialize RARP timeout action.                                   */  /*-------------------------------------------------------------------*/  RarpTimer.action = rarp_timeout;}/***********************************************************************//*     NiWrite: Write packet to interface, using ARP if needed         *//*                                                                     *//*       Input: buf = pointer to buffer to be transmitted              *//*                                                                     *//***********************************************************************/void NiWrite(NetBuf *buf){  Ni *ni = buf->ni;#if TCP_PROBE  /*-------------------------------------------------------------------*/  /* Decode outgoing network buffers on stdout.                        */  /*-------------------------------------------------------------------*/  NetProbe(buf);#endif  /*-------------------------------------------------------------------*/  /* Intercept packets destined for this machine.                      */  /*-------------------------------------------------------------------*/  if (ni == &Net.Local)  {    /*-----------------------------------------------------------------*/    /* Pass to local input.                                            */    /*-----------------------------------------------------------------*/    TcpAssert(RxBuf == 0);    RxBuf = buf;    IpLocalIn();    /*-----------------------------------------------------------------*/    /* Free buffer unless reserved for application use.                */    /*-----------------------------------------------------------------*/    if (RxBuf)      tcpRetBuf(&RxBuf);    return;  }  /*-------------------------------------------------------------------*/  /* If NI is point-to-point interface, always use transmit().         */  /*-------------------------------------------------------------------*/  if (ni->flags & NIF_P2P)    ni->transmit(buf, buf->ni->hw_addr);  /*-------------------------------------------------------------------*/  /* Else use broadcast() if next hop address is zero.                 */  /*-------------------------------------------------------------------*/  else if (buf->next_hop == 0)    ni->broadcast(buf);  /*-------------------------------------------------------------------*/  /* Else search ARP cache for next hop address.                       */  /*-------------------------------------------------------------------*/  else  {    ArpEntry *arp_entry = find_entry(buf->next_hop);    /*-----------------------------------------------------------------*/    /* If not even in cache, allocate entry and send ARP request.      */    /*-----------------------------------------------------------------*/    if (arp_entry == NULL)    {      arp_entry = alloc_entry();      arp_entry->ni = ni;      arp_entry->attempts = 0;      arp_entry->pr_addr = buf->next_hop;      send_request(arp_entry);      buf->next = NULL;      arp_entry->qhead = buf;      arp_entry->qtail = buf;      arp_entry->qcount = 1;    }    /*-----------------------------------------------------------------*/    /* Else there is an existing cache entry.                          */    /*-----------------------------------------------------------------*/    else    {      /*---------------------------------------------------------------*/      /* If entry is resolved, transmit with its hardware address.     */      /*---------------------------------------------------------------*/      if (arp_entry->state == AES_RESOLVED)        ni->transmit(buf, arp_entry->hw_addr);      /*---------------------------------------------------------------*/      /* Else if cache queue is full, discard buffer.                  */      /*---------------------------------------------------------------*/      else if (arp_entry->qcount >= ARP_QSIZE)        tcpRetBuf(&buf);      /*---------------------------------------------------------------*/      /* Else add buffer to entry's outbound buffer queue.             */      /*---------------------------------------------------------------*/      else      {        buf->next = NULL;        if (arp_entry->qhead == NULL)          arp_entry->qhead = buf;        else          arp_entry->qtail->next = buf;        arp_entry->qtail = buf;        ++arp_entry->qcount;      }    }  }}/***********************************************************************//*       ArpIn: Handle incoming ARP packets, replies and requests      *//*                                                                     *//***********************************************************************/void ArpIn(void){  Arp *arp;  ArpEntry *arp_entry;  Ni *ni = RxBuf->ni;  ui32 ip_addr;  ui8 *aligned;  /*-------------------------------------------------------------------*/  /* Align ARP packet to even byte boundary and assign pointer.        */  /*-------------------------------------------------------------------*/  aligned = (ui8 *)((ui32)RxBuf->ip_pkt & ~1);  if (aligned != RxBuf->ip_pkt)  {    memmove(aligned, RxBuf->ip_pkt, RxBuf->length);    RxBuf->ip_pkt = aligned;  }  arp = (Arp *)RxBuf->ip_pkt;#if TCP_PROBE  /*-------------------------------------------------------------------*/  /* Decode ARP packet if global decode flag is TRUE.                  */  /*-------------------------------------------------------------------*/  if (NetProbeFlag)    got_arp(arp);#endif  /*-------------------------------------------------------------------*/  /* Verify hardware and protocol type.                                */  /*-------------------------------------------------------------------*/  if (ntohs(arp->hw_type) != ni->hw_type ||      arp->pr_type != htons(IP_TYPE))    return;  /*-------------------------------------------------------------------*/  /* Check if source address matches a cache entry.                    */  /*-------------------------------------------------------------------*/  memcpy(&ip_addr, SenderPA(arp), IP_ALEN);  arp_entry = find_entry(ip_addr);  if (arp_entry)  {    int len = arp->ha_len;    /*-----------------------------------------------------------------*/    /* If this is an UnARP packet, free the arp entry and return.      */    /*-----------------------------------------------------------------*/    if ((len == 0) || (memcmp(SenderHA(arp), ZeroHwAddr, len) == 0))    {      arp_entry->state = AES_FREE;      NetTimerStop(&arp_entry->timer);      return;    }    /*-----------------------------------------------------------------*/    /* Otherwise, update entry's hardware address and timeout.         */    /*-----------------------------------------------------------------*/    else    {      memcpy(arp_entry->hw_addr, SenderHA(arp), len);      NetTimerStart(&arp_entry->timer, ARP_TIMEOUT);    }  }  /*-------------------------------------------------------------------*/  /* Finished if destination address does not match interface address. */  /*-------------------------------------------------------------------*/  memcpy(&ip_addr, TargetPA(arp), IP_ALEN);  if (ip_addr != ni->ip_addr)    return;  /*-------------------------------------------------------------------*/  /* Check if this source address is not in our cache.                 */  /*-------------------------------------------------------------------*/  if (arp_entry == NULL)  {    /*-----------------------------------------------------------------*/    /* If source address is valid, add new cache entry.                */    /*-----------------------------------------------------------------*/    ip_addr = INADDR_ANY;

⌨️ 快捷键说明

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