1/*	$NetBSD$	*/
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * Copyright (c) 1982, 1989, 1993
34 *	The Regents of the University of California.  All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 *    notice, this list of conditions and the following disclaimer in the
43 *    documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors
45 *    may be used to endorse or promote products derived from this software
46 *    without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 *	@(#)if_fddisubr.c	8.1 (Berkeley) 6/10/93
61 *
62 * Id: if_fddisubr.c,v 1.15 1997/03/21 22:35:50 thomas Exp
63 */
64
65/*
66 * Copyright (c) 1995, 1996
67 *	Matt Thomas <matt@3am-software.com>.  All rights reserved.
68 *
69 * Redistribution and use in source and binary forms, with or without
70 * modification, are permitted provided that the following conditions
71 * are met:
72 * 1. Redistributions of source code must retain the above copyright
73 *    notice, this list of conditions and the following disclaimer.
74 * 2. Redistributions in binary form must reproduce the above copyright
75 *    notice, this list of conditions and the following disclaimer in the
76 *    documentation and/or other materials provided with the distribution.
77 * 3. The name of its contributor may not be used to endorse or promote
78 *    products derived from this software without specific prior written
79 *    permission.
80 *
81 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
82 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
85 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
86 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
87 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
88 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
89 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
90 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
91 * SUCH DAMAGE.
92 *
93 *	@(#)if_fddisubr.c	8.1 (Berkeley) 6/10/93
94 *
95 * Id: if_fddisubr.c,v 1.15 1997/03/21 22:35:50 thomas Exp
96 */
97
98#include <sys/cdefs.h>
99__KERNEL_RCSID(0, "$NetBSD$");
100
101#include "opt_gateway.h"
102#include "opt_inet.h"
103#include "opt_atalk.h"
104#include "opt_iso.h"
105#include "opt_ipx.h"
106#include "opt_mbuftrace.h"
107
108
109#include <sys/param.h>
110#include <sys/systm.h>
111#include <sys/kernel.h>
112#include <sys/malloc.h>
113#include <sys/mbuf.h>
114#include <sys/protosw.h>
115#include <sys/socket.h>
116#include <sys/ioctl.h>
117#include <sys/errno.h>
118#include <sys/syslog.h>
119
120#include <sys/cpu.h>
121
122#include <net/if.h>
123#include <net/netisr.h>
124#include <net/route.h>
125#include <net/if_llc.h>
126#include <net/if_dl.h>
127#include <net/if_types.h>
128
129#include <net/bpf.h>
130
131#ifdef INET
132#include <netinet/in.h>
133#include <netinet/in_var.h>
134#include <netinet/if_inarp.h>
135#include "opt_gateway.h"
136#endif
137#include <net/if_fddi.h>
138
139#ifdef IPX
140#include <netipx/ipx.h>
141#include <netipx/ipx_if.h>
142#endif
143
144#ifdef INET6
145#ifndef INET
146#include <netinet/in.h>
147#include <netinet/in_var.h>
148#endif
149#include <netinet6/nd6.h>
150#endif
151
152
153#include "carp.h"
154#if NCARP > 0
155#include <netinet/ip_carp.h>
156#endif
157
158#ifdef DECNET
159#include <netdnet/dn.h>
160#endif
161
162#ifdef ISO
163#include <netiso/argo_debug.h>
164#include <netiso/iso.h>
165#include <netiso/iso_var.h>
166#include <netiso/iso_snpac.h>
167#endif
168
169
170#ifdef NETATALK
171#include <netatalk/at.h>
172#include <netatalk/at_var.h>
173#include <netatalk/at_extern.h>
174
175#define llc_snap_org_code llc_un.type_snap.org_code
176#define llc_snap_ether_type llc_un.type_snap.ether_type
177
178extern u_char	at_org_code[ 3 ];
179extern u_char	aarp_org_code[ 3 ];
180#endif /* NETATALK */
181
182
183
184#define senderr(e) { error = (e); goto bad;}
185
186/*
187 * This really should be defined in if_llc.h but in case it isn't.
188 */
189#ifndef llc_snap
190#define	llc_snap	llc_un.type_snap
191#endif
192
193#define	FDDIADDR(ifp)		LLADDR((ifp)->if_sadl)
194#define	CFDDIADDR(ifp)		CLLADDR((ifp)->if_sadl)
195
196static	int fddi_output(struct ifnet *, struct mbuf *,
197	    const struct sockaddr *, struct rtentry *);
198static	void fddi_input(struct ifnet *, struct mbuf *);
199
200/*
201 * FDDI output routine.
202 * Encapsulate a packet of type family for the local net.
203 * Assumes that ifp is actually pointer to ethercom structure.
204 */
205static int
206fddi_output(struct ifnet *ifp0, struct mbuf *m0, const struct sockaddr *dst,
207    struct rtentry *rt0)
208{
209	uint16_t etype;
210	int error = 0, hdrcmplt = 0;
211	uint8_t esrc[6], edst[6];
212	struct mbuf *m = m0;
213	struct rtentry *rt;
214	struct fddi_header *fh;
215	struct mbuf *mcopy = NULL;
216	struct ifnet *ifp = ifp0;
217	ALTQ_DECL(struct altq_pktattr pktattr;)
218
219	MCLAIM(m, ifp->if_mowner);
220
221#if NCARP > 0
222	if (ifp->if_type == IFT_CARP) {
223		struct ifaddr *ifa;
224
225		/* loop back if this is going to the carp interface */
226		if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP &&
227		    (ifa = ifa_ifwithaddr(dst)) != NULL &&
228		    ifa->ifa_ifp == ifp0)
229			return (looutput(ifp0, m, dst, rt0));
230
231		ifp = ifp->if_carpdev;
232		/* ac = (struct arpcom *)ifp; */
233
234		if ((ifp0->if_flags & (IFF_UP|IFF_RUNNING)) !=
235		    (IFF_UP|IFF_RUNNING))
236			senderr(ENETDOWN);
237	}
238#endif /* NCARP > 0 */
239	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
240		senderr(ENETDOWN);
241#if !defined(__bsdi__) || _BSDI_VERSION >= 199401
242	if ((rt = rt0) != NULL) {
243		if ((rt->rt_flags & RTF_UP) == 0) {
244			if ((rt0 = rt = rtalloc1(dst, 1)) != NULL)
245				rt->rt_refcnt--;
246			else
247				senderr(EHOSTUNREACH);
248		}
249		if (rt->rt_flags & RTF_GATEWAY) {
250			if (rt->rt_gwroute == 0)
251				goto lookup;
252			if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
253				rtfree(rt); rt = rt0;
254			lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
255				if ((rt = rt->rt_gwroute) == 0)
256					senderr(EHOSTUNREACH);
257			}
258		}
259		if (rt->rt_flags & RTF_REJECT)
260			if (rt->rt_rmx.rmx_expire == 0 ||
261			    time_second < rt->rt_rmx.rmx_expire)
262				senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
263	}
264#endif
265
266	/*
267	 * If the queueing discipline needs packet classification,
268	 * do it before prepending link headers.
269	 */
270	IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
271
272	switch (dst->sa_family) {
273
274#ifdef INET
275	case AF_INET: {
276		if (m->m_flags & M_BCAST)
277                	memcpy(edst, fddibroadcastaddr, sizeof(edst));
278		else if (m->m_flags & M_MCAST) {
279			ETHER_MAP_IP_MULTICAST(&satocsin(dst)->sin_addr,
280			    (char *)edst);
281		} else if (!arpresolve(ifp, rt, m, dst, edst))
282			return (0);	/* if not yet resolved */
283		/* If broadcasting on a simplex interface, loopback a copy */
284		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
285			mcopy = m_copy(m, 0, (int)M_COPYALL);
286		etype = htons(ETHERTYPE_IP);
287		break;
288	}
289#endif
290#ifdef INET6
291	case AF_INET6:
292		if (!nd6_storelladdr(ifp, rt, m, dst, edst, sizeof(edst))){
293			/* something bad happened */
294			return (0);
295		}
296		etype = htons(ETHERTYPE_IPV6);
297		break;
298#endif
299#ifdef AF_ARP
300	case AF_ARP: {
301		struct arphdr *ah = mtod(m, struct arphdr *);
302		if (m->m_flags & M_BCAST)
303                	memcpy(edst, etherbroadcastaddr, sizeof(edst));
304		else {
305			void *tha = ar_tha(ah);
306			if (tha == NULL)
307				return 0;
308			memcpy(edst, tha, sizeof(edst));
309		}
310
311		ah->ar_hrd = htons(ARPHRD_ETHER);
312
313		switch (ntohs(ah->ar_op)) {
314		case ARPOP_REVREQUEST:
315		case ARPOP_REVREPLY:
316			etype = htons(ETHERTYPE_REVARP);
317			break;
318
319		case ARPOP_REQUEST:
320		case ARPOP_REPLY:
321		default:
322			etype = htons(ETHERTYPE_ARP);
323		}
324
325		break;
326	}
327#endif /* AF_ARP */
328#ifdef IPX
329	case AF_IPX:
330		etype = htons(ETHERTYPE_IPX);
331 		memcpy(edst, &(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
332		    sizeof (edst));
333		/* If broadcasting on a simplex interface, loopback a copy */
334		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
335			mcopy = m_copy(m, 0, (int)M_COPYALL);
336		break;
337#endif
338#ifdef NETATALK
339	case AF_APPLETALK: {
340		struct at_ifaddr *aa;
341		if (!aarpresolve(ifp, m, (const struct sockaddr_at *)dst, edst)) {
342#ifdef NETATALKDEBUG
343			printf("aarpresolv: failed\n");
344#endif
345			return (0);
346		}
347		/*
348		 * ifaddr is the first thing in at_ifaddr
349		 */
350		if ((aa = (struct at_ifaddr *)at_ifawithnet(
351		    (const struct sockaddr_at *)dst, ifp)) == NULL)
352			goto bad;
353
354		/*
355		 * In the phase 2 case, we need to prepend an mbuf for the llc
356		 * header. Since we must preserve the value of m, which is
357		 * passed to us by value, we m_copy() the first mbuf, and use
358		 * it for our llc header.
359		 */
360		if (aa->aa_flags & AFA_PHASE2) {
361			struct llc llc;
362
363			M_PREPEND(m, sizeof(struct llc), M_NOWAIT);
364			if (m == 0)
365				senderr(ENOBUFS);
366			llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
367			llc.llc_control = LLC_UI;
368			memcpy(llc.llc_snap_org_code, at_org_code,
369			    sizeof(at_org_code));
370			llc.llc_snap_ether_type = htons(ETHERTYPE_ATALK);
371			memcpy(mtod(m, void *), &llc, sizeof(struct llc));
372			etype = 0;
373		} else {
374			etype = htons(ETHERTYPE_ATALK);
375		}
376		break;
377	}
378#endif /* NETATALK */
379#ifdef	ISO
380	case AF_ISO: {
381		int	snpalen;
382		struct	llc *l;
383		const struct sockaddr_dl *sdl;
384
385		if (rt && (sdl = satocsdl(rt->rt_gateway)) &&
386		    sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
387			memcpy(edst, CLLADDR(sdl), sizeof(edst));
388		} else if ((error =
389			    iso_snparesolve(ifp, (const struct sockaddr_iso *)dst,
390					    (char *)edst, &snpalen)) != 0)
391			goto bad; /* Not Resolved */
392		/* If broadcasting on a simplex interface, loopback a copy */
393		if (*edst & 1)
394			m->m_flags |= (M_BCAST|M_MCAST);
395		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
396		    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
397			M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT);
398			if (mcopy) {
399				fh = mtod(mcopy, struct fddi_header *);
400				memcpy(fh->fddi_dhost, edst, sizeof (edst));
401				memcpy(fh->fddi_shost, CFDDIADDR(ifp),
402				    sizeof (edst));
403			}
404		}
405		M_PREPEND(m, 3, M_DONTWAIT);
406		if (m == NULL)
407			return (0);
408		etype = 0;
409		l = mtod(m, struct llc *);
410		l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
411		l->llc_control = LLC_UI;
412		} break;
413#endif /* ISO */
414
415	case pseudo_AF_HDRCMPLT:
416	{
417		const struct fddi_header *fh1 =
418		    (const struct fddi_header *)dst->sa_data;
419		hdrcmplt = 1;
420		memcpy(esrc, fh1->fddi_shost, sizeof (esrc));
421		/*FALLTHROUGH*/
422	}
423
424	case AF_LINK:
425	{
426		const struct fddi_header *fh1 =
427		    (const struct fddi_header *)dst->sa_data;
428 		memcpy(edst, fh1->fddi_dhost, sizeof (edst));
429		if (*edst & 1)
430			m->m_flags |= (M_BCAST|M_MCAST);
431		etype = 0;
432		break;
433	}
434
435	case AF_UNSPEC:
436	{
437		const struct ether_header *eh;
438		eh = (const struct ether_header *)dst->sa_data;
439 		memcpy(edst, eh->ether_dhost, sizeof(edst));
440		if (*edst & 1)
441			m->m_flags |= (M_BCAST|M_MCAST);
442		etype = eh->ether_type;
443		break;
444	}
445
446	case AF_IMPLINK:
447	{
448		fh = mtod(m, struct fddi_header *);
449		error = EPROTONOSUPPORT;
450		switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) {
451			case FDDIFC_LLC_ASYNC: {
452				/* legal priorities are 0 through 7 */
453				if ((fh->fddi_fc & FDDIFC_Z) > 7)
454			        	goto bad;
455				break;
456			}
457			case FDDIFC_LLC_SYNC: {
458				/* FDDIFC_Z bits reserved, must be zero */
459				if (fh->fddi_fc & FDDIFC_Z)
460					goto bad;
461				break;
462			}
463			case FDDIFC_SMT: {
464				/* FDDIFC_Z bits must be non zero */
465				if ((fh->fddi_fc & FDDIFC_Z) == 0)
466					goto bad;
467				break;
468			}
469			default: {
470				/* anything else is too dangerous */
471               	 		goto bad;
472			}
473		}
474		error = 0;
475		if (fh->fddi_dhost[0] & 1)
476			m->m_flags |= (M_BCAST|M_MCAST);
477		goto queue_it;
478	}
479	default:
480		printf("%s: can't handle af%d\n", ifp->if_xname,
481		       dst->sa_family);
482		senderr(EAFNOSUPPORT);
483	}
484
485
486	if (mcopy)
487		(void) looutput(ifp, mcopy, dst, rt);
488	if (etype != 0) {
489		struct llc *l;
490		M_PREPEND(m, sizeof (struct llc), M_DONTWAIT);
491		if (m == 0)
492			senderr(ENOBUFS);
493		l = mtod(m, struct llc *);
494		l->llc_control = LLC_UI;
495		l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
496		l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0;
497		memcpy(&l->llc_snap.ether_type, &etype, sizeof(uint16_t));
498	}
499	/*
500	 * Add local net header.  If no space in first mbuf,
501	 * allocate another.
502	 */
503	M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT);
504	if (m == 0)
505		senderr(ENOBUFS);
506	fh = mtod(m, struct fddi_header *);
507	fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4;
508 	memcpy(fh->fddi_dhost, edst, sizeof (edst));
509  queue_it:
510	if (hdrcmplt)
511		memcpy(fh->fddi_shost, esrc, sizeof(fh->fddi_shost));
512	else
513		memcpy(fh->fddi_shost, CFDDIADDR(ifp), sizeof(fh->fddi_shost));
514
515#if NCARP > 0
516	if (ifp0 != ifp && ifp0->if_type == IFT_CARP) {
517		if_set_sadl(ifp0, fh->fddi_shost, sizeof(fh->fddi_shost),
518		    false);
519	}
520
521	if (ifp != ifp0)
522		ifp0->if_obytes += m->m_pkthdr.len;
523#endif /* NCARP > 0 */
524	return ifq_enqueue(ifp, m ALTQ_COMMA ALTQ_DECL(&pktattr));
525
526bad:
527	if (m)
528		m_freem(m);
529	return (error);
530}
531
532/*
533 * Process a received FDDI packet;
534 * the packet is in the mbuf chain m with
535 * the fddi header.
536 */
537static void
538fddi_input(struct ifnet *ifp, struct mbuf *m)
539{
540#if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
541	struct ifqueue *inq;
542	int s;
543#endif
544	struct llc *l;
545	struct fddi_header *fh;
546
547	MCLAIM(m, &((struct ethercom *)ifp)->ec_rx_mowner);
548	if ((ifp->if_flags & IFF_UP) == 0) {
549		m_freem(m);
550		return;
551	}
552
553	fh = mtod(m, struct fddi_header *);
554
555	ifp->if_ibytes += m->m_pkthdr.len;
556	if (fh->fddi_dhost[0] & 1) {
557		if (memcmp(fddibroadcastaddr, fh->fddi_dhost,
558		    sizeof(fddibroadcastaddr)) == 0)
559			m->m_flags |= M_BCAST;
560		else
561			m->m_flags |= M_MCAST;
562		ifp->if_imcasts++;
563	} else if ((ifp->if_flags & IFF_PROMISC)
564	    && memcmp(CFDDIADDR(ifp), (void *)fh->fddi_dhost,
565		    sizeof(fh->fddi_dhost)) != 0) {
566		m_freem(m);
567		return;
568	}
569
570#ifdef M_LINK0
571	/*
572	 * If this has a LLC priority of 0, then mark it so upper
573	 * layers have a hint that it really came via a FDDI/Ethernet
574	 * bridge.
575	 */
576	if ((fh->fddi_fc & FDDIFC_LLC_PRIO7) == FDDIFC_LLC_PRIO0)
577		m->m_flags |= M_LINK0;
578#endif
579
580	l = (struct llc *)(fh+1);
581	switch (l->llc_dsap) {
582#if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
583	case LLC_SNAP_LSAP:
584	{
585		uint16_t etype;
586		if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
587			goto dropanyway;
588
589		/* Strip off the FDDI header. */
590		m_adj(m, sizeof(struct fddi_header));
591
592#ifdef NETATALK
593		if (memcmp(&(l->llc_snap_org_code)[0], at_org_code,
594			 sizeof(at_org_code)) == 0 &&
595		 	ntohs(l->llc_snap_ether_type) == ETHERTYPE_ATALK) {
596		    inq = &atintrq2;
597		    m_adj( m, sizeof( struct llc ));
598		    schednetisr(NETISR_ATALK);
599		    break;
600		}
601
602		if (memcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
603			 sizeof(aarp_org_code)) == 0 &&
604			ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
605		    m_adj( m, sizeof( struct llc ));
606		    aarpinput(ifp, m); /* XXX */
607		    return;
608		}
609#endif /* NETATALK */
610		if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0)
611			goto dropanyway;
612		etype = ntohs(l->llc_snap.ether_type);
613		m_adj(m, 8);
614#if NCARP > 0
615		if (ifp->if_carp && ifp->if_type != IFT_CARP &&
616		    (carp_input(m, (uint8_t *)&fh->fddi_shost,
617		    (uint8_t *)&fh->fddi_dhost, l->llc_snap.ether_type) == 0))
618			return;
619#endif
620
621		switch (etype) {
622#ifdef INET
623		case ETHERTYPE_IP:
624#ifdef GATEWAY
625			if (ipflow_fastforward(m))
626				return;
627#endif
628			schednetisr(NETISR_IP);
629			inq = &ipintrq;
630			break;
631
632		case ETHERTYPE_ARP:
633#if !defined(__bsdi__) || _BSDI_VERSION >= 199401
634			schednetisr(NETISR_ARP);
635			inq = &arpintrq;
636			break;
637#else
638			arpinput(ifp, m);
639			return;
640#endif
641#endif
642#ifdef IPX
643		case ETHERTYPE_IPX:
644			schednetisr(NETISR_IPX);
645			inq = &ipxintrq;
646			break;
647#endif
648#ifdef INET6
649		case ETHERTYPE_IPV6:
650#ifdef GATEWAY
651			if (ip6flow_fastforward(&m))
652				return;
653#endif
654			schednetisr(NETISR_IPV6);
655			inq = &ip6intrq;
656			break;
657
658#endif
659#ifdef DECNET
660		case ETHERTYPE_DECNET:
661			schednetisr(NETISR_DECNET);
662			inq = &decnetintrq;
663			break;
664#endif
665#ifdef NETATALK
666		case ETHERTYPE_ATALK:
667	                schednetisr(NETISR_ATALK);
668			inq = &atintrq1;
669			break;
670	        case ETHERTYPE_AARP:
671			/* probably this should be done with a NETISR as well */
672			aarpinput(ifp, m); /* XXX */
673			return;
674#endif /* NETATALK */
675		default:
676			ifp->if_noproto++;
677			goto dropanyway;
678		}
679		break;
680	}
681#endif /* INET || NS */
682#ifdef	ISO
683	case LLC_ISO_LSAP:
684		switch (l->llc_control) {
685		case LLC_UI:
686			/* LLC_UI_P forbidden in class 1 service */
687			if ((l->llc_dsap == LLC_ISO_LSAP) &&
688			    (l->llc_ssap == LLC_ISO_LSAP)) {
689
690				schednetisr(NETISR_ISO);
691				inq = &clnlintrq;
692				break;
693			}
694			goto dropanyway;
695
696		case LLC_XID:
697		case LLC_XID_P:
698			if(m->m_len <
699			    LLC_XID_BASIC_MINLEN + sizeof(struct fddi_header))
700				goto dropanyway;
701			l->llc_window = 0;
702			l->llc_fid = LLC_XID_FORMAT_BASIC;
703			l->llc_class = LLC_XID_CLASS_I;
704			l->llc_dsap = l->llc_ssap = 0;
705			/* Fall through to */
706		case LLC_TEST:
707		case LLC_TEST_P:
708		{
709			struct sockaddr sa;
710			struct ether_header *eh;
711			int i;
712			u_char c = l->llc_dsap;
713
714			l->llc_dsap = l->llc_ssap;
715			l->llc_ssap = c;
716			eh = (struct ether_header *)sa.sa_data;
717			if (m->m_flags & (M_BCAST | M_MCAST))
718				memcpy(eh->ether_dhost, CFDDIADDR(ifp), 6);
719			sa.sa_family = AF_UNSPEC;
720			sa.sa_len = sizeof(sa);
721			for (i = 0; i < 6; i++) {
722				eh->ether_shost[i] = fh->fddi_dhost[i];
723				eh->ether_dhost[i] = fh->fddi_shost[i];
724			}
725			eh->ether_type = 0;
726			m_adj(m, sizeof(struct fddi_header));
727			ifp->if_output(ifp, m, &sa, NULL);
728			return;
729		}
730		default:
731			m_freem(m);
732			return;
733		}
734		break;
735#endif /* ISO */
736
737	default:
738		ifp->if_noproto++;
739#if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
740	dropanyway:
741#endif
742		m_freem(m);
743		return;
744	}
745
746#if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
747	s = splnet();
748	if (IF_QFULL(inq)) {
749		IF_DROP(inq);
750		m_freem(m);
751	} else
752		IF_ENQUEUE(inq, m);
753	splx(s);
754#endif
755}
756
757/*
758 * Perform common duties while attaching to interface list
759 */
760void
761fddi_ifattach(struct ifnet *ifp, void *lla)
762{
763	struct ethercom *ec = (struct ethercom *)ifp;
764
765	ifp->if_type = IFT_FDDI;
766	ifp->if_hdrlen = 21;
767	ifp->if_dlt = DLT_FDDI;
768	ifp->if_mtu = FDDIMTU;
769	ifp->if_output = fddi_output;
770	ifp->if_input = fddi_input;
771	ifp->if_baudrate = IF_Mbps(100);
772#ifdef IFF_NOTRAILERS
773	ifp->if_flags |= IFF_NOTRAILERS;
774#endif
775
776	/*
777	 * Update the max_linkhdr
778	 */
779	if (ALIGN(ifp->if_hdrlen) > max_linkhdr)
780		max_linkhdr = ALIGN(ifp->if_hdrlen);
781
782	LIST_INIT(&ec->ec_multiaddrs);
783	if_set_sadl(ifp, lla, 6, true);
784
785	ifp->if_broadcastaddr = fddibroadcastaddr;
786	bpf_attach(ifp, DLT_FDDI, sizeof(struct fddi_header));
787#ifdef MBUFTRACE
788	strlcpy(ec->ec_tx_mowner.mo_name, ifp->if_xname,
789	    sizeof(ec->ec_tx_mowner.mo_name));
790	strlcpy(ec->ec_tx_mowner.mo_descr, "tx",
791	    sizeof(ec->ec_tx_mowner.mo_descr));
792	strlcpy(ec->ec_rx_mowner.mo_name, ifp->if_xname,
793	    sizeof(ec->ec_rx_mowner.mo_name));
794	strlcpy(ec->ec_rx_mowner.mo_descr, "rx",
795	    sizeof(ec->ec_rx_mowner.mo_descr));
796	MOWNER_ATTACH(&ec->ec_tx_mowner);
797	MOWNER_ATTACH(&ec->ec_rx_mowner);
798	ifp->if_mowner = &ec->ec_tx_mowner;
799#endif
800}
801