|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1989, 1993
28: * The Regents of the University of California. All rights reserved.
29: *
30: * The NEXTSTEP Software License Agreement specifies the terms
31: * and conditions for redistribution.
32: *
33: */
34:
35: #include <sys/param.h>
36: #include <sys/systm.h>
37: #include <sys/kernel.h>
38: #include <sys/malloc.h>
39: #include <sys/mbuf.h>
40: #include <sys/protosw.h>
41: #include <sys/socket.h>
42: #include <sys/ioctl.h>
43: #include <sys/errno.h>
44: #include <sys/syslog.h>
45:
46: #include <machine/cpu.h>
47:
48: #include <net/if.h>
49: #include <net/netisr.h>
50: #include <net/route.h>
51: #include <net/if_llc.h>
52: #include <net/if_dl.h>
53: #include <net/if_types.h>
54:
55: #if INET
56: #include <netinet/in.h>
57: #include <netinet/in_var.h>
58: #endif
59: #include <netinet/if_ether.h>
60: #include <netinet/if_fddi.h>
61:
62: #if NS
63: #include <netns/ns.h>
64: #include <netns/ns_if.h>
65: #endif
66:
67: #if DECNET
68: #include <netdnet/dn.h>
69: #endif
70:
71: #if defined(ISO) && notyet
72: #include <netiso/argo_debug.h>
73: #include <netiso/iso.h>
74: #include <netiso/iso_var.h>
75: #include <netiso/iso_snpac.h>
76: #endif /* defined(ISO) && notyet */
77:
78: #include "bpfilter.h"
79:
80: #if LLC
81: #include <netccitt/dll.h>
82: #include <netccitt/llc_var.h>
83: #endif
84:
85: #if defined(LLC) && defined(CCITT)
86: extern struct ifqueue pkintrq;
87: #endif
88:
89: #define senderr(e) { error = (e); goto bad;}
90:
91: /*
92: * This really should be defined in if_llc.h but in case it isn't.
93: */
94: #ifndef llc_snap
95: #define llc_snap llc_un.type_snap
96: #endif
97:
98: /*
99: * FDDI output routine.
100: * Encapsulate a packet of type family for the local net.
101: * Use trailer local net encapsulation if enough data in first
102: * packet leaves a multiple of 512 bytes of data in remainder.
103: * Assumes that ifp is actually pointer to arpcom structure.
104: */
105: int
106: fddi_output(ifp, m0, dst, rt0)
107: register struct ifnet *ifp;
108: struct mbuf *m0;
109: struct sockaddr *dst;
110: struct rtentry *rt0;
111: {
112: short type;
113: int s, error = 0;
114: u_char edst[6];
115: register struct mbuf *m = m0;
116: register struct rtentry *rt;
117: struct mbuf *mcopy = (struct mbuf *)0;
118: register struct fddi_header *fh;
119: struct arpcom *ac = (struct arpcom *)ifp;
120:
121: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
122: senderr(ENETDOWN);
123: ifp->if_lastchange = time;
124: if (rt = rt0) {
125: if ((rt->rt_flags & RTF_UP) == 0) {
126: if (rt0 = rt = rtalloc1(dst, 1))
127: rt->rt_refcnt--;
128: else
129: senderr(EHOSTUNREACH);
130: }
131: if (rt->rt_flags & RTF_GATEWAY) {
132: if (rt->rt_gwroute == 0)
133: goto lookup;
134: if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
135: rtfree(rt); rt = rt0;
136: lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
137: if ((rt = rt->rt_gwroute) == 0)
138: senderr(EHOSTUNREACH);
139: }
140: }
141: if (rt->rt_flags & RTF_REJECT)
142: if (rt->rt_rmx.rmx_expire == 0 ||
143: time.tv_sec < rt->rt_rmx.rmx_expire)
144: senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
145: }
146: switch (dst->sa_family) {
147:
148: #if INET
149: case AF_INET:
150: if (!arpresolve(ac, rt, m, dst, edst))
151: return (0); /* if not yet resolved */
152: /* If broadcasting on a simplex interface, loopback a copy */
153: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
154: mcopy = m_copy(m, 0, (int)M_COPYALL);
155: type = ETHERTYPE_IP;
156: break;
157: #endif
158: #if NS
159: case AF_NS:
160: type = ETHERTYPE_NS;
161: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
162: (caddr_t)edst, sizeof (edst));
163: if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
164: return (looutput(ifp, m, dst, rt));
165: /* If broadcasting on a simplex interface, loopback a copy */
166: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
167: mcopy = m_copy(m, 0, (int)M_COPYALL);
168: break;
169: #endif
170: #if defined(ISO) && notyet
171: case AF_ISO: {
172: int snpalen;
173: struct llc *l;
174: register struct sockaddr_dl *sdl;
175:
176: if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
177: sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
178: bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
179: } else if (error =
180: iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
181: (char *)edst, &snpalen))
182: goto bad; /* Not Resolved */
183: /* If broadcasting on a simplex interface, loopback a copy */
184: if (*edst & 1)
185: m->m_flags |= (M_BCAST|M_MCAST);
186: if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
187: (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
188: M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT);
189: if (mcopy) {
190: fh = mtod(mcopy, struct fddi_header *);
191: bcopy((caddr_t)edst,
192: (caddr_t)fh->fddi_dhost, sizeof (edst));
193: bcopy((caddr_t)ac->ac_enaddr,
194: (caddr_t)fh->fddi_shost, sizeof (edst));
195: }
196: }
197: M_PREPEND(m, 3, M_DONTWAIT);
198: if (m == NULL)
199: return (0);
200: type = 0;
201: l = mtod(m, struct llc *);
202: l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
203: l->llc_control = LLC_UI;
204: IFDEBUG(D_ETHER)
205: int i;
206: printf("unoutput: sending pkt to: ");
207: for (i=0; i<6; i++)
208: printf("%x ", edst[i] & 0xff);
209: printf("\n");
210: ENDDEBUG
211: } break;
212: #endif /* defined(ISO) && notyet */
213: #if LLC
214: /* case AF_NSAP: */
215: case AF_CCITT: {
216: register struct sockaddr_dl *sdl =
217: (struct sockaddr_dl *) rt -> rt_gateway;
218:
219: if (sdl && sdl->sdl_family == AF_LINK
220: && sdl->sdl_alen > 0) {
221: bcopy(LLADDR(sdl), (char *)edst,
222: sizeof(edst));
223: } else goto bad; /* Not a link interface ? Funny ... */
224: if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
225: (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
226: M_PREPEND(mcopy, sizeof (*fh), M_DONTWAIT);
227: if (mcopy) {
228: fh = mtod(mcopy, struct fddi_header *);
229: bcopy((caddr_t)edst,
230: (caddr_t)fh->fddi_dhost, sizeof (edst));
231: bcopy((caddr_t)ac->ac_enaddr,
232: (caddr_t)fh->fddi_shost, sizeof (edst));
233: fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4;
234: }
235: }
236: type = 0;
237: #if LLC_DEBUG
238: {
239: int i;
240: register struct llc *l = mtod(m, struct llc *);
241:
242: printf("fddi_output: sending LLC2 pkt to: ");
243: for (i=0; i<6; i++)
244: printf("%x ", edst[i] & 0xff);
245: printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
246: type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
247: l->llc_control & 0xff);
248:
249: }
250: #endif /* LLC_DEBUG */
251: } break;
252: #endif /* LLC */
253:
254: case AF_UNSPEC:
255: {
256: struct ether_header *eh;
257: eh = (struct ether_header *)dst->sa_data;
258: (void)memcpy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
259: if (*edst & 1)
260: m->m_flags |= (M_BCAST|M_MCAST);
261: type = eh->ether_type;
262: break;
263: }
264:
265: #if NBPFILTER > 0
266: case AF_IMPLINK:
267: {
268: fh = mtod(m, struct fddi_header *);
269: error = EPROTONOSUPPORT;
270: switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) {
271: case FDDIFC_LLC_ASYNC: {
272: /* legal priorities are 0 through 7 */
273: if ((fh->fddi_fc & FDDIFC_Z) > 7)
274: goto bad;
275: break;
276: }
277: case FDDIFC_LLC_SYNC: {
278: /* FDDIFC_Z bits reserved, must be zero */
279: if (fh->fddi_fc & FDDIFC_Z)
280: goto bad;
281: break;
282: }
283: case FDDIFC_SMT: {
284: /* FDDIFC_Z bits must be non zero */
285: if ((fh->fddi_fc & FDDIFC_Z) == 0)
286: goto bad;
287: break;
288: }
289: default: {
290: /* anything else is too dangerous */
291: goto bad;
292: }
293: }
294: error = 0;
295: if (fh->fddi_dhost[0] & 1)
296: m->m_flags |= (M_BCAST|M_MCAST);
297: goto queue_it;
298: }
299: #endif
300: default:
301: printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
302: dst->sa_family);
303: senderr(EAFNOSUPPORT);
304: }
305:
306:
307: if (mcopy)
308: (void) looutput(ifp, mcopy, dst, rt);
309: if (type != 0) {
310: register struct llc *l;
311: M_PREPEND(m, sizeof (struct llc), M_DONTWAIT);
312: if (m == 0)
313: senderr(ENOBUFS);
314: l = mtod(m, struct llc *);
315: l->llc_control = LLC_UI;
316: l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
317: l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0;
318: type = ntohs(type);
319: (void)memcpy((caddr_t) &l->llc_snap.ether_type, (caddr_t) &type,
320: sizeof(u_short));
321: }
322: /*
323: * Add local net header. If no space in first mbuf,
324: * allocate another.
325: */
326: M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT);
327: if (m == 0)
328: senderr(ENOBUFS);
329: fh = mtod(m, struct fddi_header *);
330: fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4;
331: (void)memcpy((caddr_t)fh->fddi_dhost, (caddr_t)edst, sizeof (edst));
332: queue_it:
333: (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)ac->ac_enaddr,
334: sizeof(fh->fddi_shost));
335: s = splimp();
336: /*
337: * Queue message on interface, and start output if interface
338: * not yet active.
339: */
340: if (IF_QFULL(&ifp->if_snd)) {
341: IF_DROP(&ifp->if_snd);
342: splx(s);
343: senderr(ENOBUFS);
344: }
345: ifp->if_obytes += m->m_pkthdr.len;
346: IF_ENQUEUE(&ifp->if_snd, m);
347: if ((ifp->if_flags & IFF_OACTIVE) == 0)
348: (*ifp->if_start)(ifp);
349: splx(s);
350: if (m->m_flags & M_MCAST)
351: ifp->if_omcasts++;
352: return (error);
353:
354: bad:
355: if (m)
356: m_freem(m);
357: return (error);
358: }
359:
360: /*
361: * Process a received FDDI packet;
362: * the packet is in the mbuf chain m without
363: * the fddi header, which is provided separately.
364: */
365: void
366: fddi_input(ifp, fh, m)
367: struct ifnet *ifp;
368: register struct fddi_header *fh;
369: struct mbuf *m;
370: {
371: register struct ifqueue *inq;
372: register struct llc *l;
373: int s;
374:
375: if ((ifp->if_flags & IFF_UP) == 0) {
376: m_freem(m);
377: return;
378: }
379: ifp->if_lastchange = time;
380: ifp->if_ibytes += m->m_pkthdr.len + sizeof (*fh);
381: if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost,
382: sizeof(fddibroadcastaddr)) == 0)
383: m->m_flags |= M_BCAST;
384: else if (fh->fddi_dhost[0] & 1)
385: m->m_flags |= M_MCAST;
386: if (m->m_flags & (M_BCAST|M_MCAST))
387: ifp->if_imcasts++;
388:
389: l = mtod(m, struct llc *);
390: switch (l->llc_dsap) {
391: #if defined(INET) || defined(NS) || defined(DECNET)
392: case LLC_SNAP_LSAP:
393: {
394: unsigned fddi_type;
395: if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
396: goto dropanyway;
397: if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0)
398: goto dropanyway;
399: fddi_type = ntohs(l->llc_snap.ether_type);
400: m_adj(m, 8);
401: switch (fddi_type) {
402: #if INET
403: case ETHERTYPE_IP:
404: schednetisr(NETISR_IP);
405: inq = &ipintrq;
406: break;
407:
408: case ETHERTYPE_ARP:
409: schednetisr(NETISR_ARP);
410: inq = &arpintrq;
411: break;
412: #endif
413: #if NS
414: case ETHERTYPE_NS:
415: schednetisr(NETISR_NS);
416: inq = &nsintrq;
417: break;
418: #endif
419: #if DECNET
420: case ETHERTYPE_DECENT:
421: schednetisr(NETISR_DECNET);
422: inq = &decnetintrq;
423: break;
424: #endif
425: default:
426: printf("fddi_input: unknown protocol 0x%x\n", fddi_type);
427: ifp->if_noproto++;
428: goto dropanyway;
429: }
430: break;
431: }
432: #endif /* INET || NS */
433: #if defined(ISO) && notyet
434: case LLC_ISO_LSAP:
435: switch (l->llc_control) {
436: case LLC_UI:
437: /* LLC_UI_P forbidden in class 1 service */
438: if ((l->llc_dsap == LLC_ISO_LSAP) &&
439: (l->llc_ssap == LLC_ISO_LSAP)) {
440: /* LSAP for ISO */
441: m->m_data += 3; /* XXX */
442: m->m_len -= 3; /* XXX */
443: m->m_pkthdr.len -= 3; /* XXX */
444: M_PREPEND(m, sizeof *fh, M_DONTWAIT);
445: if (m == 0)
446: return;
447: *mtod(m, struct fddi_header *) = *fh;
448: IFDEBUG(D_ETHER)
449: printf("clnp packet");
450: ENDDEBUG
451: schednetisr(NETISR_ISO);
452: inq = &clnlintrq;
453: break;
454: }
455: goto dropanyway;
456:
457: case LLC_XID:
458: case LLC_XID_P:
459: if(m->m_len < 6)
460: goto dropanyway;
461: l->llc_window = 0;
462: l->llc_fid = 9;
463: l->llc_class = 1;
464: l->llc_dsap = l->llc_ssap = 0;
465: /* Fall through to */
466: case LLC_TEST:
467: case LLC_TEST_P:
468: {
469: struct sockaddr sa;
470: register struct ether_header *eh2;
471: int i;
472: u_char c = l->llc_dsap;
473:
474: l->llc_dsap = l->llc_ssap;
475: l->llc_ssap = c;
476: if (m->m_flags & (M_BCAST | M_MCAST))
477: bcopy((caddr_t)ac->ac_enaddr,
478: (caddr_t)eh->ether_dhost, 6);
479: sa.sa_family = AF_UNSPEC;
480: sa.sa_len = sizeof(sa);
481: eh2 = (struct ether_header *)sa.sa_data;
482: for (i = 0; i < 6; i++) {
483: eh2->ether_shost[i] = c = eh->fddi_dhost[i];
484: eh2->ether_dhost[i] =
485: eh->ether_dhost[i] = eh->fddi_shost[i];
486: eh2->ether_shost[i] = c;
487: }
488: eh2->ether_type = 0;
489: ifp->if_output(ifp, m, &sa, NULL);
490: return;
491: }
492: default:
493: m_freem(m);
494: return;
495: }
496: break;
497: #endif /* defined(ISO) && notyet */
498: #if LLC
499: case LLC_X25_LSAP:
500: {
501: M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
502: if (m == 0)
503: return;
504: if ( !sdl_sethdrif(ifp, fh->fddi_shost, LLC_X25_LSAP,
505: fh->fddi_dhost, LLC_X25_LSAP, 6,
506: mtod(m, struct sdl_hdr *)))
507: panic("ETHER cons addr failure");
508: mtod(m, struct sdl_hdr *)->sdlhdr_len = m->m_pkthdr.len - sizeof(struct sdl_hdr);
509: #if LLC_DEBUG
510: printf("llc packet\n");
511: #endif /* LLC_DEBUG */
512: schednetisr(NETISR_CCITT);
513: inq = &llcintrq;
514: break;
515: }
516: #endif /* LLC */
517:
518: default:
519: printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap);
520: ifp->if_noproto++;
521: dropanyway:
522: m_freem(m);
523: return;
524: }
525:
526: s = splimp();
527: if (IF_QFULL(inq)) {
528: IF_DROP(inq);
529: m_freem(m);
530: } else
531: IF_ENQUEUE(inq, m);
532: splx(s);
533: }
534: /*
535: * Perform common duties while attaching to interface list
536: */
537: void
538: fddi_ifattach(ifp)
539: register struct ifnet *ifp;
540: {
541: register struct ifaddr *ifa;
542: register struct sockaddr_dl *sdl;
543:
544: ifp->if_type = IFT_FDDI;
545: ifp->if_addrlen = 6;
546: ifp->if_hdrlen = 21;
547: ifp->if_mtu = FDDIMTU;
548: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
549: if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
550: sdl->sdl_family == AF_LINK) {
551: sdl->sdl_type = IFT_FDDI;
552: sdl->sdl_alen = ifp->if_addrlen;
553: bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
554: LLADDR(sdl), ifp->if_addrlen);
555: break;
556: }
557: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.