📄 if_ether.c
字号:
/* if_ether.c - network Ethernet address resolution protocol *//* Copyright 1984 - 2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if_ether.c 8.2 (Berkeley) 9/26/94 *//* * Ethernet address resolution protocol. * TODO: * add "inuse/lock" bit (or ref. count) along with valid bit *//*modification history--------------------01u,24jun02,wap optimize away some bcopy()s in arpresolve()01t,21may02,vvv fixed ARP timer overflow problem (SPR #63908)01s,24jan02,vvv fixed arpintr memory leak (SPR #72577)01r,18dec01,vvv fixed build error from previous check-in01q,18dec01,vvv fixed shared-memory booting problem (SPR #71023)01p,10dec01,vvv allow send to any address assigned to an interface (SPR #71836)01o,01nov01,rae compiler warnings, modified arpresolve error message (SPR #71242)01n,12oct01,rae merge from truestack ver 01z base 01j (SPRs 63006, 68954, 69112 ... plus Fastpath, revarp, etc.)01m,07feb01,spm added merge record for 30jan01 update from version 01i of tor2_0_x branch (base 01h) and fixed modification history01l,30jan01,ijm merged SPR# 28602 fixes (proxy ARP services are obsolete); fixed deleting ARP entries when proxy flag set01j,08nov99,pul merging T2 cumulative patch 201k,08Nov98,pul changed the argument ordering to ipEtherResolveRtn01i,29apr99,pul Upgraded NPT phase3 code to tor2.0.001h,10may99,spm fixed SIOCSARP handling to support ATF_PUBL flag (SPR #24397)01g,03sep98,n_s fixed handling of IFF_NOARP flag in arpresolve. spr #2228001g,13jul98,n_s added arpRxmitTicks. spr # 2157701f,10jul97,vin ifdefed revarp code, fixed warnings.01e,23apr97,vin fixed SPR8445, rt_expire for arp route entry being set to 0.01d,29jan97,vin fixed a bug in arpioctl(), sdl_alen field.01c,16dec96,vin removed unnecessary htons in arprequest() and arpinput().01b,31oct96,vin changed m_gethdr(..) to mHdrClGet(..). 01a,03mar96,vin created from BSD4.4 stuff,integrated with 02n of if_ether.c*//* * Ethernet address resolution protocol. * TODO: * run at splnet (add ARP protocol intr.) * link entries onto hash chains, keep free list * add "inuse/lock" bit (or ref. count) along with valid bit */#include "vxWorks.h"#include "logLib.h"#include "stdio.h"#include "net/mbuf.h"#include "sys/socket.h"#include "errno.h"#include "sys/ioctl.h"#include "net/if.h"#include "net/if_dl.h"#include "net/route.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/in_var.h"#include "netinet/ip.h"#include "netinet/if_ether.h"#include "wdLib.h"#include "tickLib.h"#include "net/systm.h"#ifdef VIRTUAL_STACK#include "netinet/vsLib.h"#endif /* VIRTUAL_STACK */#ifdef ROUTER_STACK#include "wrn/fastPath/fastPathLib.h"#include "wrn/fastPath/fastPathIpP.h"#endif /* ROUTER_STACK */#ifdef INET#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET#include "wvNetLib.h"#endif /* INCLUDE_WVNET */#endif/* defines *//* defines */#define ENET_SIZE 6 /* Ethernet address size */#define DDB#define PROXY_HOOK /* include proxy hook code */#define SIN(s) ((struct sockaddr_in *)s)#define SDL(s) ((struct sockaddr_dl *)s)#define SRP(s) ((struct sockaddr_inarp *)s)/* * ARP trailer negotiation. Trailer protocol is not IP specific, * but ARP request/response use IP addresses. */#define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL#define rt_expire rt_rmx.rmx_expire#define ARP_RXMIT_TICKS_DFLT sysClkRateGet () /* Minimum number of ticks */ /* between retransmission */ /* of ARP request */#define TICK_GEQ(t1,t2) ((long)((t1) - (t2)) >= 0)/* externs */IMPORT STATUS netJobAdd (FUNCPTR, int, int, int, int, int);IMPORT int sysClkRateGet ();#ifndef VIRTUAL_STACKextern struct ifnet loif[];#endif /* VIRTUAL_STACK */extern void _insque ();extern void _remque ();int arpMaxEntries = 12; /* sensible default *//* globals */void arptfree (struct llinfo_arp *);#ifndef VIRTUAL_STACKstruct llinfo_arp llinfo_arp = {&llinfo_arp, &llinfo_arp};int arp_inuse, arp_allocated, arp_intimer;int arpinit_done = 0;#endif /* VIRTUAL_STACK */struct ifqueue arpintrq = {0, 0, 0, 50};int useloopback = 1;int arp_maxtries = 5; /* use loopback interface for local traffic *//* timer values */int arpt_prune = (1*60); /* walk list every 1 minutes */int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */int arpt_down = 20; /* once declared down, don't send for 20 secs */#ifndef VIRTUAL_STACKint arpRxmitTicks = -1; /* Minimum number of ticks between */ /* retranmission of ARP request */#endif /* VIRTUAL_STACK *//* proxy arp hook */#ifdef PROXY_HOOKFUNCPTR proxyArpHook = NULL;#endif/* locals */#ifndef VIRTUAL_STACKLOCAL WDOG_ID arptimerWd; /* watchdog timer for arptimer routine */#endif /* VIRTUAL_STACK */static char digits[] = "0123456789abcdef";#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* Set common fields of event identifiers for this module. */LOCAL UCHAR wvNetModuleId = WV_NET_IFETHER_MODULE; /* Value for if_ether.c */LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE; /* Available event filter */LOCAL ULONG wvNetEventId; /* Event identifier: see wvNetLib.h */#endif /* INCLUDE_WVNET */#endif/* forward declarations */#ifdef VIRTUAL_STACKvoid arptimer (int);#elsestatic void arptimer (void *);#endif /* VIRTUAL_STACK */static void arprequest (struct arpcom *, u_long *, u_long *, u_char *);static struct llinfo_arp *arplookup (u_long, int, int);static void in_arpinput (struct mbuf *);static void arpEntryDelete (void);/* * Timeout routine. Age arp_tab entries periodically. *//* ARGSUSED */#ifdef VIRTUAL_STACK/* must have a helper routine because of argument limitations *//* in WdStart */void arptimerRestart ( int stackNum ) { netJobAdd ((FUNCPTR)arptimer, stackNum, 0, 0, 0, 0); }void arptimer ( int stackNum /* used to set the stack correctly in wd routine*/ ) { int s; register struct llinfo_arp *la; virtualStackNumTaskIdSet(stackNum); s = splnet(); la = _llinfo_arp.la_next; wdStart (arptimerWd, arpt_prune * sysClkRateGet(), (FUNCPTR) arptimerRestart, (int) stackNum); while (la != &_llinfo_arp) { register struct rtentry *rt = la->la_rt; la = la->la_next; if (rt->rt_expire && rt->rt_expire <= tickGet()) { arptfree(la->la_prev); /* timer has expired; clear */ } } splx (s); }#else /* just use original version */static voidarptimer(arg) void *arg; { int s = splnet(); register struct llinfo_arp *la = llinfo_arp.la_next; wdStart (arptimerWd, arpt_prune * sysClkRateGet(), (FUNCPTR) netJobAdd, (int)arptimer); while (la != &llinfo_arp) { register struct rtentry *rt = la->la_rt; la = la->la_next; if (rt->rt_expire && TICK_GEQ (tickGet(), rt->rt_expire)) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_INFO, 2, 15, WV_NETEVENT_ARPTIMER_FREE)#endif /* INCLUDE_WVNET */#endif arptfree(la->la_prev); /* timer has expired; clear */ } } splx (s); }#endif /* VIRTUAL_STACK *//* IP multicast address to Ethernet mulitcast address mapping */void ipToEtherMCastMap ( struct in_addr * ipaddr, u_char * enaddr ) { enaddr[0] = 0x01; enaddr[1] = 0x00; enaddr[2] = 0x5e; enaddr[3] = ((u_char *)ipaddr)[1] & 0x7f; enaddr[4] = ((u_char *)ipaddr)[2]; enaddr[5] = ((u_char *)ipaddr)[3]; return; }/* IP to Ethernet address resolution protocol. This is just a wrapper for arpresolve* being called from ipOutput. This routine calls arpresolve with the appropriate* set of arguments. ** Returns 1 if the address is resolved and 0 if the address is not resolved.*/int ipEtherResolvRtn ( FUNCPTR ipArpCallBackRtn, struct mbuf * pMbuf, struct sockaddr * dstIpAddr, struct ifnet * ifp, struct rtentry * rt, char * dstBuff ) { return(arpresolve ((struct arpcom *)ifp, rt, pMbuf, dstIpAddr, dstBuff)); }/* * Parallel to llc_rtrequest. */voidarp_rtrequest(req, rt, sa) int req; register struct rtentry *rt; struct sockaddr *sa;{ register struct sockaddr *gate = rt->rt_gateway; register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; struct ifaddr *ifAddr = NULL;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 7, 17, WV_NETEVENT_ARPRTREQ_START, req)#endif /* INCLUDE_WVNET */#endif#ifndef VIRTUAL_STACK if (!arpinit_done) { /* * if this routine is executed for the first time, then * create the watch dog timer and kick of the arp timer. */ arpinit_done = 1; arptimerWd = wdCreate (); netJobAdd ((FUNCPTR)arptimer, 0, 0, 0, 0, 0); }#endif /* VIRTUAL_STACK */ if (rt->rt_flags & RTF_GATEWAY) return; switch (req) { case RTM_ADD: /* * XXX: If this is a manually added route to interface * such as older version of routed or gated might provide, * restore cloning bit. */ if ((rt->rt_flags & RTF_HOST) == 0 && SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) rt->rt_flags |= RTF_CLONING; if (rt->rt_flags & RTF_CLONING) { /* * Case 1: This route should come from a route to iface. */ rt_setgate(rt, rt_key(rt), (struct sockaddr *)&null_sdl); gate = rt->rt_gateway; SDL(gate)->sdl_type = rt->rt_ifp->if_type; SDL(gate)->sdl_index = rt->rt_ifp->if_index; /* * Give this route an expiration time, even though * it's a "permanent" route, so that routes cloned * from it do not need their expiration time set. */ rt->rt_expire = tickGet(); /* * rt_expire could be zero if the interface is * initialized before the first tick of the system * typically 1/60th of a second. * All the arp routes cloned from this route will * inherit all the route metrics properties. * if rt_expire is 0 for an arp route entry, * it never kicks in arpwhohas () in arpresolve (). * This would result in not generating an arp request * for the host. This problem was seen on the MIPS * board p4000. --- Vinai. Fix for SPR 8445 */ if (rt->rt_expire == 0) rt->rt_expire++; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -