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

📄 if_ether.c

📁 vxworks源码源码解读是学习vxworks的最佳途径
💻 C
📖 第 1 页 / 共 2 页
字号:
/* if_ether.c - network Ethernet address resolution protocol *//* Copyright 1984-1996 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--------------------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 "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 INET/* defines */#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          *//* externs */IMPORT void netJobAdd ();IMPORT sysClkRateGet ();extern	struct ifnet loif;extern  _insque ();extern  _remque ();/* globals */void arptfree (struct llinfo_arp *);struct	llinfo_arp llinfo_arp = {&llinfo_arp, &llinfo_arp};struct	ifqueue arpintrq = {0, 0, 0, 50};int	arp_inuse, arp_allocated, arp_intimer;int	arp_maxtries = 5;int	useloopback = 1;	/* use loopback interface for local traffic */int	arpinit_done = 0;/* 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 */int     arpRxmitTicks = -1;     /* Minimum number of ticks between */                                /*   retranmission of ARP request *//* proxy ary hook */#ifdef PROXY_HOOKFUNCPTR	 proxyArpHook = NULL;#endif/* locals *//* revarp state */#ifdef INCLUDE_REVARP /* XXX currently not supported */static struct	in_addr myip, srv_ip;static int	myip_initialized = 0;static int	revarp_in_progress = 0;static struct	ifnet *myip_ifp = NULL;#endif /* INCLUDE_REVARP */LOCAL WDOG_ID arptimerWd;	/* watchdog timer for arptimer routine */static char 	digits[] = "0123456789abcdef";/* forward declarations */static	void arprequest (struct arpcom *, u_long *, u_long *, u_char *);static	void arptimer (void *);static	struct llinfo_arp *arplookup (u_long, int, int);static	void in_arpinput (struct mbuf *);/* * Timeout routine.  Age arp_tab entries periodically. *//* ARGSUSED */static voidarptimer(arg)	void *arg;    {    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 && rt->rt_expire <= tickGet())	    {	    arptfree(la->la_prev); /* timer has expired; clear */	    }	}    }/* * 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};		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 (arptimer);	}	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;		}		/* Announce a new entry if requested. */		if (rt->rt_flags & RTF_ANNOUNCE)			arprequest((struct arpcom *)rt->rt_ifp,			    &SIN(rt_key(rt))->sin_addr.s_addr,			    &SIN(rt_key(rt))->sin_addr.s_addr,			    (u_char *)LLADDR(SDL(gate)));		/*FALLTHROUGH*/	case RTM_RESOLVE:		if (gate->sa_family != AF_LINK ||		    gate->sa_len < sizeof(null_sdl)) {			logMsg("arp_rtrequest: bad gateway value",0,0,0,0,0,0);			break;		}		SDL(gate)->sdl_type = rt->rt_ifp->if_type;		SDL(gate)->sdl_index = rt->rt_ifp->if_index;		if (la != 0)			break; /* This happens on a route change */		/*		 * Case 2:  This route may come from cloning, or a manual route		 * add with a LL address.		 */		R_Malloc(la, struct llinfo_arp *, sizeof(*la));		rt->rt_llinfo = (caddr_t)la;		if (la == 0) {			logMsg("arp_rtrequest: malloc failed\n",0,0,0,0,0,0);			break;		}		arp_inuse++, arp_allocated++;		Bzero(la, sizeof(*la));		la->la_rt = rt;		rt->rt_flags |= RTF_LLINFO;		insque(la, &llinfo_arp);		if (SIN(rt_key(rt))->sin_addr.s_addr ==		    (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) {		    /*		     * This test used to be		     *	if (loif.if_flags & IFF_UP)		     * It allowed local traffic to be forced		     * through the hardware by configuring the loopback down.		     * However, it causes problems during network configuration		     * for boards that can't receive packets they send.		     * It is now necessary to clear "useloopback" and remove		     * the route to force traffic out to the hardware.		     */			rt->rt_expire = 0;			Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr,				LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6);			if (useloopback)				rt->rt_ifp = &loif;		}		break;	case RTM_DELETE:		if (la == 0)			break;		arp_inuse--;		remque(la);		rt->rt_llinfo = 0;		rt->rt_flags &= ~RTF_LLINFO;		if (la->la_hold)			m_freem(la->la_hold);		Free((caddr_t)la);	}}/* * Broadcast an ARP packet, asking who has addr on interface ac. */voidarpwhohas(ac, addr)	register struct arpcom *ac;	register struct in_addr *addr;{	arprequest(ac, &ac->ac_ipaddr.s_addr, &addr->s_addr, ac->ac_enaddr);}/* * Broadcast an ARP request. Caller specifies: *	- arp header source ip address *	- arp header target ip address *	- arp header source ethernet address */static voidarprequest(ac, sip, tip, enaddr)	register struct arpcom *ac;	register u_long *sip, *tip;	register u_char *enaddr;{	register struct mbuf *m;	register struct ether_header *eh;	register struct ether_arp *ea;	struct sockaddr sa;	if ((m = mHdrClGet(M_DONTWAIT, MT_DATA, 			   sizeof(*ea), TRUE)) == NULL)	    return;	m->m_len = sizeof(*ea);	m->m_pkthdr.len = sizeof(*ea);	MH_ALIGN(m, sizeof(*ea));	ea = mtod(m, struct ether_arp *);	eh = (struct ether_header *)sa.sa_data;	bzero((caddr_t)ea, sizeof (*ea));	bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,	    sizeof(eh->ether_dhost));	eh->ether_type = ETHERTYPE_ARP;		/* if_output will swap */	ea->arp_hrd = htons(ARPHRD_ETHER);	ea->arp_pro = htons(ETHERTYPE_IP);	ea->arp_hln = sizeof(ea->arp_sha);	/* hardware address length */	ea->arp_pln = sizeof(ea->arp_spa);	/* protocol address length */	ea->arp_op = htons(ARPOP_REQUEST);	bcopy((caddr_t)enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha));	bcopy((caddr_t)sip, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa));	bcopy((caddr_t)tip, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa));	sa.sa_family = AF_UNSPEC;	sa.sa_len = sizeof(sa);	(*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);}/* * Resolve an IP address into an ethernet address.  If success, * desten is filled in.  If there is no entry in arptab, * set one up and broadcast a request for the IP address. * Hold onto this mbuf and resend it once the address * is finally resolved.  A return value of 1 indicates * that desten has been filled in and the packet should be sent * normally; a 0 return indicates that the packet has been * taken over here, either now or for later transmission. */intarpresolve(ac, rt, m, dst, desten)	register struct arpcom *ac;	register struct rtentry *rt;	struct mbuf *m;	register struct sockaddr *dst;	register u_char *desten;{	register struct llinfo_arp *la;	struct sockaddr_dl *sdl;	int alen;                          /* Length of MAC address */	u_long lna;                        /* Host portion if IP address */	if (m != NULL)		/* check if mbuf is not null */	    {	    if (m->m_flags & M_BCAST)		{	/* broadcast */		bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten,		      sizeof(etherbroadcastaddr));		return (1);		}	    if (m->m_flags & M_MCAST)		{	/* multicast */		ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);		return(1);		}	    }		if (rt)		la = (struct llinfo_arp *)rt->rt_llinfo;	else {		if ((la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0)))			rt = la->la_rt;	}	if (la == 0 || rt == 0) {		logMsg ("arpresolve: can't allocate llinfo",0,0,0,0,0,0);		m_freem(m);		return (0);	}	sdl = SDL(rt->rt_gateway);	/*	 * Check the address family and length is valid, the address	 * is resolved; otherwise, try to resolve.	 */	if ((rt->rt_expire == 0 || rt->rt_expire > tickGet()) &&	    sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {		bcopy(LLADDR(sdl), (char *)desten, sdl->sdl_alen);		return 1;	}	/* If IFF_NOARP then make LL addr from IP host addr */	 	if (ac->ac_if.if_flags & IFF_NOARP) 	    {	    /* Set expiration of Route/ARP entry */	    if (rt->rt_expire == 0)		{		rt->rt_expire = tickGet ();		}	    /* Set length of MAC address.  Default to Ethernet length. */	    alen = (sdl->sdl_alen > 0 ? sdl->sdl_alen : 		    sizeof (struct ether_addr));	    if (alen < 3)		{		return (0);		}	    bcopy((caddr_t)ac->ac_enaddr, (char *)desten, alen - 3);	    lna = in_lnaof(SIN(dst)->sin_addr);	    desten[alen - 1]     = lna & 0xff;	    desten[alen - 1 - 1] = (lna >> 8) & 0xff;	    desten[alen - 1 - 2] = (lna >> 16) & 0x7f;	    return (1);	    }	/*	 * There is an arptab entry, but no ethernet address	 * response yet.  Replace the held mbuf with this	 * latest one.	 */	if (la->la_hold)		m_freem(la->la_hold);	la->la_hold = m;	if (rt->rt_expire) {		rt->rt_flags &= ~RTF_REJECT;		if (arpRxmitTicks < 0)		    arpRxmitTicks = ARP_RXMIT_TICKS_DFLT;		if (la->la_asked == 0 || 		    (tickGet () - rt->rt_expire >= arpRxmitTicks)) {			rt->rt_expire = tickGet();			if (la->la_asked++ < arp_maxtries)				arpwhohas(ac, &(SIN(dst)->sin_addr));			else {				rt->rt_flags |= RTF_REJECT;				rt->rt_expire += (sysClkRateGet() * arpt_down);				la->la_asked = 0;			}		}	}	return (0);}/* * Common length and type checks are done here, * then the protocol-specific routine is called. */voidarpintr(){	register struct mbuf *m;	register struct arphdr *ar;	int s;	while (arpintrq.ifq_head) {		s = splimp();		IF_DEQUEUE(&arpintrq, m);		splx(s);		if (m == 0 || (m->m_flags & M_PKTHDR) == 0)			panic("arpintr");		if (m->m_len >= sizeof(struct arphdr) &&		    (ar = mtod(m, struct arphdr *)) &&		    ntohs(ar->ar_hrd) == ARPHRD_ETHER &&		    m->m_len >=		      sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln))			switch (ntohs(ar->ar_pro)) {			case ETHERTYPE_IP:			case ETHERTYPE_IPTRAILERS:#ifdef PROXY_HOOK			        if (proxyArpHook != NULL)				    (* proxyArpHook)					((struct arpcom *)m->m_pkthdr.rcvif,m);#endif				in_arpinput(m);				continue;			}		m_freem(m);	}}/* * ARP for Internet protocols on 10 Mb/s Ethernet. * Algorithm is that given in RFC 826. * In addition, a sanity check is performed on the sender * protocol address, to catch impersonators. * We no longer handle negotiations for use of trailer protocol: * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent * along with IP replies if we wanted trailers sent to us, * and also sent them in response to IP replies. * This allowed either end to announce the desire to receive * trailer packets. * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, * but formerly didn't normally send requests. */static voidin_arpinput(m)	struct mbuf *m;{	register struct ether_arp *ea;	register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;

⌨️ 快捷键说明

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