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