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