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