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

📄 if_subr.c

📁 This is the demo source code for embedded VxWorks, which include severl functions. The function sour
💻 C
📖 第 1 页 / 共 2 页
字号:
/* if_subr.c - common routines for network interface drivers *//* Copyright 1990-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * Copyright (c) 1982, 1989, 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_ethersubr.c	8.1 (Berkeley) 6/10/93 *//*modification history--------------------01h,21aug98,n_s  updated if_omcast in ether_output () if_noproto in                  do_protocol_with_type (). spr2107401f,19sep97,vin  modified build_cluster to incorporate cluster blks,		 removed pointers to refcounts.01g,11aug97,vin  changed mBlkGet to use _pNetDpool.01e,10jul97,vin  removed unsupported revarpinput() code.01f,05jun97,vin  corrected processing for promiscuous interfaces in		 ether_input.01e,02jun97,spm  updated man page for bcopy_to_mbufs()01d,15may97,vin  reworked ether_input, cleanup, added copyFromMbufs().		 removed support for check_trailer().01c,16dec96,vin  removed unnecessary ntohs(). 01b,13nov96,vin  replaced m_gethdr with mBlkGet() in buildCluster.01a,03mar96,vin  created from BSD4.4 stuff,integrated with 02p of if_subr.c*/#include "vxWorks.h"#include "stdlib.h"#include "stdio.h"#include "tickLib.h"#include "logLib.h"#include "errno.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/in_var.h"#include "netinet/ip.h"#include "net/if.h"#include "net/if_arp.h"#include "netinet/if_ether.h"#include "net/if_subr.h"#include "netinet/in_var.h"#include "net/mbuf.h"#include "net/route.h"#include "net/if_llc.h"#include "net/if_dl.h"#include "net/if_types.h"#include "lstLib.h"#include "netLib.h"typedef struct net_type    {    NODE     	node;    FUNCPTR     inputRtn;    int     	etherType;    } NET_TYPE;/* externs */extern	struct ifnet loif;extern  looutput();u_char	etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };u_char	ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };u_char	ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };#define senderr(e) { error = (e); goto bad;}LOCAL LIST netTypeList;/* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. * Assumes that ifp is actually pointer to arpcom structure. */intether_output(ifp, m0, dst, rt0)	register struct ifnet *ifp;	struct mbuf *m0;	struct sockaddr *dst;	struct rtentry *rt0;{	u_short etype;	int s, error = 0; 	u_char edst[6];	register struct mbuf *m = m0;	register struct rtentry *rt;	struct mbuf *mcopy = (struct mbuf *)0;	register struct ether_header *eh;	int off, len = m->m_pkthdr.len;	struct arpcom *ac = (struct arpcom *)ifp;	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))		senderr(ENETDOWN);	ifp->if_lastchange = tickGet();	if ((rt = rt0)) {		if ((rt->rt_flags & RTF_UP) == 0) {			if ((rt0 = rt = rtalloc1(dst, 1)))				rt->rt_refcnt--;			else 				senderr(EHOSTUNREACH);		}		if (rt->rt_flags & RTF_GATEWAY) {			if (rt->rt_gwroute == 0)				goto lookup;			if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {				rtfree(rt); rt = rt0;			lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);				if ((rt = rt->rt_gwroute) == 0)					senderr(EHOSTUNREACH);			}		}		if (rt->rt_flags & RTF_REJECT)			if (rt->rt_rmx.rmx_expire == 0 ||			    tickGet() < rt->rt_rmx.rmx_expire)				senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);	}	switch (dst->sa_family) {#ifdef INET	case AF_INET:		if (!arpresolve(ac, rt, m, dst, edst))			return (0);	/* if not yet resolved */		/* If broadcasting on a simplex interface, loopback a copy */		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))			mcopy = m_copy(m, 0, (int)M_COPYALL);		off = m->m_pkthdr.len - m->m_len;		etype = ETHERTYPE_IP;		break;#endif	case AF_UNSPEC:		eh = (struct ether_header *)dst->sa_data; 		bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));		etype = eh->ether_type;		break;	default:		printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,			dst->sa_family);		senderr(EAFNOSUPPORT);	}	if (mcopy)		(void) looutput(ifp, mcopy, dst, rt);	/*	 * Add local net header.  If no space in first mbuf,	 * allocate another.	 */	M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);	if (m == 0)		senderr(ENOBUFS);	eh = mtod(m, struct ether_header *);	etype = htons(etype);	bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type,		sizeof(eh->ether_type)); 	bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 	bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,	    sizeof(eh->ether_shost));	s = splimp();	/*	 * Queue message on interface, and start output if interface	 * not yet active.	 */	if (IF_QFULL(&ifp->if_snd)) {		IF_DROP(&ifp->if_snd);		splx(s);		senderr(ENOBUFS);	}	IF_ENQUEUE(&ifp->if_snd, m);	if ((ifp->if_flags & IFF_OACTIVE) == 0)		(*ifp->if_start)(ifp);	splx(s);	ifp->if_obytes += len + sizeof (struct ether_header);	if (m->m_flags & M_MCAST || m->m_flags & M_BCAST)		ifp->if_omcasts++;	return (error);bad:	if (m)		m_freem(m);	return (error);}/********************************************************************************* do_protocol - check the link-level type field and process IP and ARP data** This routine must not be called at interrupt level.* Process a received Ethernet packet;* the packet is in the mbuf chain m without* the ether header, which is provided separately.** NOMANUAL*/voidether_input(ifp, eh, m)	struct ifnet *ifp;	register struct ether_header *eh;	struct mbuf *m;{	u_short 		etype;	struct arpcom *		ac = (struct arpcom *)ifp;	if ((ifp->if_flags & IFF_UP) == 0) {		m_freem(m);		return;	}	ifp->if_lastchange = tickGet();	ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);	if (eh->ether_dhost[0] & 1) {		if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,		    sizeof(etherbroadcastaddr)) == 0)			m->m_flags |= M_BCAST;		else			m->m_flags |= M_MCAST;		ifp->if_imcasts++;	}        if (ifp->if_flags & IFF_PROMISC)            {            /*             * do not hand over the non multicast packets to the ip stack             * if they are not destined to us, orelse it confuses the             * ip forwarding logic and keeps sending unnecessary redirects.             * If packets destined for other hosts have to be snooped they             * have to done through driver level hooks.             */                        if (!(m->m_flags & (M_BCAST | M_MCAST)))                {                if (bcmp ((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_dhost,                          sizeof(eh->ether_dhost)) != 0)                    {                    m_freem (m); 	/* free the packet chain */                    return;                     }                }            }        	etype = ntohs(eh->ether_type);        /* add code here to process IEEE802.3 LLC format, Hook!! */        /* demux the packet and hand off the ip layer */        do_protocol_with_type (etype, m , ac, m->m_pkthdr.len); }/* * Perform common duties while attaching to interface list */voidether_ifattach(ifp)	register struct ifnet *ifp;{	register struct ifaddr *ifa;	register struct sockaddr_dl *sdl;	ifp->if_type = IFT_ETHER;	ifp->if_addrlen = 6;	ifp->if_hdrlen = 14;	ifp->if_mtu = ETHERMTU;	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)		if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&		    sdl->sdl_family == AF_LINK) {			sdl->sdl_type = IFT_ETHER;			sdl->sdl_alen = ifp->if_addrlen;			bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,			      LLADDR(sdl), ifp->if_addrlen);			break;		}}/* * Add an Ethernet multicast address or range of addresses to the list for a * given interface. */intether_addmulti(ifr, ac)	struct ifreq *ifr;	register struct arpcom *ac;{	register struct ether_multi *enm;	struct sockaddr_in *sin;	u_char addrlo[6];	u_char addrhi[6];	int s = splimp();	switch (ifr->ifr_addr.sa_family) {	case AF_UNSPEC:		bcopy((char *)ifr->ifr_addr.sa_data, (char *)addrlo, 6);		bcopy((char *) addrlo, (char *)addrhi, 6);		break;#ifdef INET	case AF_INET:		sin = (struct sockaddr_in *)&(ifr->ifr_addr);		if (sin->sin_addr.s_addr == INADDR_ANY) {			/*			 * An IP address of INADDR_ANY means listen to all			 * of the Ethernet multicast addresses used for IP.			 * (This is for the sake of IP multicast routers.)			 */			bcopy((char *)ether_ipmulticast_min, (char *)addrlo, 6);			bcopy((char *)ether_ipmulticast_max, (char *)addrhi, 6);		}		else {			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);			bcopy((char *)addrlo, (char *)addrhi, 6);		}		break;#endif	default:		splx(s);		return (EAFNOSUPPORT);	}	/*	 * Verify that we have valid Ethernet multicast addresses.	 */	if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {		splx(s);		return (EINVAL);	}	/*	 * See if the address range is already in the list.	 */	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);	if (enm != NULL) {		/*		 * Found it; just increment the reference count.		 */		++enm->enm_refcount;		splx(s);		return (0);	}	/*	 * New address or range; malloc a new multicast record	 * and link it into the interface's multicast list.	 */        MALLOC (enm, struct ether_multi *, sizeof(*enm), MT_IFMADDR, 		M_DONTWAIT);	if (enm == NULL) {		splx(s);		return (ENOBUFS);	}	bcopy((char *)addrlo, (char *)enm->enm_addrlo, 6);	bcopy((char *)addrhi, (char *)enm->enm_addrhi, 6);	enm->enm_ac = ac;	enm->enm_refcount = 1;	enm->enm_next = ac->ac_multiaddrs;	ac->ac_multiaddrs = enm;	ac->ac_multicnt++;	splx(s);	/*	 * Return ENETRESET to inform the driver that the list has changed	 * and its reception filter should be adjusted accordingly.	 */	return (ENETRESET);}/* * Delete a multicast address record. */intether_delmulti(ifr, ac)	struct ifreq *ifr;	register struct arpcom *ac;{	register struct ether_multi *enm;	register struct ether_multi **p;	struct sockaddr_in *sin;	u_char addrlo[6];	u_char addrhi[6];	int s = splimp();	switch (ifr->ifr_addr.sa_family) {	case AF_UNSPEC:		bcopy((char *)ifr->ifr_addr.sa_data, (char *)addrlo, 6);		bcopy((char *)addrlo, (char *)addrhi, 6);		break;#ifdef INET	case AF_INET:		sin = (struct sockaddr_in *)&(ifr->ifr_addr);		if (sin->sin_addr.s_addr == INADDR_ANY) {			/*			 * An IP address of INADDR_ANY means stop listening			 * to the range of Ethernet multicast addresses used			 * for IP.			 */			bcopy((char *)ether_ipmulticast_min, (char *)addrlo, 6);			bcopy((char *)ether_ipmulticast_max, (char *)addrhi, 6);		}		else {			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);			bcopy((char *)addrlo, (char *)addrhi, 6);		}		break;#endif	default:		splx(s);		return (EAFNOSUPPORT);	}	/*	 * Look up the address in our list.	 */	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);	if (enm == NULL) {		splx(s);		return (ENXIO);	}	if (--enm->enm_refcount != 0) {		/*		 * Still some claims to this record.		 */		splx(s);		return (0);	}	/*	 * No remaining claims to this record; unlink and free it.	 */	for (p = &enm->enm_ac->ac_multiaddrs;	     *p != enm;	     p = &(*p)->enm_next)		continue;	*p = (*p)->enm_next;	FREE(enm, MT_IFMADDR);	ac->ac_multicnt--;	splx(s);	/*	 * Return ENETRESET to inform the driver that the list has changed	 * and its reception filter should be adjusted accordingly.	 */	return (ENETRESET);}/********************************************************************************* check_trailer - check ethernet frames that have trailers following them*

⌨️ 快捷键说明

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