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