📄 if_subr.c
字号:
/* if_subr.c - common routines for network interface drivers *//* Copyright 1990 - 2002 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--------------------01q,23may02,vvv removed unnecessary m_copy from ether_output (SPR #77775)01p,22apr02,wap call ip_mloopback() rather than calling looutput() directly (SPR #72246)01o,15apr02,wap reinstate netJobAdd removal changes01n,29mar02,wap back out the previous change (needs more investigation)01m,21mar02,rae remove unecessary netJobAdd() SPR #01l,21mar02,vvv updated man page for copyFromMbufs (SPR #20787)01k,01nov01,rae fixed compile warnings, corrected WV event (SPR #71284)01j,12oct01,rae merge from truestack ver 01o, base 01h (SPR #69112 etc.)01i,17oct00,spm updated ether_attach to report memory allocation failures01h,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 "netinet/ip_var.h" /* for ipintr() prototype */#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"#include "muxLib.h"#include "memPartLib.h"#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET#include "wvNetLib.h"#endif /* INCLUDE_WVNET */#endif#ifdef VIRTUAL_STACK#include "netinet/vsLib.h"#endiftypedef struct net_type { NODE node; FUNCPTR inputRtn; int etherType; } NET_TYPE;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* Set common fields of event identifiers for this module. */LOCAL UCHAR wvNetModuleId = WV_NET_IFSUBR_MODULE; /* Value for if_subr.c */LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE; /* Available event filter */LOCAL ULONG wvNetEventId; /* Event identifier: see wvNetLib.h */#endif /* INCLUDE_WVNET */#endif/* externs */#ifndef VIRTUAL_STACKextern struct ifnet loif;extern void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *, struct rtentry *rt);#endif /* VIRTUAL_STACK */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; 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)) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_CRITICAL event */ WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 2, 3, WV_NETEVENT_ETHEROUT_IFDOWN, WV_NET_SEND, ifp)#endif /* INCLUDE_WVNET */#endif 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 {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_CRITICAL event */ WV_NET_DSTADDROUT_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 4, 5, ((struct sockaddr_in *)dst)->sin_addr.s_addr, WV_NETEVENT_ETHEROUT_NOROUTE, WV_NET_SEND, ((struct sockaddr_in *)dst)->sin_addr.s_addr)#endif /* INCLUDE_WVNET */#endif 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) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_CRITICAL event */ WV_NET_DSTADDROUT_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 4, 5, ((struct sockaddr_in *)rt->rt_gateway)->sin_addr.s_addr, WV_NETEVENT_ETHEROUT_NOROUTE, WV_NET_SEND, ((struct sockaddr_in *)rt->rt_gateway)->sin_addr.s_addr)#endif /* INCLUDE_WVNET */#endif senderr(EHOSTUNREACH); } } } if (rt->rt_flags & RTF_REJECT) if (rt->rt_rmx.rmx_expire == 0 || tickGet() < rt->rt_rmx.rmx_expire) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_CRITICAL event */ WV_NET_EVENT_0 (NET_CORE_EVENT, WV_NET_CRITICAL, 5, 6, WV_NETEVENT_ETHEROUT_RTREJECT, WV_NET_SEND)#endif /* INCLUDE_WVNET */#endif 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)) ip_mloopback (ifp, m, (struct sockaddr_in *)dst, (struct rtentry*)rt); 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);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_ERROR event */ WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_ERROR, 3, 7, WV_NETEVENT_ETHEROUT_AFNOTSUPP, WV_NET_SEND, dst->sa_family)#endif /* INCLUDE_WVNET */#endif senderr(EAFNOSUPPORT); } /* * Add local net header. If no space in first mbuf, * allocate another. */ M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); if (m == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_CRITICAL event */ WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 3, 4, WV_NETEVENT_ETHEROUT_NOBUFS, WV_NET_SEND, ifp)#endif /* INCLUDE_WVNET */#endif 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);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_CRITICAL event */ WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 3, 4, WV_NETEVENT_ETHEROUT_NOBUFS, WV_NET_SEND, ifp)#endif /* INCLUDE_WVNET */#endif 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++;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_NOTICE event */ WV_NET_EVENT_2 (NET_CORE_EVENT, WV_NET_NOTICE, 3, 12, WV_NETEVENT_ETHEROUT_FINISH, WV_NET_SEND, ifp, error)#endif /* INCLUDE_WVNET */#endif 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;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_NOTICE event */ WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_NOTICE, 4, 13, WV_NETEVENT_ETHERIN_START, WV_NET_RECV, ifp)#endif /* INCLUDE_WVNET */#endif 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; } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -