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