|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*-
23: * Copyright (c) 1991, 1993
24: * The Regents of the University of California. All rights reserved.
25: *
26: * Redistribution and use in source and binary forms, with or without
27: * modification, are permitted provided that the following conditions
28: * are met:
29: * 1. Redistributions of source code must retain the above copyright
30: * notice, this list of conditions and the following disclaimer.
31: * 2. Redistributions in binary form must reproduce the above copyright
32: * notice, this list of conditions and the following disclaimer in the
33: * documentation and/or other materials provided with the distribution.
34: * 3. All advertising materials mentioning features or use of this software
35: * must display the following acknowledgement:
36: * This product includes software developed by the University of
37: * California, Berkeley and its contributors.
38: * 4. Neither the name of the University nor the names of its contributors
39: * may be used to endorse or promote products derived from this software
40: * without specific prior written permission.
41: *
42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52: * SUCH DAMAGE.
53: *
54: * @(#)if_eon.c 8.1 (Berkeley) 6/10/93
55: */
56:
57: /***********************************************************
58: Copyright IBM Corporation 1987
59:
60: All Rights Reserved
61:
62: Permission to use, copy, modify, and distribute this software and its
63: documentation for any purpose and without fee is hereby granted,
64: provided that the above copyright notice appear in all copies and that
65: both that copyright notice and this permission notice appear in
66: supporting documentation, and that the name of IBM not be
67: used in advertising or publicity pertaining to distribution of the
68: software without specific, written prior permission.
69:
70: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
71: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
72: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
73: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
74: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
75: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
76: SOFTWARE.
77:
78: ******************************************************************/
79:
80: /*
81: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
82: */
83: /*
84: * EON rfc
85: * Layer between IP and CLNL
86: *
87: * TODO:
88: * Put together a current rfc986 address format and get the right offset
89: * for the nsel
90: */
91:
92: #if EON
93: #define NEON 1
94:
95:
96: #include <sys/param.h>
97: #include <sys/systm.h>
98: #include <sys/mbuf.h>
99: #include <sys/buf.h>
100: #include <sys/protosw.h>
101: #include <sys/socket.h>
102: #include <sys/ioctl.h>
103: #include <sys/errno.h>
104: #include <sys/types.h>
105:
106: #include <net/if.h>
107: #include <net/if_types.h>
108: #include <net/if_dl.h>
109: #include <net/netisr.h>
110: #include <net/route.h>
111: #include <machine/mtpr.h>
112:
113: #include <netinet/in.h>
114: #include <netinet/in_systm.h>
115: #include <netinet/in_var.h>
116: #include <netinet/ip.h>
117: #include <netinet/ip_var.h>
118: #include <netinet/if_ether.h>
119:
120: #include <netiso/iso.h>
121: #include <netiso/iso_var.h>
122: #include <netiso/iso_snpac.h>
123: #include <netiso/argo_debug.h>
124: #include <netiso/iso_errno.h>
125: #include <netiso/eonvar.h>
126:
127: extern struct timeval time;
128: extern struct ifnet loif;
129:
130: #define EOK 0
131:
132: int eoninput();
133: int eonoutput();
134: int eonioctl();
135: int eonattach();
136: int eoninit();
137: void eonrtrequest();
138: struct ifnet eonif[1];
139:
140: eonprotoinit() {
141: (void) eonattach();
142: }
143:
144: struct eon_llinfo eon_llinfo;
145: #define PROBE_OK 0;
146:
147:
148: /*
149: * FUNCTION: eonattach
150: *
151: * PURPOSE: autoconf attach routine
152: *
153: * RETURNS: void
154: */
155:
156: eonattach()
157: {
158: register struct ifnet *ifp = eonif;
159:
160: IFDEBUG(D_EON)
161: printf("eonattach()\n");
162: ENDDEBUG
163: ifp->if_unit = 0;
164: ifp->if_name = "eon";
165: ifp->if_mtu = ETHERMTU;
166: /* since everything will go out over ether or token ring */
167:
168: ifp->if_init = eoninit;
169: ifp->if_ioctl = eonioctl;
170: ifp->if_output = eonoutput;
171: ifp->if_type = IFT_EON;
172: ifp->if_addrlen = 5;
173: ifp->if_hdrlen = EONIPLEN;
174: ifp->if_flags = IFF_BROADCAST;
175: if_attach(ifp);
176: eonioctl(ifp, SIOCSIFADDR, (caddr_t)ifp->if_addrlist);
177: eon_llinfo.el_qhdr.link =
178: eon_llinfo.el_qhdr.rlink = &(eon_llinfo.el_qhdr);
179:
180: IFDEBUG(D_EON)
181: printf("eonattach()\n");
182: ENDDEBUG
183: }
184:
185:
186: /*
187: * FUNCTION: eonioctl
188: *
189: * PURPOSE: io controls - ifconfig
190: * need commands to
191: * link-UP (core addr) (flags: ES, IS)
192: * link-DOWN (core addr) (flags: ES, IS)
193: * must be callable from kernel or user
194: *
195: * RETURNS: nothing
196: */
197: eonioctl(ifp, cmd, data)
198: register struct ifnet *ifp;
199: int cmd;
200: register caddr_t data;
201: {
202: int s = splimp();
203: register int error = 0;
204:
205: IFDEBUG(D_EON)
206: printf("eonioctl (cmd 0x%x) \n", cmd);
207: ENDDEBUG
208:
209: switch (cmd) {
210: register struct ifaddr *ifa;
211:
212: case SIOCSIFADDR:
213: if (ifa = (struct ifaddr *)data) {
214: ifp->if_flags |= IFF_UP;
215: if (ifa->ifa_addr->sa_family != AF_LINK)
216: ifa->ifa_rtrequest = eonrtrequest;
217: }
218: break;
219: }
220: splx(s);
221: return(error);
222: }
223:
224:
225: eoniphdr(hdr, loc, ro, class, zero)
226: struct route *ro;
227: register struct eon_iphdr *hdr;
228: caddr_t loc;
229: {
230: struct mbuf mhead;
231: register struct sockaddr_in *sin = (struct sockaddr_in *)&ro->ro_dst;
232: if (zero) {
233: bzero((caddr_t)hdr, sizeof (*hdr));
234: bzero((caddr_t)ro, sizeof (*ro));
235: }
236: sin->sin_family = AF_INET;
237: sin->sin_len = sizeof (*sin);
238: bcopy(loc, (caddr_t)&sin->sin_addr, sizeof(struct in_addr));
239: /*
240: * If there is a cached route,
241: * check that it is to the same destination
242: * and is still up. If not, free it and try again.
243: */
244: if (ro->ro_rt) {
245: struct sockaddr_in *dst =
246: (struct sockaddr_in *)rt_key(ro->ro_rt);
247: if ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
248: sin->sin_addr.s_addr != dst->sin_addr.s_addr) {
249: RTFREE(ro->ro_rt);
250: ro->ro_rt = (struct rtentry *)0;
251: }
252: }
253: rtalloc(ro);
254: if (ro->ro_rt)
255: ro->ro_rt->rt_use++;
256: hdr->ei_ip.ip_dst = sin->sin_addr;
257: hdr->ei_ip.ip_p = IPPROTO_EON;
258: hdr->ei_ip.ip_ttl = MAXTTL;
259: hdr->ei_eh.eonh_class = class;
260: hdr->ei_eh.eonh_vers = EON_VERSION;
261: hdr->ei_eh.eonh_csum = 0;
262: mhead.m_data = (caddr_t) &hdr->ei_eh;
263: mhead.m_len = sizeof(struct eon_hdr);
264: mhead.m_next = 0;
265: IFDEBUG(D_EON)
266: printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n",
267: &mhead,
268: _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
269: ENDDEBUG
270: iso_gen_csum(&mhead,
271: _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
272: }
273: /*
274: * FUNCTION: eonrtrequest
275: *
276: * PURPOSE: maintains list of direct eon recipients.
277: * sets up IP route for rest.
278: *
279: * RETURNS: nothing
280: */
281: void
282: eonrtrequest(cmd, rt, gate)
283: register struct rtentry *rt;
284: register struct sockaddr *gate;
285: {
286: unsigned long zerodst = 0;
287: caddr_t ipaddrloc = (caddr_t) &zerodst;
288: register struct eon_llinfo *el = (struct eon_llinfo *)rt->rt_llinfo;
289:
290: /*
291: * Common Housekeeping
292: */
293: switch (cmd) {
294: case RTM_DELETE:
295: if (el) {
296: remque(&(el->el_qhdr));
297: if (el->el_iproute.ro_rt)
298: RTFREE(el->el_iproute.ro_rt);
299: Free(el);
300: rt->rt_llinfo = 0;
301: }
302: return;
303:
304: case RTM_ADD:
305: case RTM_RESOLVE:
306: rt->rt_rmx.rmx_mtu = loif.if_mtu; /* unless better below */
307: R_Malloc(el, struct eon_llinfo *, sizeof(*el));
308: rt->rt_llinfo = (caddr_t)el;
309: if (el == 0)
310: return;
311: Bzero(el, sizeof(*el));
312: insque(&(el->el_qhdr), &eon_llinfo.el_qhdr);
313: el->el_rt = rt;
314: break;
315: }
316: if (gate || (gate = rt->rt_gateway)) switch (gate->sa_family) {
317: case AF_LINK:
318: #define SDL(x) ((struct sockaddr_dl *)x)
319: if (SDL(gate)->sdl_alen == 1)
320: el->el_snpaoffset = *(u_char *)LLADDR(SDL(gate));
321: else
322: ipaddrloc = LLADDR(SDL(gate));
323: break;
324: case AF_INET:
325: #define SIN(x) ((struct sockaddr_in *)x)
326: ipaddrloc = (caddr_t) &SIN(gate)->sin_addr;
327: break;
328: default:
329: return;
330: }
331: el->el_flags |= RTF_UP;
332: eoniphdr(&el->el_ei, ipaddrloc, &el->el_iproute, EON_NORMAL_ADDR, 0);
333: if (el->el_iproute.ro_rt)
334: rt->rt_rmx.rmx_mtu = el->el_iproute.ro_rt->rt_rmx.rmx_mtu
335: - sizeof(el->el_ei);
336: }
337:
338: /*
339: * FUNCTION: eoninit
340: *
341: * PURPOSE: initialization
342: *
343: * RETURNS: nothing
344: */
345:
346: eoninit(unit)
347: int unit;
348: {
349: printf("eon driver-init eon%d\n", unit);
350: }
351:
352:
353: /*
354: * FUNCTION: eonoutput
355: *
356: * PURPOSE: prepend an eon header and hand to IP
357: * ARGUMENTS: (ifp) is points to the ifnet structure for this unit/device
358: * (m) is an mbuf *, *m is a CLNL packet
359: * (dst) is a destination address - have to interp. as
360: * multicast or broadcast or real address.
361: *
362: * RETURNS: unix error code
363: *
364: * NOTES:
365: *
366: */
367: eonoutput(ifp, m, dst, rt)
368: struct ifnet *ifp;
369: register struct mbuf *m; /* packet */
370: struct sockaddr_iso *dst; /* destination addr */
371: struct rtentry *rt;
372: {
373: register struct eon_llinfo *el;
374: register struct eon_iphdr *ei;
375: struct route *ro;
376: int datalen;
377: struct mbuf *mh;
378: int error = 0, class = 0, alen = 0;
379: caddr_t ipaddrloc;
380: static struct eon_iphdr eon_iphdr;
381: static struct route route;
382:
383: IFDEBUG(D_EON)
384: printf("eonoutput \n" );
385: ENDDEBUG
386:
387: ifp->if_lastchange = time;
388: ifp->if_opackets++;
389: if (rt == 0 || (el = (struct eon_llinfo *)rt->rt_llinfo) == 0) {
390: if (dst->siso_family == AF_LINK) {
391: register struct sockaddr_dl *sdl = (struct sockaddr_dl *)dst;
392:
393: ipaddrloc = LLADDR(sdl);
394: alen = sdl->sdl_alen;
395: } else if (dst->siso_family == AF_ISO && dst->siso_data[0] == AFI_SNA) {
396: alen = dst->siso_nlen - 1;
397: ipaddrloc = (caddr_t) dst->siso_data + 1;
398: }
399: switch (alen) {
400: case 5:
401: class = 4[(u_char *)ipaddrloc];
402: case 4:
403: ro = &route;
404: ei = &eon_iphdr;
405: eoniphdr(ei, ipaddrloc, ro, class, 1);
406: goto send;
407: }
408: einval:
409: error = EINVAL;
410: goto flush;
411: }
412: if ((el->el_flags & RTF_UP) == 0) {
413: eonrtrequest(RTM_CHANGE, rt, (struct sockaddr *)0);
414: if ((el->el_flags & RTF_UP) == 0) {
415: error = EHOSTUNREACH;
416: goto flush;
417: }
418: }
419: if ((m->m_flags & M_PKTHDR) == 0) {
420: printf("eon: got non headered packet\n");
421: goto einval;
422: }
423: ei = &el->el_ei;
424: ro = &el->el_iproute;
425: if (el->el_snpaoffset) {
426: if (dst->siso_family == AF_ISO) {
427: bcopy((caddr_t) &dst->siso_data[el->el_snpaoffset],
428: (caddr_t) &ei->ei_ip.ip_dst, sizeof(ei->ei_ip.ip_dst));
429: } else
430: goto einval;
431: }
432: send:
433: /* put an eon_hdr in the buffer, prepended by an ip header */
434: datalen = m->m_pkthdr.len + EONIPLEN;
435: MGETHDR(mh, M_DONTWAIT, MT_HEADER);
436: if(mh == (struct mbuf *)0)
437: goto flush;
438: mh->m_next = m;
439: m = mh;
440: MH_ALIGN(m, sizeof(struct eon_iphdr));
441: m->m_len = sizeof(struct eon_iphdr);
442: ifp->if_obytes +=
443: (ei->ei_ip.ip_len = (u_short)(m->m_pkthdr.len = datalen));
444: *mtod(m, struct eon_iphdr *) = *ei;
445:
446: IFDEBUG(D_EON)
447: printf("eonoutput dst ip addr : %x\n", ei->ei_ip.ip_dst.s_addr);
448: printf("eonoutput ip_output : eonip header:\n");
449: dump_buf(ei, sizeof(struct eon_iphdr));
450: ENDDEBUG
451:
452: error = ip_output(m, (struct mbuf *)0, ro, 0, NULL);
453: m = 0;
454: if (error) {
455: ifp->if_oerrors++;
456: ifp->if_opackets--;
457: ifp->if_obytes -= datalen;
458: }
459: flush:
460: if (m)
461: m_freem(m);
462: return error;
463: }
464:
465: eoninput(m, iphlen)
466: register struct mbuf *m;
467: int iphlen;
468: {
469: register struct eon_hdr *eonhdr;
470: register struct ip *iphdr;
471: struct ifnet *eonifp;
472: int s;
473:
474: eonifp = &eonif[0]; /* kludge - really want to give CLNP
475: * the ifp for eon, not for the real device
476: */
477:
478: IFDEBUG(D_EON)
479: printf("eoninput() 0x%x m_data 0x%x m_len 0x%x dequeued\n",
480: m, m?m->m_data:0, m?m->m_len:0);
481: ENDDEBUG
482:
483: if (m == 0)
484: return;
485: if (iphlen > sizeof (struct ip))
486: ip_stripoptions(m, (struct mbuf *)0);
487: if (m->m_len < EONIPLEN) {
488: if ((m = m_pullup(m, EONIPLEN)) == 0) {
489: IncStat(es_badhdr);
490: drop:
491: IFDEBUG(D_EON)
492: printf("eoninput: DROP \n" );
493: ENDDEBUG
494: eonifp->if_ierrors ++;
495: m_freem(m);
496: return;
497: }
498: }
499: eonif->if_ibytes += m->m_pkthdr.len;
500: eonif->if_lastchange = time;
501: iphdr = mtod(m, struct ip *);
502: /* do a few checks for debugging */
503: if( iphdr->ip_p != IPPROTO_EON ) {
504: IncStat(es_badhdr);
505: goto drop;
506: }
507: /* temporarily drop ip header from the mbuf */
508: m->m_data += sizeof(struct ip);
509: eonhdr = mtod(m, struct eon_hdr *);
510: if( iso_check_csum( m, sizeof(struct eon_hdr) ) != EOK ) {
511: IncStat(es_badcsum);
512: goto drop;
513: }
514: m->m_data -= sizeof(struct ip);
515:
516: IFDEBUG(D_EON)
517: printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class );
518: printf("eoninput: eon header:\n");
519: dump_buf(eonhdr, sizeof(struct eon_hdr));
520: ENDDEBUG
521:
522: /* checks for debugging */
523: if( eonhdr->eonh_vers != EON_VERSION) {
524: IncStat(es_badhdr);
525: goto drop;
526: }
527: m->m_flags &= ~(M_BCAST|M_MCAST);
528: switch( eonhdr->eonh_class) {
529: case EON_BROADCAST:
530: IncStat(es_in_broad);
531: m->m_flags |= M_BCAST;
532: break;
533: case EON_NORMAL_ADDR:
534: IncStat(es_in_normal);
535: break;
536: case EON_MULTICAST_ES:
537: IncStat(es_in_multi_es);
538: m->m_flags |= M_MCAST;
539: break;
540: case EON_MULTICAST_IS:
541: IncStat(es_in_multi_is);
542: m->m_flags |= M_MCAST;
543: break;
544: }
545: eonifp->if_ipackets++;
546:
547: {
548: /* put it on the CLNP queue and set soft interrupt */
549: struct ifqueue *ifq;
550: extern struct ifqueue clnlintrq;
551:
552: m->m_pkthdr.rcvif = eonifp; /* KLUDGE */
553: IFDEBUG(D_EON)
554: printf("eoninput to clnl IFQ\n");
555: ENDDEBUG
556: ifq = &clnlintrq;
557: s = splimp();
558: if (IF_QFULL(ifq)) {
559: IF_DROP(ifq);
560: m_freem(m);
561: eonifp->if_iqdrops++;
562: eonifp->if_ipackets--;
563: splx(s);
564: return;
565: }
566: IF_ENQUEUE(ifq, m);
567: IFDEBUG(D_EON)
568: printf(
569: "0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data 0x%x\n",
570: m, m->m_len, m->m_type, m->m_data);
571: dump_buf(mtod(m, caddr_t), m->m_len);
572: ENDDEBUG
573: schednetisr(NETISR_ISO);
574: splx(s);
575: }
576: }
577:
578: int
579: eonctlinput(cmd, sin)
580: int cmd;
581: struct sockaddr_in *sin;
582: {
583: extern u_char inetctlerrmap[];
584:
585: IFDEBUG(D_EON)
586: printf("eonctlinput: cmd 0x%x addr: ", cmd);
587: dump_isoaddr(sin);
588: printf("\n");
589: ENDDEBUG
590:
591: if (cmd < 0 || cmd > PRC_NCMDS)
592: return 0;
593:
594: IncStat(es_icmp[cmd]);
595: switch (cmd) {
596:
597: case PRC_QUENCH:
598: case PRC_QUENCH2:
599: /* TODO: set the dec bit */
600: break;
601: case PRC_TIMXCEED_REASS:
602: case PRC_ROUTEDEAD:
603: case PRC_HOSTUNREACH:
604: case PRC_UNREACH_NET:
605: case PRC_IFDOWN:
606: case PRC_UNREACH_HOST:
607: case PRC_HOSTDEAD:
608: case PRC_TIMXCEED_INTRANS:
609: /* TODO: mark the link down */
610: break;
611:
612: case PRC_UNREACH_PROTOCOL:
613: case PRC_UNREACH_PORT:
614: case PRC_UNREACH_SRCFAIL:
615: case PRC_REDIRECT_NET:
616: case PRC_REDIRECT_HOST:
617: case PRC_REDIRECT_TOSNET:
618: case PRC_REDIRECT_TOSHOST:
619: case PRC_MSGSIZE:
620: case PRC_PARAMPROB:
621: /* printf("eonctlinput: ICMP cmd 0x%x\n", cmd );*/
622: break;
623: }
624: return 0;
625: }
626:
627: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.