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