📄 arp.c
字号:
/***********************************************************************//* *//* 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 + -