1 /*	$OpenBSD: if_tokensubr.c,v 1.14 2004/04/17 00:09:01 henning Exp $	*/
2 /*	$NetBSD: if_tokensubr.c,v 1.7 1999/05/30 00:39:07 bad Exp $	*/
3 
4 /*
5  * Copyright (c) 1997-1999
6  *	Onno van der Linden
7  * Copyright (c) 1995
8  *	Matt Thomas.  All rights reserved.
9  * Copyright (c) 1982, 1989, 1993
10  *	The Regents of the University of California.  All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *	from: NetBSD: if_fddisubr.c,v 1.2 1995/08/19 04:35:29 cgd Exp
37  */
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/mbuf.h>
44 #include <sys/protosw.h>
45 #include <sys/socket.h>
46 #include <sys/ioctl.h>
47 #include <sys/errno.h>
48 #include <sys/syslog.h>
49 
50 #include <machine/cpu.h>
51 
52 #include <net/if.h>
53 #include <net/netisr.h>
54 #include <net/route.h>
55 #include <net/if_llc.h>
56 #include <net/if_dl.h>
57 #include <net/if_types.h>
58 
59 
60 #ifdef INET
61 #include <netinet/in.h>
62 #include <netinet/if_ether.h>
63 #include <netinet/in_var.h>
64 #include <net/if_token.h>
65 #endif
66 
67 #ifdef NS
68 #include <netns/ns.h>
69 #include <netns/ns_if.h>
70 #endif
71 
72 #ifdef DECNET
73 #include <netdnet/dn.h>
74 #endif
75 
76 #ifdef ISO
77 #include <netiso/argo_debug.h>
78 #include <netiso/iso.h>
79 #include <netiso/iso_var.h>
80 #include <netiso/iso_snpac.h>
81 #endif
82 
83 #include "bpfilter.h"
84 
85 #ifdef LLC
86 #include <netccitt/dll.h>
87 #include <netccitt/llc_var.h>
88 #endif
89 
90 /*
91  * TODO:
92  * handle source routing via send_xid()
93  * source routing for ISO,LLC,CCITT protocols
94  * need sockaddr_dl_8025 to handle this correctly
95  * IPX cases
96  * handle "fast" forwarding like if_ether and if_fddi
97  */
98 
99 #if defined(LLC) && defined(CCITT)
100 extern struct ifqueue pkintrq;
101 #endif
102 
103 #define senderr(e) { error = (e); goto bad;}
104 
105 #if defined(__bsdi__) || defined(__NetBSD__) || defined(__OpenBSD__)
106 #define	RTALLOC1(a, b)			rtalloc1(a, b)
107 #define	ARPRESOLVE(a, b, c, d, e, f)	arpresolve(a, b, c, d, e)
108 #define	TYPEHTONS(t)			(t)
109 #elif defined(__FreeBSD__)
110 #define	RTALLOC1(a, b)			rtalloc1(a, b, 0UL)
111 #define	ARPRESOLVE(a, b, c, d, e, f)	arpresolve(a, b, c, d, e, f)
112 #define	TYPEHTONS(t)			(htons(t))
113 #endif
114 
115 #define RCF_ALLROUTES (2 << 8) | TOKEN_RCF_FRAME2 | TOKEN_RCF_BROADCAST_ALL
116 #define RCF_SINGLEROUTE (2 << 8) | TOKEN_RCF_FRAME2 | TOKEN_RCF_BROADCAST_SINGLE
117 
118 #ifndef llc_snap
119 #define llc_snap	llc_un.type_snap
120 #endif
121 
122 int	token_output(struct ifnet *, struct mbuf *, struct sockaddr *,
123 	struct rtentry *);
124 
125 /*
126  * Token Ring output routine.
127  * Encapsulate a packet of type family for the local net.
128  * Assumes that ifp is actually pointer to arphdr structure.
129  * XXX route info has to go into the same mbuf as the header
130  */
131 int
token_output(ifp,m0,dst,rt0)132 token_output(ifp, m0, dst, rt0)
133 	struct ifnet *ifp;
134 	struct mbuf *m0;
135 	struct sockaddr *dst;
136 	struct rtentry *rt0;
137 {
138 	u_int16_t etype;
139 	int s, len, error = 0;
140 	u_char edst[ISO88025_ADDR_LEN];
141 	struct mbuf *m = m0;
142 	struct rtentry *rt;
143 	struct mbuf *mcopy = (struct mbuf *)0;
144 	struct token_header *trh;
145 #ifdef INET
146 	struct arpcom *ac = (struct arpcom *)ifp;
147 #endif /* INET */
148 	struct token_rif *rif = (struct  token_rif *)0;
149 	struct token_rif bcastrif;
150 	size_t riflen = 0;
151 	short mflags;
152 
153 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
154 		senderr(ENETDOWN);
155 	if ((rt = rt0)) {
156 		if ((rt->rt_flags & RTF_UP) == 0) {
157 			if ((rt0 = rt = RTALLOC1(dst, 1)))
158 				rt->rt_refcnt--;
159 			else
160 				senderr(EHOSTUNREACH);
161 		}
162 		if (rt->rt_flags & RTF_GATEWAY) {
163 			if (rt->rt_gwroute == 0)
164 				goto lookup;
165 			if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
166 				rtfree(rt); rt = rt0;
167 			lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 1);
168 				if ((rt = rt->rt_gwroute) == 0)
169 					senderr(EHOSTUNREACH);
170 			}
171 		}
172 		if (rt->rt_flags & RTF_REJECT)
173 			if (rt->rt_rmx.rmx_expire == 0 ||
174 			    time.tv_sec < rt->rt_rmx.rmx_expire)
175 				senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
176 	}
177 
178 	switch (dst->sa_family) {
179 
180 #ifdef INET
181 	case AF_INET:
182 		if (m->m_flags & M_BCAST) {
183 			if (ifp->if_flags & IFF_LINK0) {
184 				if (ifp->if_flags & IFF_LINK1)
185 					bcastrif.tr_rcf = htons(RCF_ALLROUTES);
186 				else
187 					bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
188 				rif = &bcastrif;
189 				riflen = sizeof(rif->tr_rcf);
190 			}
191 			bcopy((caddr_t)tokenbroadcastaddr, (caddr_t)edst,
192 			    sizeof(edst));
193 		}
194 /*
195  * XXX m->m_flags & M_MCAST   IEEE802_MAP_IP_MULTICAST ??
196  */
197 		else {
198 			if (!ARPRESOLVE(ac, rt, m, dst, edst, rt0))
199 				return (0);	/* if not yet resolved */
200 			rif = TOKEN_RIF((struct llinfo_arp *) rt->rt_llinfo);
201 			riflen = (ntohs(rif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
202 		}
203 		/* If broadcasting on a simplex interface, loopback a copy. */
204 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
205 		    m_tag_find(m, PACKET_TAG_PF_ROUTED, NULL) == NULL)
206 			mcopy = m_copy(m, 0, (int)M_COPYALL);
207 		etype = htons(ETHERTYPE_IP);
208 		break;
209 #if 0
210 	case AF_ARP:
211 /*
212  * XXX source routing, assume m->m_data contains the useful stuff
213  */
214 		ah = mtod(m, struct arphdr *);
215 		ah->ar_hrd = htons(ARPHRD_IEEE802);
216 
217 		switch(ntohs(ah->ar_op)) {
218 		case ARPOP_REVREQUEST:
219 		case ARPOP_REVREPLY:
220 			etype = htons(ETHERTYPE_REVARP);
221 			break;
222 
223 		case ARPOP_REQUEST:
224 		case ARPOP_REPLY:
225 		default:
226 			etype = htons(ETHERTYPE_ARP);
227 		}
228 
229 		if (m->m_flags & M_BCAST) {
230 			if (ifp->if_flags & IFF_LINK0) {
231 				if (ifp->if_flags & IFF_LINK1)
232 					bcastrif.tr_rcf = htons(RCF_ALLROUTES);
233 				else
234 					bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
235 				rif = &bcastrif;
236 				riflen = sizeof(rif->tr_rcf);
237 			}
238 			bcopy((caddr_t)tokenbroadcastaddr, (caddr_t)edst,
239 			    sizeof(edst));
240 		}
241 		else {
242 			bcopy((caddr_t)ar_tha(ah), (caddr_t)edst, sizeof(edst));
243 			trh = (struct token_header *)M_TRHSTART(m);
244 			trh->token_ac = TOKEN_AC;
245 			trh->token_fc = TOKEN_FC;
246 			if (trh->token_shost[0] & TOKEN_RI_PRESENT) {
247 				struct token_rif *trrif;
248 
249 				trrif = TOKEN_RIF(trh);
250 				riflen = (ntohs(trrif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
251 			}
252 			bcopy((caddr_t)edst, (caddr_t)trh->token_dhost,
253 			    sizeof (edst));
254 			bcopy(LLADDR(ifp->if_sadl), (caddr_t)trh->token_shost,
255 			    sizeof(trh->token_shost));
256 			if (riflen != 0)
257 				trh->token_shost[0] |= TOKEN_RI_PRESENT;
258 /*
259  * compare (m->m_data - m->m_pktdat) with (sizeof(struct token_header) + riflen + ...
260  */
261 			m->m_len += (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
262 			m->m_data -= (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
263 			m->m_pkthdr.len += (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
264 			goto send;
265 		}
266 		break;
267 #endif /* 0 */
268 #endif
269 #ifdef NS
270 	case AF_NS:
271 		etype = htons(ETHERTYPE_NS);
272 		bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
273 		    (caddr_t)edst, sizeof (edst));
274 		if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
275 			return (looutput(ifp, m, dst, rt));
276 		/* If broadcasting on a simplex interface, loopback a copy. */
277 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
278 			mcopy = m_copy(m, 0, (int)M_COPYALL);
279 		break;
280 #endif
281 #ifdef	ISO
282 	case AF_ISO: {
283 		int	snpalen;
284 		struct	llc *l;
285 		struct sockaddr_dl *sdl;
286 
287 		if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
288 		    sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
289 			bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
290 		}
291 		else if ((error =
292 			    iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
293 					    (char *)edst, &snpalen)))
294 			goto bad; /* Not resolved */
295 		/* If broadcasting on a simplex interface, loopback a copy. */
296 		if (*edst & 1)
297 			m->m_flags |= (M_BCAST|M_MCAST);
298 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
299 		    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
300 			M_PREPEND(mcopy, sizeof (*trh), M_DONTWAIT);
301 			if (mcopy) {
302 				trh = mtod(mcopy, struct token_header *);
303 				bcopy((caddr_t)edst,
304 				    (caddr_t)trh->token_dhost, sizeof (edst));
305 				bcopy(LLADDR(ifp->if_sadl),
306 				    (caddr_t)trh->token_shost, sizeof (edst));
307 			}
308 		}
309 		M_PREPEND(m, 3, M_DONTWAIT);
310 		if (m == NULL)
311 			return (0);
312 		etype = 0;
313 		l = mtod(m, struct llc *);
314 		l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
315 		l->llc_control = LLC_UI;
316 #if defined(__FreeBSD__)
317 		IFDEBUG(D_ETHER)
318 			int i;
319 			printf("token_output: sending pkt to: ");
320 			for (i=0; i < ISO88025_ADDR_LEN; i++)
321 				printf("%x ", edst[i] & 0xff);
322 			printf("\n");
323 		ENDDEBUG
324 #endif
325 		} break;
326 #endif /* ISO */
327 #ifdef	LLC
328 /*	case AF_NSAP: */
329 	case AF_CCITT: {
330 		struct sockaddr_dl *sdl =
331 		    (struct sockaddr_dl *) rt -> rt_gateway;
332 
333 		if (sdl && sdl->sdl_family == AF_LINK
334 		    && sdl->sdl_alen > 0) {
335 			bcopy(LLADDR(sdl), (char *)edst, sizeof(edst));
336 		}
337 		else {
338 			/* Not a link interface ? Funny ... */
339 			goto bad;
340 		}
341 		if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
342 		    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
343 			M_PREPEND(mcopy, sizeof (*trh), M_DONTWAIT);
344 			if (mcopy) {
345 				trh = mtod(mcopy, struct token_header *);
346 				bcopy((caddr_t)edst,
347 				    (caddr_t)trh->token_dhost, sizeof (edst));
348 				bcopy(LLADDR(ifp->if_sadl),
349 				    (caddr_t)trh->token_shost, sizeof (edst));
350 			}
351 		}
352 		etype = 0;
353 #ifdef LLC_DEBUG
354 		{
355 			int i;
356 			struct llc *l = mtod(m, struct llc *);
357 
358 			printf("token_output: sending LLC2 pkt to: ");
359 			for (i=0; i < ISO88025_ADDR_LEN; i++)
360 				printf("%x ", edst[i] & 0xff);
361 			printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
362 			    etype & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
363 			    l->llc_control & 0xff);
364 
365 		}
366 #endif /* LLC_DEBUG */
367 		}
368 		break;
369 #endif /* LLC */
370 
371 	case AF_UNSPEC:
372 	{
373 		struct ether_header *eh;
374 		eh = (struct ether_header *)dst->sa_data;
375 		bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
376 		if (*edst & 1)
377 			m->m_flags |= (M_BCAST|M_MCAST);
378 		etype = TYPEHTONS(eh->ether_type);
379 		if (m->m_flags & M_BCAST) {
380 			if (ifp->if_flags & IFF_LINK0) {
381 				if (ifp->if_flags & IFF_LINK1)
382 					bcastrif.tr_rcf = htons(RCF_ALLROUTES);
383 				else
384 					bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
385 				rif = &bcastrif;
386 				riflen = sizeof(bcastrif.tr_rcf);
387 			}
388 		}
389 		break;
390 	}
391 
392 	default:
393 		printf("%s: can't handle af%d\n", ifp->if_xname,
394 		    dst->sa_family);
395 		senderr(EAFNOSUPPORT);
396 	}
397 
398 
399 	if (mcopy)
400 		(void) looutput(ifp, mcopy, dst, rt);
401 	if (etype != 0) {
402 		struct llc *l;
403 		M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
404 		if (m == 0)
405 			senderr(ENOBUFS);
406 		l = mtod(m, struct llc *);
407 		l->llc_control = LLC_UI;
408 		l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
409 		l->llc_snap.org_code[0] = l->llc_snap.org_code[1] =
410 		    l->llc_snap.org_code[2] = 0;
411 		bcopy((caddr_t) &etype, (caddr_t) &l->llc_snap.ether_type,
412 		    sizeof(u_short));
413 	}
414 
415 	/*
416 	 * Add local net header.  If no space in first mbuf,
417 	 * allocate another.
418 	 */
419 
420 	M_PREPEND(m, (riflen + sizeof (*trh)), M_DONTWAIT);
421 	if (m == 0)
422 		senderr(ENOBUFS);
423 	trh = mtod(m, struct token_header *);
424 	trh->token_ac = TOKEN_AC;
425 	trh->token_fc = TOKEN_FC;
426 	bcopy((caddr_t)edst, (caddr_t)trh->token_dhost, sizeof (edst));
427 	bcopy((caddr_t)ac->ac_enaddr, (caddr_t)trh->token_shost,
428 	    sizeof(trh->token_shost));
429 
430 	if (riflen != 0) {
431 		struct token_rif *trrif;
432 
433 		trh->token_shost[0] |= TOKEN_RI_PRESENT;
434 		trrif = TOKEN_RIF(trh);
435 		bcopy(rif, trrif, riflen);
436 	}
437 #if 0
438 send:
439 #endif /* 0 */
440 
441 	mflags = m->m_flags;
442 	len = m->m_pkthdr.len;
443 	s = splimp();
444 	/*
445 	 * Queue message on interface, and start output if interface
446 	 * not yet active.
447 	 */
448 	IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
449 	if (error) {
450 		/* mbuf is already freed */
451 		splx(s);
452 		return (error);
453 	}
454 	ifp->if_obytes += len;
455 	if (mflags & M_MCAST)
456 		ifp->if_omcasts++;
457 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
458 		(*ifp->if_start)(ifp);
459 	splx(s);
460 	return (error);
461 
462 bad:
463 	if (m)
464 		m_freem(m);
465 	return (error);
466 }
467 
468 /*
469  * Process a received token ring packet;
470  * the packet is in the mbuf chain m with
471  * the token ring header.
472  */
473 void
token_input(ifp,m)474 token_input(ifp, m)
475 	struct ifnet *ifp;
476 	struct mbuf *m;
477 {
478 	struct ifqueue *inq;
479 	struct llc *l;
480 	struct token_header *trh;
481 	int s, lan_hdr_len;
482 
483 	if ((ifp->if_flags & IFF_UP) == 0) {
484 		m_freem(m);
485 		return;
486 	}
487 
488 	trh = mtod(m, struct token_header *);
489 
490 	ifp->if_ibytes += m->m_pkthdr.len;
491 	if (bcmp((caddr_t)tokenbroadcastaddr, (caddr_t)trh->token_dhost,
492 	    sizeof(tokenbroadcastaddr)) == 0)
493 		m->m_flags |= M_BCAST;
494 	else if (trh->token_dhost[0] & 1)
495 		m->m_flags |= M_MCAST;
496 	if (m->m_flags & (M_BCAST|M_MCAST))
497 		ifp->if_imcasts++;
498 
499 	/* Skip past the Token Ring header and RIF. */
500 	lan_hdr_len = sizeof(struct token_header);
501 	if (trh->token_shost[0] & TOKEN_RI_PRESENT) {
502 		struct token_rif *trrif;
503 
504 		trrif = TOKEN_RIF(trh);
505 		lan_hdr_len += (ntohs(trrif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
506 	}
507 	m_adj(m, lan_hdr_len);
508 
509 	l = mtod(m, struct llc *);
510 	switch (l->llc_dsap) {
511 #if defined(INET) || defined(NS) || defined(DECNET)
512 	case LLC_SNAP_LSAP:
513 	{
514 		u_int16_t etype;
515 		if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
516 			goto dropanyway;
517 		if (l->llc_snap.org_code[0] != 0 ||
518 		    l->llc_snap.org_code[1] != 0 ||
519 		    l->llc_snap.org_code[2] != 0)
520 			goto dropanyway;
521 		etype = ntohs(l->llc_snap.ether_type);
522 		m_adj(m, LLC_SNAPFRAMELEN);
523 		switch (etype) {
524 #ifdef INET
525 		case ETHERTYPE_IP:
526 			schednetisr(NETISR_IP);
527 			inq = &ipintrq;
528 			break;
529 
530 		case ETHERTYPE_ARP:
531 			schednetisr(NETISR_ARP);
532 			inq = &arpintrq;
533 			break;
534 #endif
535 #ifdef NS
536 		case ETHERTYPE_NS:
537 			schednetisr(NETISR_NS);
538 			inq = &nsintrq;
539 			break;
540 #endif
541 #ifdef DECNET
542 		case ETHERTYPE_DECNET:
543 			schednetisr(NETISR_DECNET);
544 			inq = &decnetintrq;
545 			break;
546 #endif
547 		default:
548 			/*
549 			printf("token_input: unknown protocol 0x%x\n", etype);
550 			*/
551 			ifp->if_noproto++;
552 			goto dropanyway;
553 		}
554 		break;
555 	}
556 #endif /* INET || NS */
557 #ifdef	ISO
558 	case LLC_ISO_LSAP:
559 		switch (l->llc_control) {
560 		case LLC_UI:
561 			/* LLC_UI_P forbidden in class 1 service */
562 			if ((l->llc_dsap == LLC_ISO_LSAP) &&
563 			    (l->llc_ssap == LLC_ISO_LSAP)) {
564 				/* LSAP for ISO */
565 				m->m_data += 3;		/* XXX */
566 				m->m_len -= 3;		/* XXX */
567 				m->m_pkthdr.len -= 3;	/* XXX */
568 				M_PREPEND(m, sizeof *trh, M_DONTWAIT);
569 				if (m == 0)
570 					return;
571 				*mtod(m, struct token_header *) = *trh;
572 #if defined(__FreeBSD__)
573 				IFDEBUG(D_ETHER)
574 					printf("clnp packet");
575 				ENDDEBUG
576 #endif
577 				schednetisr(NETISR_ISO);
578 				inq = &clnlintrq;
579 				break;
580 			}
581 			goto dropanyway;
582 
583 		case LLC_XID:
584 		case LLC_XID_P:
585 			if(m->m_len < ISO88025_ADDR_LEN)
586 				goto dropanyway;
587 			l->llc_window = 0;
588 			l->llc_fid = 9;
589 			l->llc_class = 1;
590 			l->llc_dsap = l->llc_ssap = 0;
591 			/* Fall through to */
592 		case LLC_TEST:
593 		case LLC_TEST_P:
594 		{
595 			struct sockaddr sa;
596 			struct ether_header *eh;
597 			int i;
598 			u_char c = l->llc_dsap;
599 
600 			l->llc_dsap = l->llc_ssap;
601 			l->llc_ssap = c;
602 			if (m->m_flags & (M_BCAST | M_MCAST))
603 				bcopy(LLADDR(ifp->if_sadl),
604 				    (caddr_t)trh->token_dhost,
605 				    ISO88025_ADDR_LEN);
606 			sa.sa_family = AF_UNSPEC;
607 			sa.sa_len = sizeof(sa);
608 			eh = (struct ether_header *)sa.sa_data;
609 			for (i = 0; i < ISO88025_ADDR_LEN; i++) {
610 				eh->ether_shost[i] = c = trh->token_dhost[i];
611 				eh->ether_dhost[i] =
612 				    eh->ether_dhost[i] = trh->token_shost[i];
613 				eh->ether_shost[i] = c;
614 			}
615 			eh->ether_type = 0;
616 			ifp->if_output(ifp, m, &sa, NULL);
617 			return;
618 		}
619 		default:
620 			m_freem(m);
621 			return;
622 		}
623 		break;
624 #endif /* ISO */
625 #ifdef LLC
626 	case LLC_X25_LSAP:
627 	{
628 /*
629  * XXX check for source routing info ? (sizeof(struct sdl_hdr) and
630  * ISO88025_ADDR_LEN)
631  */
632 		M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
633 		if (m == 0)
634 			return;
635 		if (!sdl_sethdrif(ifp, trh->token_shost, LLC_X25_LSAP,
636 				    trh->token_dhost, LLC_X25_LSAP,
637 				    ISO88025_ADDR_LEN,
638 				    mtod(m, struct sdl_hdr *)))
639 			panic("ETHER cons addr failure");
640 		mtod(m, struct sdl_hdr *)->sdlhdr_len =
641 		    m->m_pkthdr.len - sizeof(struct sdl_hdr);
642 #ifdef LLC_DEBUG
643 		printf("llc packet\n");
644 #endif /* LLC_DEBUG */
645 		schednetisr(NETISR_CCITT);
646 		inq = &llcintrq;
647 		break;
648 	}
649 #endif /* LLC */
650 
651 	default:
652 		/* printf("token_input: unknown dsap 0x%x\n", l->llc_dsap); */
653 		ifp->if_noproto++;
654 	dropanyway:
655 		m_freem(m);
656 		return;
657 	}
658 
659 	s = splimp();
660 	IF_INPUT_ENQUEUE(inq, m);
661 	splx(s);
662 }
663 
664 /*
665  * Perform common duties while attaching to interface list
666  */
667 void
token_ifattach(ifp)668 token_ifattach(ifp)
669 	struct ifnet *ifp;
670 {
671 	ifp->if_type = IFT_ISO88025;
672 	ifp->if_addrlen = ISO88025_ADDR_LEN;
673 	ifp->if_hdrlen = 14;
674 	ifp->if_mtu = ISO88025_MTU;
675 	ifp->if_output = token_output;
676 #ifdef IFF_NOTRAILERS
677 	ifp->if_flags |= IFF_NOTRAILERS;
678 #endif
679 	if_alloc_sadl(ifp);
680 	bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
681 	    LLADDR(ifp->if_sadl), ifp->if_addrlen);
682 }
683