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