No empty .Rs/.Re
[netbsd-mini2440.git] / sys / net / if_tokensubr.c
blobd2a643dc3591d92aca30e3288a331f2b85fc8e1e
1 /* $NetBSD: if_tokensubr.c,v 1.57 2009/04/18 14:58:05 tsutsui Exp $ */
3 /*
4 * Copyright (c) 1982, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
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 University 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.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
31 * from: NetBSD: if_fddisubr.c,v 1.2 1995/08/19 04:35:29 cgd Exp
35 * Copyright (c) 1997-1999 The NetBSD Foundation, Inc.
36 * All rights reserved.
38 * This code is derived from software contributed to The NetBSD Foundation
39 * by Onno van der Linden.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
50 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
51 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
54 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 * POSSIBILITY OF SUCH DAMAGE.
64 * Copyright (c) 1995
65 * Matt Thomas. All rights reserved.
67 * Redistribution and use in source and binary forms, with or without
68 * modification, are permitted provided that the following conditions
69 * are met:
70 * 1. Redistributions of source code must retain the above copyright
71 * notice, this list of conditions and the following disclaimer.
72 * 2. Redistributions in binary form must reproduce the above copyright
73 * notice, this list of conditions and the following disclaimer in the
74 * documentation and/or other materials provided with the distribution.
75 * 3. The names of its contributors may not be used to endorse or promote
76 * products derived from this software without specific prior written
77 * permission.
79 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
80 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
81 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
82 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
83 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
84 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
85 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
86 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
87 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
88 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
89 * SUCH DAMAGE.
91 * from: NetBSD: if_fddisubr.c,v 1.2 1995/08/19 04:35:29 cgd Exp
94 #include <sys/cdefs.h>
95 __KERNEL_RCSID(0, "$NetBSD: if_tokensubr.c,v 1.57 2009/04/18 14:58:05 tsutsui Exp $");
97 #include "opt_inet.h"
98 #include "opt_atalk.h"
99 #include "opt_iso.h"
100 #include "opt_gateway.h"
102 #include "bpfilter.h"
104 #include <sys/param.h>
105 #include <sys/systm.h>
106 #include <sys/kernel.h>
107 #include <sys/malloc.h>
108 #include <sys/mbuf.h>
109 #include <sys/protosw.h>
110 #include <sys/socket.h>
111 #include <sys/ioctl.h>
112 #include <sys/errno.h>
113 #include <sys/syslog.h>
115 #include <sys/cpu.h>
117 #include <net/if.h>
118 #include <net/netisr.h>
119 #include <net/route.h>
120 #include <net/if_llc.h>
121 #include <net/if_dl.h>
122 #include <net/if_types.h>
124 #if NBPFILTER > 0
125 #include <net/bpf.h>
126 #endif
128 #include <net/if_ether.h>
129 #include <net/if_token.h>
131 #include "carp.h"
132 #if NCARP > 0
133 #include <netinet/ip_carp.h>
134 #endif
136 #ifdef INET
137 #include <netinet/in.h>
138 #include <netinet/in_var.h>
139 #include <netinet/if_inarp.h>
140 #endif
143 #ifdef DECNET
144 #include <netdnet/dn.h>
145 #endif
147 #ifdef ISO
148 #include <netiso/argo_debug.h>
149 #include <netiso/iso.h>
150 #include <netiso/iso_var.h>
151 #include <netiso/iso_snpac.h>
152 #endif
154 #include "bpfilter.h"
156 #define senderr(e) { error = (e); goto bad;}
158 #if defined(__bsdi__) || defined(__NetBSD__)
159 #define RTALLOC1(a, b) rtalloc1(a, b)
160 #define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e)
161 #define TYPEHTONS(t) (t)
162 #elif defined(__FreeBSD__)
163 #define RTALLOC1(a, b) rtalloc1(a, b, 0UL)
164 #define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e, f)
165 #define TYPEHTONS(t) (htons(t))
166 #endif
168 #define RCF_ALLROUTES (2 << 8) | TOKEN_RCF_FRAME2 | TOKEN_RCF_BROADCAST_ALL
169 #define RCF_SINGLEROUTE (2 << 8) | TOKEN_RCF_FRAME2 | TOKEN_RCF_BROADCAST_SINGLE
171 static int token_output(struct ifnet *, struct mbuf *,
172 const struct sockaddr *, struct rtentry *);
173 static void token_input(struct ifnet *, struct mbuf *);
176 * Token Ring output routine.
177 * Encapsulate a packet of type family for the local net.
178 * Assumes that ifp is actually pointer to arphdr structure.
179 * XXX route info has to go into the same mbuf as the header
181 static int
182 token_output(struct ifnet *ifp0, struct mbuf *m0, const struct sockaddr *dst,
183 struct rtentry *rt0)
185 uint16_t etype;
186 int error = 0;
187 u_char edst[ISO88025_ADDR_LEN];
188 struct mbuf *m = m0;
189 struct rtentry *rt;
190 struct mbuf *mcopy = NULL;
191 struct token_header *trh;
192 #ifdef INET
193 struct arphdr *ah = (struct arphdr *)ifp0;
194 #endif /* INET */
195 struct token_rif *rif = NULL;
196 struct token_rif bcastrif;
197 struct ifnet *ifp = ifp0;
198 size_t riflen = 0;
199 ALTQ_DECL(struct altq_pktattr pktattr;)
201 #if NCARP > 0
202 if (ifp->if_type == IFT_CARP) {
203 struct ifaddr *ifa;
205 /* loop back if this is going to the carp interface */
206 if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP &&
207 (ifa = ifa_ifwithaddr(dst)) != NULL &&
208 ifa->ifa_ifp == ifp0)
209 return (looutput(ifp0, m, dst, rt0));
211 ifp = ifp->if_carpdev;
212 ah = (struct arphdr *)ifp;
214 if ((ifp0->if_flags & (IFF_UP|IFF_RUNNING)) !=
215 (IFF_UP|IFF_RUNNING))
216 senderr(ENETDOWN);
218 #endif /* NCARP > 0 */
220 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
221 senderr(ENETDOWN);
222 if ((rt = rt0)) {
223 if ((rt->rt_flags & RTF_UP) == 0) {
224 if ((rt0 = rt = RTALLOC1(dst, 1)))
225 rt->rt_refcnt--;
226 else
227 senderr(EHOSTUNREACH);
229 if (rt->rt_flags & RTF_GATEWAY) {
230 if (rt->rt_gwroute == 0)
231 goto lookup;
232 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
233 rtfree(rt); rt = rt0;
234 lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 1);
235 if ((rt = rt->rt_gwroute) == 0)
236 senderr(EHOSTUNREACH);
239 if (rt->rt_flags & RTF_REJECT)
240 if (rt->rt_rmx.rmx_expire == 0 ||
241 time_second < rt->rt_rmx.rmx_expire)
242 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
246 * If the queueing discipline needs packet classification,
247 * do it before prepending link headers.
249 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
251 switch (dst->sa_family) {
253 #ifdef INET
254 case AF_INET:
255 if (m->m_flags & M_BCAST) {
256 if (ifp->if_flags & IFF_LINK0) {
257 if (ifp->if_flags & IFF_LINK1)
258 bcastrif.tr_rcf = htons(RCF_ALLROUTES);
259 else
260 bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
261 rif = &bcastrif;
262 riflen = sizeof(rif->tr_rcf);
264 memcpy(edst, tokenbroadcastaddr, sizeof(edst));
267 * XXX m->m_flags & M_MCAST IEEE802_MAP_IP_MULTICAST ??
269 else {
270 if (!ARPRESOLVE(ifp, rt, m, dst, edst, rt0))
271 return (0); /* if not yet resolved */
272 rif = TOKEN_RIF((struct llinfo_arp *) rt->rt_llinfo);
273 riflen = (ntohs(rif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
275 /* If broadcasting on a simplex interface, loopback a copy. */
276 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
277 mcopy = m_copy(m, 0, (int)M_COPYALL);
278 etype = htons(ETHERTYPE_IP);
279 break;
280 case AF_ARP:
282 * XXX source routing, assume m->m_data contains the useful stuff
284 ah = mtod(m, struct arphdr *);
285 ah->ar_hrd = htons(ARPHRD_IEEE802);
287 switch (ntohs(ah->ar_op)) {
288 case ARPOP_REVREQUEST:
289 case ARPOP_REVREPLY:
290 etype = htons(ETHERTYPE_REVARP);
291 break;
293 case ARPOP_REQUEST:
294 case ARPOP_REPLY:
295 default:
296 etype = htons(ETHERTYPE_ARP);
299 if (m->m_flags & M_BCAST) {
300 if (ifp->if_flags & IFF_LINK0) {
301 if (ifp->if_flags & IFF_LINK1)
302 bcastrif.tr_rcf = htons(RCF_ALLROUTES);
303 else
304 bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
305 rif = &bcastrif;
306 riflen = sizeof(rif->tr_rcf);
308 memcpy(edst, tokenbroadcastaddr, sizeof(edst));
310 else {
311 void *tha = ar_tha(ah);
312 if (tha == NULL)
313 return 0;
314 memcpy(edst, tha, sizeof(edst));
315 trh = (struct token_header *)M_TRHSTART(m);
316 trh->token_ac = TOKEN_AC;
317 trh->token_fc = TOKEN_FC;
318 if (trh->token_shost[0] & TOKEN_RI_PRESENT) {
319 struct token_rif *trrif;
321 trrif = TOKEN_RIF(trh);
322 riflen = (ntohs(trrif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
324 memcpy((void *)trh->token_dhost, (void *)edst,
325 sizeof (edst));
326 memcpy((void *)trh->token_shost, CLLADDR(ifp->if_sadl),
327 sizeof(trh->token_shost));
328 if (riflen != 0)
329 trh->token_shost[0] |= TOKEN_RI_PRESENT;
331 * compare (m->m_data - m->m_pktdat) with (sizeof(struct token_header) + riflen + ...
333 m->m_len += (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
334 m->m_data -= (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
335 m->m_pkthdr.len += (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
336 goto send;
338 break;
339 #endif
340 #ifdef ISO
341 case AF_ISO: {
342 int snpalen;
343 struct llc *l;
344 const struct sockaddr_dl *sdl;
346 if (rt && (sdl = satocsdl(rt->rt_gateway)) &&
347 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
348 memcpy(edst, CLLADDR(sdl), sizeof(edst));
350 else if ((error = iso_snparesolve(ifp,
351 (const struct sockaddr_iso *)dst, (char *)edst, &snpalen)))
352 goto bad; /* Not resolved */
353 /* If broadcasting on a simplex interface, loopback a copy. */
354 if (*edst & 1)
355 m->m_flags |= (M_BCAST|M_MCAST);
356 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
357 (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
358 M_PREPEND(mcopy, sizeof (*trh), M_DONTWAIT);
359 if (mcopy) {
360 trh = mtod(mcopy, struct token_header *);
361 bcopy((void *)edst,
362 (void *)trh->token_dhost, sizeof (edst));
363 bcopy(CLLADDR(ifp->if_sadl),
364 (void *)trh->token_shost, sizeof (edst));
367 M_PREPEND(m, 3, M_DONTWAIT);
368 if (m == NULL)
369 return (0);
370 etype = 0;
371 l = mtod(m, struct llc *);
372 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
373 l->llc_control = LLC_UI;
374 #if defined(__FreeBSD__)
375 IFDEBUG(D_ETHER)
376 int i;
377 printf("token_output: sending pkt to: ");
378 for (i=0; i < ISO88025_ADDR_LEN; i++)
379 printf("%x ", edst[i] & 0xff);
380 printf("\n");
381 ENDDEBUG
382 #endif
383 } break;
384 #endif /* ISO */
386 case AF_UNSPEC:
388 const struct ether_header *eh;
389 eh = (const struct ether_header *)dst->sa_data;
390 memcpy(edst, eh->ether_dhost, sizeof(edst));
391 if (*edst & 1)
392 m->m_flags |= (M_BCAST|M_MCAST);
393 etype = TYPEHTONS(eh->ether_type);
394 if (m->m_flags & M_BCAST) {
395 if (ifp->if_flags & IFF_LINK0) {
396 if (ifp->if_flags & IFF_LINK1)
397 bcastrif.tr_rcf = htons(RCF_ALLROUTES);
398 else
399 bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
400 rif = &bcastrif;
401 riflen = sizeof(bcastrif.tr_rcf);
404 break;
407 default:
408 printf("%s: can't handle af%d\n", ifp->if_xname,
409 dst->sa_family);
410 senderr(EAFNOSUPPORT);
414 if (mcopy)
415 (void) looutput(ifp, mcopy, dst, rt);
416 if (etype != 0) {
417 struct llc *l;
418 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
419 if (m == 0)
420 senderr(ENOBUFS);
421 l = mtod(m, struct llc *);
422 l->llc_control = LLC_UI;
423 l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
424 l->llc_snap.org_code[0] = l->llc_snap.org_code[1] =
425 l->llc_snap.org_code[2] = 0;
426 memcpy((void *) &l->llc_snap.ether_type, (void *) &etype,
427 sizeof(uint16_t));
431 * Add local net header. If no space in first mbuf,
432 * allocate another.
435 M_PREPEND(m, (riflen + sizeof (*trh)), M_DONTWAIT);
436 if (m == 0)
437 senderr(ENOBUFS);
438 trh = mtod(m, struct token_header *);
439 trh->token_ac = TOKEN_AC;
440 trh->token_fc = TOKEN_FC;
441 memcpy((void *)trh->token_dhost, (void *)edst, sizeof (edst));
442 memcpy((void *)trh->token_shost, CLLADDR(ifp->if_sadl),
443 sizeof(trh->token_shost));
445 if (riflen != 0) {
446 struct token_rif *trrif;
448 trh->token_shost[0] |= TOKEN_RI_PRESENT;
449 trrif = TOKEN_RIF(trh);
450 memcpy(trrif, rif, riflen);
452 #ifdef INET
453 send:
454 #endif
456 #if NCARP > 0
457 if (ifp0 != ifp && ifp0->if_type == IFT_CARP) {
458 memcpy((void *)trh->token_shost, CLLADDR(ifp0->if_sadl),
459 sizeof(trh->token_shost));
461 #endif /* NCARP > 0 */
463 return ifq_enqueue(ifp, m ALTQ_COMMA ALTQ_DECL(&pktattr));
464 bad:
465 if (m)
466 m_freem(m);
467 return (error);
471 * Process a received token ring packet;
472 * the packet is in the mbuf chain m with
473 * the token ring header.
475 static void
476 token_input(struct ifnet *ifp, struct mbuf *m)
478 struct ifqueue *inq;
479 struct llc *l;
480 struct token_header *trh;
481 int s, lan_hdr_len;
483 if ((ifp->if_flags & IFF_UP) == 0) {
484 m_freem(m);
485 return;
488 trh = mtod(m, struct token_header *);
490 ifp->if_ibytes += m->m_pkthdr.len;
491 if (memcmp(tokenbroadcastaddr, 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++;
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;
504 trrif = TOKEN_RIF(trh);
505 lan_hdr_len += (ntohs(trrif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
508 l = (struct llc *)(mtod(m, uint8_t *) + lan_hdr_len);
510 switch (l->llc_dsap) {
511 #if defined(INET) || defined(NS) || defined(DECNET)
512 case LLC_SNAP_LSAP:
514 uint16_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, lan_hdr_len + LLC_SNAPFRAMELEN);
523 #if NCARP > 0
524 if (ifp->if_carp && ifp->if_type != IFT_CARP &&
525 (carp_input(m, (uint8_t *)&trh->token_shost,
526 (uint8_t *)&trh->token_dhost, l->llc_snap.ether_type) == 0))
527 return;
528 #endif /* NCARP > 0 */
530 switch (etype) {
531 #ifdef INET
532 case ETHERTYPE_IP:
533 schednetisr(NETISR_IP);
534 inq = &ipintrq;
535 break;
537 case ETHERTYPE_ARP:
538 schednetisr(NETISR_ARP);
539 inq = &arpintrq;
540 break;
541 #endif
542 #ifdef DECNET
543 case ETHERTYPE_DECNET:
544 schednetisr(NETISR_DECNET);
545 inq = &decnetintrq;
546 break;
547 #endif
548 default:
550 printf("token_input: unknown protocol 0x%x\n", etype);
552 ifp->if_noproto++;
553 goto dropanyway;
555 break;
557 #endif /* INET || NS || DECNET */
558 #ifdef ISO
559 case LLC_ISO_LSAP:
560 switch (l->llc_control) {
561 case LLC_UI:
562 /* LLC_UI_P forbidden in class 1 service */
563 if ((l->llc_dsap == LLC_ISO_LSAP) &&
564 (l->llc_ssap == LLC_ISO_LSAP)) {
566 #if defined(__FreeBSD__)
567 IFDEBUG(D_ETHER)
568 printf("clnp packet");
569 ENDDEBUG
570 #endif
571 schednetisr(NETISR_ISO);
572 inq = &clnlintrq;
573 break;
575 goto dropanyway;
577 case LLC_XID:
578 case LLC_XID_P:
579 if(m->m_len < LLC_XID_BASIC_MINLEN + lan_hdr_len)
580 goto dropanyway;
581 l->llc_window = 0;
582 l->llc_fid = LLC_XID_FORMAT_BASIC;
583 l->llc_class = LLC_XID_CLASS_I;
584 l->llc_dsap = l->llc_ssap = 0;
585 /* Fall through to */
586 case LLC_TEST:
587 case LLC_TEST_P:
589 struct sockaddr sa;
590 struct ether_header *eh;
591 int i;
592 u_char c = l->llc_dsap;
594 l->llc_dsap = l->llc_ssap;
595 l->llc_ssap = c;
596 if (m->m_flags & (M_BCAST | M_MCAST))
597 bcopy(CLLADDR(ifp->if_sadl),
598 (void *)trh->token_dhost,
599 ISO88025_ADDR_LEN);
600 sa.sa_family = AF_UNSPEC;
601 sa.sa_len = sizeof(sa);
602 eh = (struct ether_header *)sa.sa_data;
603 for (i = 0; i < ISO88025_ADDR_LEN; i++) {
604 eh->ether_shost[i] = c = trh->token_dhost[i];
605 eh->ether_dhost[i] =
606 eh->ether_dhost[i] = trh->token_shost[i];
607 eh->ether_shost[i] = c;
609 eh->ether_type = 0;
610 m_adj(m, lan_hdr_len);
611 ifp->if_output(ifp, m, &sa, NULL);
612 return;
614 default:
615 m_freem(m);
616 return;
618 break;
619 #endif /* ISO */
621 default:
622 /* printf("token_input: unknown dsap 0x%x\n", l->llc_dsap); */
623 ifp->if_noproto++;
624 #if defined(INET) || defined(NS) || defined(DECNET) || defined(ISO)
625 dropanyway:
626 #endif
627 m_freem(m);
628 return;
631 s = splnet();
632 if (IF_QFULL(inq)) {
633 IF_DROP(inq);
634 m_freem(m);
636 else
637 IF_ENQUEUE(inq, m);
638 splx(s);
642 * Perform common duties while attaching to interface list
644 void
645 token_ifattach(struct ifnet *ifp, void *lla)
648 ifp->if_type = IFT_ISO88025;
649 ifp->if_hdrlen = 14;
650 ifp->if_dlt = DLT_IEEE802;
651 ifp->if_mtu = ISO88025_MTU;
652 ifp->if_output = token_output;
653 ifp->if_input = token_input;
654 ifp->if_broadcastaddr = tokenbroadcastaddr;
655 #ifdef IFF_NOTRAILERS
656 ifp->if_flags |= IFF_NOTRAILERS;
657 #endif
659 if_set_sadl(ifp, lla, ISO88025_ADDR_LEN, true);
661 #if NBPFILTER > 0
662 bpfattach(ifp, DLT_IEEE802, sizeof(struct token_header));
663 #endif
666 void
667 token_ifdetach(struct ifnet *ifp)
670 #if NBPFILTER > 0
671 bpfdetach(ifp);
672 #endif
673 #if 0 /* done in if_detach() */
674 if_free_sadl(ifp);
675 #endif