if_fddisubr.c revision 60889
17055Sdg/* 221830Sjoerg * Copyright (c) 1995, 1996 321830Sjoerg * Matt Thomas <matt@3am-software.com>. All rights reserved. 47055Sdg * Copyright (c) 1982, 1989, 1993 57055Sdg * The Regents of the University of California. All rights reserved. 67055Sdg * 77055Sdg * Redistribution and use in source and binary forms, with or without 87055Sdg * modification, are permitted provided that the following conditions 97055Sdg * are met: 107055Sdg * 1. Redistributions of source code must retain the above copyright 117055Sdg * notice, this list of conditions and the following disclaimer. 127055Sdg * 2. Redistributions in binary form must reproduce the above copyright 137055Sdg * notice, this list of conditions and the following disclaimer in the 147055Sdg * documentation and/or other materials provided with the distribution. 157055Sdg * 3. All advertising materials mentioning features or use of this software 167055Sdg * must display the following acknowledgement: 177055Sdg * This product includes software developed by the University of 187055Sdg * California, Berkeley and its contributors. 197055Sdg * 4. Neither the name of the University nor the names of its contributors 207055Sdg * may be used to endorse or promote products derived from this software 217055Sdg * without specific prior written permission. 227055Sdg * 237055Sdg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 247055Sdg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 257055Sdg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 267055Sdg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 277055Sdg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 287055Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 297055Sdg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 307055Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 317055Sdg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 327055Sdg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 337055Sdg * SUCH DAMAGE. 347055Sdg * 357061Sdg * from: if_ethersubr.c,v 1.5 1994/12/13 22:31:45 wollman Exp 3650477Speter * $FreeBSD: head/sys/net/if_fddisubr.c 60889 2000-05-24 21:16:56Z archie $ 377055Sdg */ 387055Sdg 3932356Seivind#include "opt_atalk.h" 4032350Seivind#include "opt_inet.h" 4154263Sshin#include "opt_inet6.h" 4231742Seivind#include "opt_ipx.h" 4331742Seivind 447055Sdg#include <sys/param.h> 457055Sdg#include <sys/systm.h> 467055Sdg#include <sys/mbuf.h> 477055Sdg#include <sys/socket.h> 487055Sdg 497055Sdg#include <net/if.h> 507055Sdg#include <net/netisr.h> 517055Sdg#include <net/route.h> 527055Sdg#include <net/if_llc.h> 537055Sdg#include <net/if_dl.h> 547055Sdg#include <net/if_types.h> 557055Sdg 5654263Sshin#if defined(INET) || defined(INET6) 577055Sdg#include <netinet/in.h> 587055Sdg#include <netinet/in_var.h> 5932350Seivind#include <netinet/if_ether.h> 607055Sdg#endif 6154263Sshin#ifdef INET6 6254263Sshin#include <netinet6/nd6.h> 6354263Sshin#endif 6421830Sjoerg#if defined(__FreeBSD__) 657055Sdg#include <netinet/if_fddi.h> 6621830Sjoerg#else 6721830Sjoerg#include <net/if_fddi.h> 6821830Sjoerg#endif 697055Sdg 7011819Sjulian#ifdef IPX 7121830Sjoerg#include <netipx/ipx.h> 7211819Sjulian#include <netipx/ipx_if.h> 7311819Sjulian#endif 7411819Sjulian 757055Sdg#ifdef NS 767055Sdg#include <netns/ns.h> 777055Sdg#include <netns/ns_if.h> 787055Sdg#endif 797055Sdg 807055Sdg#ifdef DECNET 817055Sdg#include <netdnet/dn.h> 827055Sdg#endif 837055Sdg 8421830Sjoerg#ifdef NETATALK 8521830Sjoerg#include <netatalk/at.h> 8621830Sjoerg#include <netatalk/at_var.h> 8721830Sjoerg#include <netatalk/at_extern.h> 8821830Sjoerg 8921830Sjoerg#define llc_snap_org_code llc_un.type_snap.org_code 9021830Sjoerg#define llc_snap_ether_type llc_un.type_snap.ether_type 9121830Sjoerg 9221830Sjoergextern u_char at_org_code[ 3 ]; 9321830Sjoergextern u_char aarp_org_code[ 3 ]; 9421830Sjoerg#endif /* NETATALK */ 9521830Sjoerg 967055Sdg#define senderr(e) { error = (e); goto bad;} 977055Sdg 987055Sdg/* 997055Sdg * This really should be defined in if_llc.h but in case it isn't. 1007055Sdg */ 1017055Sdg#ifndef llc_snap 1027055Sdg#define llc_snap llc_un.type_snap 1037055Sdg#endif 1047055Sdg 10521830Sjoerg#if defined(__bsdi__) || defined(__NetBSD__) 10621830Sjoerg#define RTALLOC1(a, b) rtalloc1(a, b) 1077055Sdg#define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e) 10821830Sjoerg#elif defined(__FreeBSD__) 10921830Sjoerg#define RTALLOC1(a, b) rtalloc1(a, b, 0UL) 1107055Sdg#define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e, f) 1117055Sdg#endif 1127055Sdg/* 1137055Sdg * FDDI output routine. 1147055Sdg * Encapsulate a packet of type family for the local net. 1157055Sdg * Use trailer local net encapsulation if enough data in first 1167055Sdg * packet leaves a multiple of 512 bytes of data in remainder. 1177055Sdg * Assumes that ifp is actually pointer to arpcom structure. 1187055Sdg */ 1197055Sdgint 12054799Sgreenfddi_output(ifp, m, dst, rt0) 1217055Sdg register struct ifnet *ifp; 12254799Sgreen struct mbuf *m; 1237055Sdg struct sockaddr *dst; 1247055Sdg struct rtentry *rt0; 1257055Sdg{ 12621830Sjoerg u_int16_t type; 12752248Smsmith int s, loop_copy = 0, error = 0, hdrcmplt = 0; 12852248Smsmith u_char esrc[6], edst[6]; 1297055Sdg register struct rtentry *rt; 13021830Sjoerg register struct fddi_header *fh; 1317055Sdg struct arpcom *ac = (struct arpcom *)ifp; 1327055Sdg 1337055Sdg if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 1347055Sdg senderr(ENETDOWN); 13534961Sphk getmicrotime(&ifp->if_lastchange); 13621830Sjoerg#if !defined(__bsdi__) || _BSDI_VERSION >= 199401 13743305Sdillon if ((rt = rt0) != NULL) { 1387055Sdg if ((rt->rt_flags & RTF_UP) == 0) { 13943305Sdillon if ((rt0 = rt = RTALLOC1(dst, 1)) != NULL) 1407055Sdg rt->rt_refcnt--; 14121830Sjoerg else 1427055Sdg senderr(EHOSTUNREACH); 1437055Sdg } 1447055Sdg if (rt->rt_flags & RTF_GATEWAY) { 1457055Sdg if (rt->rt_gwroute == 0) 1467055Sdg goto lookup; 1477055Sdg if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 1487055Sdg rtfree(rt); rt = rt0; 1497055Sdg lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 1); 1507055Sdg if ((rt = rt->rt_gwroute) == 0) 1517055Sdg senderr(EHOSTUNREACH); 1527055Sdg } 1537055Sdg } 1547055Sdg if (rt->rt_flags & RTF_REJECT) 1557055Sdg if (rt->rt_rmx.rmx_expire == 0 || 15634961Sphk time_second < rt->rt_rmx.rmx_expire) 1577055Sdg senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 1587055Sdg } 15921830Sjoerg#endif 1607055Sdg switch (dst->sa_family) { 1617055Sdg 1627055Sdg#ifdef INET 16321830Sjoerg case AF_INET: { 16421830Sjoerg#if !defined(__bsdi__) || _BSDI_VERSION >= 199401 1657055Sdg if (!ARPRESOLVE(ac, rt, m, dst, edst, rt0)) 1667055Sdg return (0); /* if not yet resolved */ 16721830Sjoerg#else 16821830Sjoerg int usetrailers; 16921830Sjoerg if (!arpresolve(ac, m, &((struct sockaddr_in *)dst)->sin_addr, edst, &usetrailers)) 17021830Sjoerg return (0); /* if not yet resolved */ 17121830Sjoerg#endif 17221830Sjoerg type = htons(ETHERTYPE_IP); 1737055Sdg break; 17421830Sjoerg } 1757055Sdg#endif 17654263Sshin#ifdef INET6 17754263Sshin case AF_INET6: 17854263Sshin if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) { 17954263Sshin /* this must be impossible, so we bark */ 18054263Sshin printf("nd6_storelladdr failed\n"); 18154263Sshin return(0); 18254263Sshin } 18354263Sshin type = htons(ETHERTYPE_IPV6); 18454263Sshin break; 18554263Sshin#endif 18611819Sjulian#ifdef IPX 18711819Sjulian case AF_IPX: 18821830Sjoerg type = htons(ETHERTYPE_IPX); 18911819Sjulian bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), 19011819Sjulian (caddr_t)edst, sizeof (edst)); 19111819Sjulian break; 19211819Sjulian#endif 19321830Sjoerg#ifdef NETATALK 19421830Sjoerg case AF_APPLETALK: { 19521830Sjoerg struct at_ifaddr *aa; 19636908Sjulian if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) 19721830Sjoerg return (0); 19821830Sjoerg /* 19921830Sjoerg * ifaddr is the first thing in at_ifaddr 20021830Sjoerg */ 20130834Sjulian if ((aa = at_ifawithnet( (struct sockaddr_at *)dst)) == 0) 20221830Sjoerg goto bad; 20321830Sjoerg 20421830Sjoerg /* 20521830Sjoerg * In the phase 2 case, we need to prepend an mbuf for the llc header. 20621830Sjoerg * Since we must preserve the value of m, which is passed to us by 20721830Sjoerg * value, we m_copy() the first mbuf, and use it for our llc header. 20821830Sjoerg */ 20921830Sjoerg if (aa->aa_flags & AFA_PHASE2) { 21021830Sjoerg struct llc llc; 21121830Sjoerg 21221830Sjoerg M_PREPEND(m, sizeof(struct llc), M_WAIT); 21321830Sjoerg if (m == 0) 21421830Sjoerg senderr(ENOBUFS); 21521830Sjoerg llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP; 21621830Sjoerg llc.llc_control = LLC_UI; 21721830Sjoerg bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code)); 21821830Sjoerg llc.llc_snap_ether_type = htons(ETHERTYPE_AT); 21921830Sjoerg bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc)); 22021830Sjoerg type = 0; 22121830Sjoerg } else { 22221830Sjoerg type = htons(ETHERTYPE_AT); 22321830Sjoerg } 22421830Sjoerg break; 22521830Sjoerg } 22621830Sjoerg#endif /* NETATALK */ 2277055Sdg#ifdef NS 2287055Sdg case AF_NS: 22921830Sjoerg type = htons(ETHERTYPE_NS); 2307055Sdg bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 2317055Sdg (caddr_t)edst, sizeof (edst)); 2327055Sdg break; 2337055Sdg#endif 2347055Sdg 23552248Smsmith case pseudo_AF_HDRCMPLT: 23652248Smsmith { 23752248Smsmith struct ether_header *eh; 23852248Smsmith hdrcmplt = 1; 23952248Smsmith eh = (struct ether_header *)dst->sa_data; 24052248Smsmith (void)memcpy((caddr_t)esrc, (caddr_t)eh->ether_shost, sizeof (esrc)); 24152248Smsmith /* FALLTHROUGH */ 24252248Smsmith } 24352248Smsmith 2447055Sdg case AF_UNSPEC: 2457055Sdg { 2467055Sdg struct ether_header *eh; 24736992Sjulian loop_copy = -1; 2487055Sdg eh = (struct ether_header *)dst->sa_data; 2498384Sdg (void)memcpy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 2507055Sdg if (*edst & 1) 2517055Sdg m->m_flags |= (M_BCAST|M_MCAST); 2527055Sdg type = eh->ether_type; 2537055Sdg break; 2547055Sdg } 2557055Sdg 2567055Sdg case AF_IMPLINK: 2577055Sdg { 2587055Sdg fh = mtod(m, struct fddi_header *); 2597055Sdg error = EPROTONOSUPPORT; 2607055Sdg switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) { 2617055Sdg case FDDIFC_LLC_ASYNC: { 2627055Sdg /* legal priorities are 0 through 7 */ 2637055Sdg if ((fh->fddi_fc & FDDIFC_Z) > 7) 2647055Sdg goto bad; 2657055Sdg break; 2667055Sdg } 2677055Sdg case FDDIFC_LLC_SYNC: { 2687055Sdg /* FDDIFC_Z bits reserved, must be zero */ 2697055Sdg if (fh->fddi_fc & FDDIFC_Z) 2707055Sdg goto bad; 2717055Sdg break; 2727055Sdg } 2737055Sdg case FDDIFC_SMT: { 2747055Sdg /* FDDIFC_Z bits must be non zero */ 2757055Sdg if ((fh->fddi_fc & FDDIFC_Z) == 0) 2767055Sdg goto bad; 2777055Sdg break; 2787055Sdg } 2797055Sdg default: { 2807055Sdg /* anything else is too dangerous */ 2817055Sdg goto bad; 2827055Sdg } 2837055Sdg } 2847055Sdg error = 0; 2857055Sdg if (fh->fddi_dhost[0] & 1) 2867055Sdg m->m_flags |= (M_BCAST|M_MCAST); 2877055Sdg goto queue_it; 2887055Sdg } 2897055Sdg default: 2907055Sdg printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, 2917055Sdg dst->sa_family); 2927055Sdg senderr(EAFNOSUPPORT); 2937055Sdg } 2947055Sdg 2957055Sdg if (type != 0) { 2967055Sdg register struct llc *l; 2977055Sdg M_PREPEND(m, sizeof (struct llc), M_DONTWAIT); 2987055Sdg if (m == 0) 2997055Sdg senderr(ENOBUFS); 3007055Sdg l = mtod(m, struct llc *); 3017055Sdg l->llc_control = LLC_UI; 3027055Sdg l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP; 3037055Sdg l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0; 3048384Sdg (void)memcpy((caddr_t) &l->llc_snap.ether_type, (caddr_t) &type, 30521830Sjoerg sizeof(u_int16_t)); 3067055Sdg } 30736908Sjulian 3087055Sdg /* 3097055Sdg * Add local net header. If no space in first mbuf, 3107055Sdg * allocate another. 3117055Sdg */ 3127055Sdg M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT); 3137055Sdg if (m == 0) 3147055Sdg senderr(ENOBUFS); 3157055Sdg fh = mtod(m, struct fddi_header *); 3167055Sdg fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; 3178384Sdg (void)memcpy((caddr_t)fh->fddi_dhost, (caddr_t)edst, sizeof (edst)); 3187055Sdg queue_it: 31952248Smsmith if (hdrcmplt) 32052248Smsmith (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)esrc, 32152248Smsmith sizeof(fh->fddi_shost)); 32252248Smsmith else 32352248Smsmith (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)ac->ac_enaddr, 32452248Smsmith sizeof(fh->fddi_shost)); 32536908Sjulian /* 32636908Sjulian * If a simplex interface, and the packet is being sent to our 32736908Sjulian * Ethernet address or a broadcast address, loopback a copy. 32836908Sjulian * XXX To make a simplex device behave exactly like a duplex 32936908Sjulian * device, we should copy in the case of sending to our own 33036908Sjulian * ethernet address (thus letting the original actually appear 33136908Sjulian * on the wire). However, we don't do that here for security 33236908Sjulian * reasons and compatibility with the original behavior. 33336908Sjulian */ 33436992Sjulian if ((ifp->if_flags & IFF_SIMPLEX) && 33536992Sjulian (loop_copy != -1)) { 33636908Sjulian if ((m->m_flags & M_BCAST) || loop_copy) { 33736908Sjulian struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 33836908Sjulian 33936908Sjulian (void) if_simloop(ifp, 34060889Sarchie n, dst->sa_family, sizeof(struct fddi_header)); 34136908Sjulian } else if (bcmp(fh->fddi_dhost, 34236908Sjulian fh->fddi_shost, sizeof(fh->fddi_shost)) == 0) { 34336908Sjulian (void) if_simloop(ifp, 34460889Sarchie m, dst->sa_family, sizeof(struct fddi_header)); 34536908Sjulian return(0); /* XXX */ 34636908Sjulian } 34736908Sjulian } 34836908Sjulian 3497055Sdg s = splimp(); 3507055Sdg /* 3517055Sdg * Queue message on interface, and start output if interface 3527055Sdg * not yet active. 3537055Sdg */ 3547055Sdg if (IF_QFULL(&ifp->if_snd)) { 3557055Sdg IF_DROP(&ifp->if_snd); 3567055Sdg splx(s); 3577055Sdg senderr(ENOBUFS); 3587055Sdg } 3597055Sdg ifp->if_obytes += m->m_pkthdr.len; 3607055Sdg IF_ENQUEUE(&ifp->if_snd, m); 3617055Sdg if ((ifp->if_flags & IFF_OACTIVE) == 0) 3627055Sdg (*ifp->if_start)(ifp); 3637055Sdg splx(s); 3647055Sdg if (m->m_flags & M_MCAST) 3657055Sdg ifp->if_omcasts++; 3667055Sdg return (error); 3677055Sdg 3687055Sdgbad: 3697055Sdg if (m) 3707055Sdg m_freem(m); 3717055Sdg return (error); 3727055Sdg} 3737055Sdg 3747055Sdg/* 3757055Sdg * Process a received FDDI packet; 3767055Sdg * the packet is in the mbuf chain m without 3777055Sdg * the fddi header, which is provided separately. 3787055Sdg */ 3797055Sdgvoid 3807055Sdgfddi_input(ifp, fh, m) 3817055Sdg struct ifnet *ifp; 3827055Sdg register struct fddi_header *fh; 3837055Sdg struct mbuf *m; 3847055Sdg{ 3857055Sdg register struct ifqueue *inq; 3867055Sdg register struct llc *l; 3877055Sdg int s; 3887055Sdg 3897055Sdg if ((ifp->if_flags & IFF_UP) == 0) { 3907055Sdg m_freem(m); 3917055Sdg return; 3927055Sdg } 39334961Sphk getmicrotime(&ifp->if_lastchange); 3947055Sdg ifp->if_ibytes += m->m_pkthdr.len + sizeof (*fh); 39521830Sjoerg if (fh->fddi_dhost[0] & 1) { 39621830Sjoerg if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost, 39721830Sjoerg sizeof(fddibroadcastaddr)) == 0) 39821830Sjoerg m->m_flags |= M_BCAST; 39921830Sjoerg else 40021830Sjoerg m->m_flags |= M_MCAST; 4017055Sdg ifp->if_imcasts++; 40223910Sjoerg } else if ((ifp->if_flags & IFF_PROMISC) 40323910Sjoerg && bcmp(((struct arpcom *)ifp)->ac_enaddr, (caddr_t)fh->fddi_dhost, 40423910Sjoerg sizeof(fh->fddi_dhost)) != 0) { 40523910Sjoerg m_freem(m); 40623910Sjoerg return; 40721830Sjoerg } 4087055Sdg 40921830Sjoerg#ifdef M_LINK0 41021830Sjoerg /* 41121830Sjoerg * If this has a LLC priority of 0, then mark it so upper 41221830Sjoerg * layers have a hint that it really came via a FDDI/Ethernet 41321830Sjoerg * bridge. 41421830Sjoerg */ 41521830Sjoerg if ((fh->fddi_fc & FDDIFC_LLC_PRIO7) == FDDIFC_LLC_PRIO0) 41621830Sjoerg m->m_flags |= M_LINK0; 41721830Sjoerg#endif 41821830Sjoerg 4197055Sdg l = mtod(m, struct llc *); 4207055Sdg switch (l->llc_dsap) { 42154263Sshin#if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK) 4227055Sdg case LLC_SNAP_LSAP: 4237055Sdg { 42421830Sjoerg u_int16_t type; 4257055Sdg if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP) 4267055Sdg goto dropanyway; 42721830Sjoerg#ifdef NETATALK 42821830Sjoerg if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code, 42921830Sjoerg sizeof(at_org_code)) == 0 && 43021830Sjoerg ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { 43121830Sjoerg inq = &atintrq2; 43221830Sjoerg m_adj( m, sizeof( struct llc )); 43321830Sjoerg schednetisr(NETISR_ATALK); 43421830Sjoerg break; 43521830Sjoerg } 43621830Sjoerg 43721830Sjoerg if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code, 43821830Sjoerg sizeof(aarp_org_code)) == 0 && 43921830Sjoerg ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { 44021830Sjoerg m_adj( m, sizeof( struct llc )); 44121830Sjoerg aarpinput((struct arpcom *)ifp, m); /* XXX */ 44221830Sjoerg return; 44321830Sjoerg } 44421830Sjoerg#endif /* NETATALK */ 4457055Sdg if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0) 4467055Sdg goto dropanyway; 44721830Sjoerg type = ntohs(l->llc_snap.ether_type); 4487055Sdg m_adj(m, 8); 44921830Sjoerg switch (type) { 4507055Sdg#ifdef INET 4517055Sdg case ETHERTYPE_IP: 45236265Sdg if (ipflow_fastforward(m)) 45336192Sdg return; 4547055Sdg schednetisr(NETISR_IP); 4557055Sdg inq = &ipintrq; 4567055Sdg break; 4577055Sdg 4587055Sdg case ETHERTYPE_ARP: 45921830Sjoerg#if !defined(__bsdi__) || _BSDI_VERSION >= 199401 4607055Sdg schednetisr(NETISR_ARP); 4617055Sdg inq = &arpintrq; 4627055Sdg break; 46321830Sjoerg#else 46421830Sjoerg arpinput((struct arpcom *)ifp, m); 46521830Sjoerg return; 4667055Sdg#endif 46721830Sjoerg#endif 46854263Sshin#ifdef INET6 46954263Sshin case ETHERTYPE_IPV6: 47054263Sshin schednetisr(NETISR_IPV6); 47154263Sshin inq = &ip6intrq; 47254263Sshin break; 47354263Sshin#endif 47421830Sjoerg#ifdef IPX 47521830Sjoerg case ETHERTYPE_IPX: 47621830Sjoerg schednetisr(NETISR_IPX); 47721830Sjoerg inq = &ipxintrq; 47821830Sjoerg break; 47921830Sjoerg#endif 4807055Sdg#ifdef NS 4817055Sdg case ETHERTYPE_NS: 4827055Sdg schednetisr(NETISR_NS); 4837055Sdg inq = &nsintrq; 4847055Sdg break; 4857055Sdg#endif 4867055Sdg#ifdef DECNET 48721830Sjoerg case ETHERTYPE_DECNET: 4887055Sdg schednetisr(NETISR_DECNET); 4897055Sdg inq = &decnetintrq; 4907055Sdg break; 4917055Sdg#endif 49221830Sjoerg#ifdef NETATALK 49321830Sjoerg case ETHERTYPE_AT: 49421830Sjoerg schednetisr(NETISR_ATALK); 49521830Sjoerg inq = &atintrq1; 49621830Sjoerg break; 49721830Sjoerg case ETHERTYPE_AARP: 49821830Sjoerg /* probably this should be done with a NETISR as well */ 49921830Sjoerg aarpinput((struct arpcom *)ifp, m); /* XXX */ 50021830Sjoerg return; 50121830Sjoerg#endif /* NETATALK */ 5027055Sdg default: 50321830Sjoerg /* printf("fddi_input: unknown protocol 0x%x\n", type); */ 5047055Sdg ifp->if_noproto++; 5057055Sdg goto dropanyway; 5067055Sdg } 5077055Sdg break; 5087055Sdg } 5097055Sdg#endif /* INET || NS */ 51021830Sjoerg 5117055Sdg default: 51221830Sjoerg /* printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap); */ 5137055Sdg ifp->if_noproto++; 5147055Sdg dropanyway: 5157055Sdg m_freem(m); 5167055Sdg return; 5177055Sdg } 5187055Sdg 5197055Sdg s = splimp(); 5207055Sdg if (IF_QFULL(inq)) { 5217055Sdg IF_DROP(inq); 5227055Sdg m_freem(m); 5237055Sdg } else 5247055Sdg IF_ENQUEUE(inq, m); 5257055Sdg splx(s); 5267055Sdg} 5277055Sdg/* 5287055Sdg * Perform common duties while attaching to interface list 5297055Sdg */ 53021830Sjoerg#ifdef __NetBSD__ 53121830Sjoerg#define ifa_next ifa_list.tqe_next 53221830Sjoerg#endif 53321830Sjoerg 5347055Sdgvoid 5357055Sdgfddi_ifattach(ifp) 5367055Sdg register struct ifnet *ifp; 5377055Sdg{ 5387055Sdg register struct ifaddr *ifa; 5397055Sdg register struct sockaddr_dl *sdl; 5407055Sdg 5417055Sdg ifp->if_type = IFT_FDDI; 5427055Sdg ifp->if_addrlen = 6; 5437055Sdg ifp->if_hdrlen = 21; 5447055Sdg ifp->if_mtu = FDDIMTU; 54516063Sgpalmer ifp->if_baudrate = 100000000; 54621830Sjoerg#ifdef IFF_NOTRAILERS 54721830Sjoerg ifp->if_flags |= IFF_NOTRAILERS; 54821830Sjoerg#endif 54921831Sjoerg#if defined(__FreeBSD__) 55021831Sjoerg ifa = ifnet_addrs[ifp->if_index - 1]; 55121831Sjoerg sdl = (struct sockaddr_dl *)ifa->ifa_addr; 55221831Sjoerg sdl->sdl_type = IFT_FDDI; 55321831Sjoerg sdl->sdl_alen = ifp->if_addrlen; 55421831Sjoerg bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); 55521831Sjoerg#elif defined(__NetBSD__) 55621830Sjoerg LIST_INIT(&((struct arpcom *)ifp)->ac_multiaddrs); 55721830Sjoerg for (ifa = ifp->if_addrlist.tqh_first; ifa != NULL; ifa = ifa->ifa_list.tqe_next) 55821830Sjoerg#else 55921830Sjoerg for (ifa = ifp->if_addrlist; ifa != NULL; ifa = ifa->ifa_next) 56021830Sjoerg#endif 56121831Sjoerg#if !defined(__FreeBSD__) 56221830Sjoerg if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && 56321830Sjoerg sdl->sdl_family == AF_LINK) { 56421830Sjoerg sdl->sdl_type = IFT_FDDI; 56521830Sjoerg sdl->sdl_alen = ifp->if_addrlen; 56621830Sjoerg bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, 56721830Sjoerg LLADDR(sdl), ifp->if_addrlen); 56821830Sjoerg break; 56921830Sjoerg } 57021831Sjoerg#endif 5717055Sdg} 572